Initial revision
[chise/xemacs-chise.git.1] / lisp / faces.el
1 ;;; faces.el --- Lisp interface to the C "face" structure
2
3 ;; Copyright (C) 1992-4, 1997 Free Software Foundation, Inc.
4 ;; Copyright (C) 1995 Board of Trustees, University of Illinois
5 ;; Copyright (C) 1995, 1996 Ben Wing
6
7 ;; Author: Ben Wing <ben@xemacs.org>
8 ;; Keywords: faces, internal, dumped
9
10 ;; This file is part of XEmacs.
11
12 ;; XEmacs is free software; you can redistribute it and/or modify it
13 ;; under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation; either version 2, or (at your option)
15 ;; any later version.
16
17 ;; XEmacs is distributed in the hope that it will be useful, but
18 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20 ;; General Public License for more details.
21
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with XEmacs; see the file COPYING.  If not, write to the
24 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25 ;; Boston, MA 02111-1307, USA.
26
27 ;;; Synched up with: Not synched with FSF.  Almost completely divergent.
28
29 ;;; Commentary:
30
31 ;; This file is dumped with XEmacs.
32
33 ;; face implementation #1 (used Lisp vectors and parallel C vectors;
34 ;; FSFmacs still uses this) authored by Jamie Zawinski <jwz@jwz.org>
35 ;; pre Lucid-Emacs 19.0.
36
37 ;; face implementation #2 (used one face object per frame per face)
38 ;; authored by Jamie Zawinski for 19.9.
39
40 ;; face implementation #3 (use one face object per face) originally
41 ;; authored for 19.12 by Chuck Thompson <cthomp@cs.uiuc.edu>,
42 ;; rewritten by Ben Wing with the advent of specifiers.
43
44
45 ;;; Some stuff in FSF's faces.el is in our x-faces.el.
46
47 ;;; Code:
48
49 (defgroup faces nil
50   "Support for multiple text attributes (fonts, colors, ...)
51 Such a collection of attributes is called a \"face\"."
52   :group 'emacs)
53
54
55 (defun read-face-name (prompt)
56   (let (face)
57     (while (= (length face) 0) ; nil or ""
58       (setq face (completing-read prompt
59                                   (mapcar (lambda (x) (list (symbol-name x)))
60                                           (face-list))
61                                   nil t)))
62     (intern face)))
63
64 (defun face-interactive (what &optional bool)
65   (let* ((fn (intern (concat "face-" what "-instance")))
66          (face (read-face-name (format "Set %s of face: " what)))
67          (default (if (fboundp fn)
68                       ;; #### we should distinguish here between
69                       ;; explicitly setting the value to be the
70                       ;; same as the default face's value, and
71                       ;; not setting a value at all.
72                       (funcall fn face)))
73          (value (if bool
74                     (y-or-n-p (format "Should face %s be %s? "
75                                       (symbol-name face) bool))
76                   (read-string (format "Set %s of face %s to: "
77                                        what (symbol-name face))
78                    (cond ((font-instance-p default)
79                           (font-instance-name default))
80                          ((color-instance-p default)
81                           (color-instance-name default))
82                          ((image-instance-p default)
83                           (image-instance-file-name default))
84                          (t default))))))
85     (list face (if (equal value "") nil value))))
86
87 (defconst built-in-face-specifiers
88   (built-in-face-specifiers)
89   "A list of the built-in face properties that are specifiers.")
90
91 (defun face-property (face property &optional locale tag-set exact-p)
92   "Return FACE's value of the given PROPERTY.
93
94 If LOCALE is omitted, the FACE's actual value for PROPERTY will be
95   returned.  For built-in properties, this will be a specifier object
96   of a type appropriate to the property (e.g. a font or color
97   specifier).  For other properties, this could be anything.
98
99 If LOCALE is supplied, then instead of returning the actual value,
100   the specification(s) for the given locale or locale type will
101   be returned.  This will only work if the actual value of
102   PROPERTY is a specifier (this will always be the case for built-in
103   properties, but not or not may apply to user-defined properties).
104   If the actual value of PROPERTY is not a specifier, this value
105   will simply be returned regardless of LOCALE.
106
107 The return value will be a list of instantiators (e.g. strings
108   specifying a font or color name), or a list of specifications, each
109   of which is a cons of a locale and a list of instantiators.
110   Specifically, if LOCALE is a particular locale (a buffer, window,
111   frame, device, or 'global), a list of instantiators for that locale
112   will be returned.  Otherwise, if LOCALE is a locale type (one of
113   the symbols 'buffer, 'window, 'frame, or 'device), the specifications
114   for all locales of that type will be returned.  Finally, if LOCALE is
115   'all, the specifications for all locales of all types will be returned.
116
117 The specifications in a specifier determine what the value of
118   PROPERTY will be in a particular \"domain\" or set of circumstances,
119   which is typically a particular Emacs window along with the buffer
120   it contains and the frame and device it lies within.  The value is
121   derived from the instantiator associated with the most specific
122   locale (in the order buffer, window, frame, device, and 'global)
123   that matches the domain in question.  In other words, given a domain
124   (i.e. an Emacs window, usually), the specifier for PROPERTY will
125   first be searched for a specification whose locale is the buffer
126   contained within that window; then for a specification whose locale
127   is the window itself; then for a specification whose locale is the
128   frame that the window is contained within; etc.  The first
129   instantiator that is valid for the domain (usually this means that
130   the instantiator is recognized by the device [i.e. MS Windows, the X
131   server or TTY device] that the domain is on.  The function
132   `face-property-instance' actually does all this, and is used to
133   determine how to display the face.
134
135 See `set-face-property' for the built-in property-names."
136
137   (setq face (get-face face))
138   (let ((value (get face property)))
139     (if (and locale
140              (or (memq property built-in-face-specifiers)
141                  (specifierp value)))
142         (setq value (specifier-specs value locale tag-set exact-p)))
143     value))
144
145 (defun convert-face-property-into-specifier (face property)
146   "Convert PROPERTY on FACE into a specifier, if it's not already."
147   (setq face (get-face face))
148   (let ((specifier (get face property)))
149     ;; if a user-property does not have a specifier but a
150     ;; locale was specified, put a specifier there.
151     ;; If there was already a value there, convert it to a
152     ;; specifier with the value as its 'global instantiator.
153     (unless (specifierp specifier)
154       (let ((new-specifier (make-specifier 'generic)))
155         (if (or (not (null specifier))
156                 ;; make sure the nil returned from `get' wasn't
157                 ;; actually the value of the property
158                 (null (get face property t)))
159             (add-spec-to-specifier new-specifier specifier))
160         (setq specifier new-specifier)
161         (put face property specifier)))))
162
163 (defun face-property-instance (face property
164                                     &optional domain default no-fallback)
165   "Return the instance of FACE's PROPERTY in the specified DOMAIN.
166
167 Under most circumstances, DOMAIN will be a particular window,
168   and the returned instance describes how the specified property
169   actually is displayed for that window and the particular buffer
170   in it.  Note that this may not be the same as how the property
171   appears when the buffer is displayed in a different window or
172   frame, or how the property appears in the same window if you
173   switch to another buffer in that window; and in those cases,
174   the returned instance would be different.
175
176 The returned instance will typically be a color-instance,
177   font-instance, or pixmap-instance object, and you can query
178   it using the appropriate object-specific functions.  For example,
179   you could use `color-instance-rgb-components' to find out the
180   RGB (red, green, and blue) components of how the 'background
181   property of the 'highlight face is displayed in a particular
182   window.  The results might be different from the results
183   you would get for another window (perhaps the user
184   specified a different color for the frame that window is on;
185   or perhaps the same color was specified but the window is
186   on a different X server, and that X server has different RGB
187   values for the color from this one).
188
189 DOMAIN defaults to the selected window if omitted.
190
191 DOMAIN can be a frame or device, instead of a window.  The value
192   returned for a such a domain is used in special circumstances
193   when a more specific domain does not apply; for example, a frame
194   value might be used for coloring a toolbar, which is conceptually
195   attached to a frame rather than a particular window.  The value
196   is also useful in determining what the value would be for a
197   particular window within the frame or device, if it is not
198   overridden by a more specific specification.
199
200 If PROPERTY does not name a built-in property, its value will
201   simply be returned unless it is a specifier object, in which case
202   it will be instanced using `specifier-instance'.
203
204 Optional arguments DEFAULT and NO-FALLBACK are the same as in
205   `specifier-instance'."
206
207   (setq face (get-face face))
208   (let ((value (get face property)))
209     (if (specifierp value)
210         (setq value (specifier-instance value domain default no-fallback)))
211     value))
212
213 (defun face-property-matching-instance (face property matchspec
214                                              &optional domain default
215                                              no-fallback)
216   "Return the instance of FACE's PROPERTY matching MATCHSPEC in DOMAIN.
217 Currently the only useful value for MATCHSPEC is a charset, when used
218 in conjunction with the face's font; this allows you to retrieve a
219 font that can be used to display a particular charset, rather than just
220 any font.
221
222 Other than MATCHSPEC, this function is identical to `face-property-instance'.
223 See also `specifier-matching-instance' for a fuller description of the
224 matching process."
225
226   (setq face (get-face face))
227   (let ((value (get face property)))
228     (if (specifierp value)
229         (setq value (specifier-matching-instance value matchspec domain
230                                                  default no-fallback)))
231     value))
232
233 (defun set-face-property (face property value &optional locale tag-set
234                                how-to-add)
235   "Change a property of FACE.
236
237 NOTE: If you want to remove a property from a face, use `remove-face-property'
238   rather than attempting to set a value of nil for the property.
239
240 For built-in properties, the actual value of the property is a
241   specifier and you cannot change this; but you can change the
242   specifications within the specifier, and that is what this function
243   will do.  For user-defined properties, you can use this function
244   to either change the actual value of the property or, if this value
245   is a specifier, change the specifications within it.
246
247 If PROPERTY is a built-in property, the specifications to be added to
248   this property can be supplied in many different ways:
249
250   -- If VALUE is a simple instantiator (e.g. a string naming a font or
251      color) or a list of instantiators, then the instantiator(s) will
252      be added as a specification of the property for the given LOCALE
253      (which defaults to 'global if omitted).
254   -- If VALUE is a list of specifications (each of which is a cons of
255      a locale and a list of instantiators), then LOCALE must be nil
256      (it does not make sense to explicitly specify a locale in this
257      case), and specifications will be added as given.
258   -- If VALUE is a specifier (as would be returned by `face-property'
259      if no LOCALE argument is given), then some or all of the
260      specifications in the specifier will be added to the property.
261      In this case, the function is really equivalent to
262      `copy-specifier' and LOCALE has the same semantics (if it is
263      a particular locale, the specification for the locale will be
264      copied; if a locale type, specifications for all locales of
265      that type will be copied; if nil or 'all, then all
266      specifications will be copied).
267
268 HOW-TO-ADD should be either nil or one of the symbols 'prepend,
269   'append, 'remove-tag-set-prepend, 'remove-tag-set-append, 'remove-locale,
270   'remove-locale-type, or 'remove-all.  See `copy-specifier' and
271   `add-spec-to-specifier' for a description of what each of
272   these means.  Most of the time, you do not need to worry about
273   this argument; the default behavior usually is fine.
274
275 In general, it is OK to pass an instance object (e.g. as returned
276   by `face-property-instance') as an instantiator in place of
277   an actual instantiator.  In such a case, the instantiator used
278   to create that instance object will be used (for example, if
279   you set a font-instance object as the value of the 'font
280   property, then the font name used to create that object will
281   be used instead).  If some cases, however, doing this
282   conversion does not make sense, and this will be noted in
283   the documentation for particular types of instance objects.
284
285 If PROPERTY is not a built-in property, then this function will
286   simply set its value if LOCALE is nil.  However, if LOCALE is
287   given, then this function will attempt to add VALUE as the
288   instantiator for the given LOCALE, using `add-spec-to-specifier'.
289   If the value of the property is not a specifier, it will
290   automatically be converted into a 'generic specifier.
291
292
293 The following symbols have predefined meanings:
294
295  foreground         The foreground color of the face.
296                     For valid instantiators, see `make-color-specifier'.
297
298  background         The background color of the face.
299                     For valid instantiators, see `make-color-specifier'.
300
301  font               The font used to display text covered by this face.
302                     For valid instantiators, see `make-font-specifier'.
303
304  display-table      The display table of the face.
305                     This should be a vector of 256 elements.
306
307  background-pixmap  The pixmap displayed in the background of the face.
308                     Only used by faces on X and MS Windows devices.
309                     For valid instantiators, see `make-image-specifier'.
310
311  underline          Underline all text covered by this face.
312                     For valid instantiators, see `make-face-boolean-specifier'.
313
314  strikethru         Draw a line through all text covered by this face.
315                     For valid instantiators, see `make-face-boolean-specifier'.
316
317  highlight          Highlight all text covered by this face.
318                     Only used by faces on TTY devices.
319                     For valid instantiators, see `make-face-boolean-specifier'.
320
321  dim                Dim all text covered by this face.
322                     For valid instantiators, see `make-face-boolean-specifier'.
323
324  blinking           Blink all text covered by this face.
325                     Only used by faces on TTY devices.
326                     For valid instantiators, see `make-face-boolean-specifier'.
327
328  reverse            Reverse the foreground and background colors.
329                     Only used by faces on TTY devices.
330                     For valid instantiators, see `make-face-boolean-specifier'.
331
332  doc-string         Description of what the face's normal use is.
333                     NOTE: This is not a specifier, unlike all
334                     the other built-in properties, and cannot
335                     contain locale-specific values."
336
337   (setq face (get-face face))
338   (if (memq property built-in-face-specifiers)
339       (set-specifier (get face property) value locale tag-set how-to-add)
340
341     ;; This section adds user defined properties.
342     (if (not locale)
343         (put face property value)
344       (convert-face-property-into-specifier face property)
345       (add-spec-to-specifier (get face property) value locale tag-set
346                              how-to-add)))
347   value)
348
349 (defun remove-face-property (face property &optional locale tag-set exact-p)
350   "Remove a property from FACE.
351 For built-in properties, this is analogous to `remove-specifier'.
352 See `remove-specifier' for the meaning of the LOCALE, TAG-SET, and EXACT-P
353 arguments."
354   (or locale (setq locale 'all))
355   (if (memq property built-in-face-specifiers)
356       (remove-specifier (face-property face property) locale tag-set exact-p)
357     (if (eq locale 'all)
358         (remprop (get-face face) property)
359       (convert-face-property-into-specifier face property)
360       (remove-specifier (face-property face property) locale tag-set
361                         exact-p))))
362
363 (defun reset-face (face &optional locale tag-set exact-p)
364   "Clear all existing built-in specifications from FACE.
365 This makes FACE inherit all its display properties from 'default.
366 WARNING: Be absolutely sure you want to do this!!!  It is a dangerous
367 operation and is not undoable.
368
369 The arguments LOCALE, TAG-SET and EXACT-P are the same as for
370 `remove-specifier'."
371   (mapc (lambda (x)
372           (remove-specifier (face-property face x) locale tag-set exact-p))
373         built-in-face-specifiers)
374   nil)
375
376 (defun set-face-parent (face parent &optional locale tag-set how-to-add)
377   "Set the parent of FACE to PARENT, for all properties.
378 This makes all properties of FACE inherit from PARENT."
379   (setq parent (get-face parent))
380   (mapcar (lambda (x)
381             (set-face-property face x (vector parent) locale tag-set
382                                how-to-add))
383           (delq 'display-table
384                 (delq 'background-pixmap
385                       (copy-sequence built-in-face-specifiers))))
386   (set-face-background-pixmap face (vector 'inherit ':face parent)
387                               locale tag-set how-to-add)
388   nil)
389
390 (defun face-doc-string (face)
391   "Return the documentation string for FACE."
392   (face-property face 'doc-string))
393
394 (defun set-face-doc-string (face doc-string)
395   "Change the documentation string of FACE to DOC-STRING."
396   (interactive (face-interactive "doc-string"))
397   (set-face-property face 'doc-string doc-string))
398
399 (defun face-font-name (face &optional domain charset)
400   "Return the font name of FACE in DOMAIN, or nil if it is unspecified.
401 DOMAIN is as in `face-font-instance'."
402   (let ((f (face-font-instance face domain charset)))
403     (and f (font-instance-name f))))
404
405 (defun face-font (face &optional locale tag-set exact-p)
406   "Return the font of FACE in LOCALE, or nil if it is unspecified.
407
408 FACE may be either a face object or a symbol representing a face.
409
410 LOCALE may be a locale (the instantiators for that particular locale
411   will be returned), a locale type (the specifications for all locales
412   of that type will be returned), 'all (all specifications will be
413   returned), or nil (the actual specifier object will be returned).
414
415 See `face-property' for more information."
416   (face-property face 'font locale tag-set exact-p))
417
418 (defun face-font-instance (face &optional domain charset)
419   "Return the instance of FACE's font in DOMAIN.
420
421 FACE may be either a face object or a symbol representing a face.
422
423 Normally DOMAIN will be a window or nil (meaning the selected window),
424   and an instance object describing how the font appears in that
425   particular window and buffer will be returned.
426
427 See `face-property-instance' for more information."
428   (if charset
429       (face-property-matching-instance face 'font charset domain)
430     (face-property-instance face 'font domain)))
431
432 (defun set-face-font (face font &optional locale tag-set how-to-add)
433   "Change the font of FACE to FONT in LOCALE.
434
435 FACE may be either a face object or a symbol representing a face.
436
437 FONT should be an instantiator (see `make-font-specifier'), a list of
438   instantiators, an alist of specifications (each mapping a
439   locale to an instantiator list), or a font specifier object.
440
441 If FONT is an alist, LOCALE must be omitted.  If FONT is a
442   specifier object, LOCALE can be a locale, a locale type, 'all,
443   or nil; see `copy-specifier' for its semantics.  Otherwise LOCALE
444   specifies the locale under which the specified instantiator(s)
445   will be added, and defaults to 'global.
446
447 See `set-face-property' for more information."
448   (interactive (face-interactive "font"))
449   (set-face-property face 'font font locale tag-set how-to-add))
450
451 (defun face-foreground (face &optional locale tag-set exact-p)
452   "Return the foreground of FACE in LOCALE, or nil if it is unspecified.
453
454 FACE may be either a face object or a symbol representing a face.
455
456 LOCALE may be a locale (the instantiators for that particular locale
457   will be returned), a locale type (the specifications for all locales
458   of that type will be returned), 'all (all specifications will be
459   returned), or nil (the actual specifier object will be returned).
460
461 See `face-property' for more information."
462   (face-property face 'foreground locale tag-set exact-p))
463
464 (defun face-foreground-instance (face &optional domain default no-fallback)
465   "Return the instance of FACE's foreground in DOMAIN.
466
467 FACE may be either a face object or a symbol representing a face.
468
469 Normally DOMAIN will be a window or nil (meaning the selected window),
470   and an instance object describing how the foreground appears in that
471   particular window and buffer will be returned.
472
473 See `face-property-instance' for more information."
474   (face-property-instance face 'foreground domain default no-fallback))
475
476 (defun face-foreground-name (face &optional domain default no-fallback)
477   "Return the name of FACE's foreground color in DOMAIN.
478
479 FACE may be either a face object or a symbol representing a face.
480
481 Normally DOMAIN will be a window or nil (meaning the selected window),
482   and an instance object describing how the background appears in that
483   particular window and buffer will be returned.
484
485 See `face-property-instance' for more information."
486   (color-instance-name (face-foreground-instance
487                         face domain default no-fallback)))
488
489 (defun set-face-foreground (face color &optional locale tag-set how-to-add)
490   "Change the foreground color of FACE to COLOR in LOCALE.
491
492 FACE may be either a face object or a symbol representing a face.
493
494 COLOR should be an instantiator (see `make-color-specifier'), a list of
495   instantiators, an alist of specifications (each mapping a locale to
496   an instantiator list), or a color specifier object.
497
498 If COLOR is an alist, LOCALE must be omitted.  If COLOR is a
499   specifier object, LOCALE can be a locale, a locale type, 'all,
500   or nil; see `copy-specifier' for its semantics.  Otherwise LOCALE
501   specifies the locale under which the specified instantiator(s)
502   will be added, and defaults to 'global.
503
504 See `set-face-property' for more information."
505   (interactive (face-interactive "foreground"))
506   (set-face-property face 'foreground color locale tag-set how-to-add))
507
508 (defun face-background (face &optional locale tag-set exact-p)
509   "Return the background color of FACE in LOCALE, or nil if it is unspecified.
510
511 FACE may be either a face object or a symbol representing a face.
512
513 LOCALE may be a locale (the instantiators for that particular locale
514   will be returned), a locale type (the specifications for all locales
515   of that type will be returned), 'all (all specifications will be
516   returned), or nil (the actual specifier object will be returned).
517
518 See `face-property' for more information."
519   (face-property face 'background locale tag-set exact-p))
520
521 (defun face-background-instance (face &optional domain default no-fallback)
522   "Return the instance of FACE's background in DOMAIN.
523
524 FACE may be either a face object or a symbol representing a face.
525
526 Normally DOMAIN will be a window or nil (meaning the selected window),
527   and an instance object describing how the background appears in that
528   particular window and buffer will be returned.
529
530 See `face-property-instance' for more information."
531   (face-property-instance face 'background domain default no-fallback))
532
533 (defun face-background-name (face &optional domain default no-fallback)
534   "Return the name of FACE's background color in DOMAIN.
535
536 FACE may be either a face object or a symbol representing a face.
537
538 Normally DOMAIN will be a window or nil (meaning the selected window),
539   and an instance object describing how the background appears in that
540   particular window and buffer will be returned.
541
542 See `face-property-instance' for more information."
543   (color-instance-name (face-background-instance
544                         face domain default no-fallback)))
545
546 (defun set-face-background (face color &optional locale tag-set how-to-add)
547   "Change the background color of FACE to COLOR in LOCALE.
548
549 FACE may be either a face object or a symbol representing a face.
550
551 COLOR should be an instantiator (see `make-color-specifier'), a list of
552   instantiators, an alist of specifications (each mapping a locale to
553   an instantiator list), or a color specifier object.
554
555 If COLOR is an alist, LOCALE must be omitted.  If COLOR is a
556   specifier object, LOCALE can be a locale, a locale type, 'all,
557   or nil; see `copy-specifier' for its semantics.  Otherwise LOCALE
558   specifies the locale under which the specified instantiator(s)
559   will be added, and defaults to 'global.
560
561 See `set-face-property' for more information."
562   (interactive (face-interactive "background"))
563   (set-face-property face 'background color locale tag-set how-to-add))
564
565 (defun face-background-pixmap (face &optional locale tag-set exact-p)
566   "Return the background pixmap of FACE in LOCALE, or nil if it is unspecified.
567 This property is only used on window system devices.
568
569 FACE may be either a face object or a symbol representing a face.
570
571 LOCALE may be a locale (the instantiators for that particular locale
572   will be returned), a locale type (the specifications for all locales
573   of that type will be returned), 'all (all specifications will be
574   returned), or nil (the actual specifier object will be returned).
575
576 See `face-property' for more information."
577   (face-property face 'background-pixmap locale tag-set exact-p))
578
579 (defun face-background-pixmap-instance (face &optional domain default
580                                              no-fallback)
581   "Return the instance of FACE's background pixmap in DOMAIN.
582
583 FACE may be either a face object or a symbol representing a face.
584
585 Normally DOMAIN will be a window or nil (meaning the selected window),
586   and an instance object describing how the background appears in that
587   particular window and buffer will be returned.
588
589 See `face-property-instance' for more information."
590   (face-property-instance face 'background-pixmap domain default no-fallback))
591
592 (defun set-face-background-pixmap (face pixmap &optional locale tag-set
593                                         how-to-add)
594   "Change the background pixmap of FACE to PIXMAP in LOCALE.
595 This property is only used on window system devices.
596
597 FACE may be either a face object or a symbol representing a face.
598
599 PIXMAP should be an instantiator (see `make-image-specifier'), a list
600   of instantiators, an alist of specifications (each mapping a locale
601   to an instantiator list), or an image specifier object.
602
603 If PIXMAP is an alist, LOCALE must be omitted.  If PIXMAP is a
604   specifier object, LOCALE can be a locale, a locale type, 'all,
605   or nil; see `copy-specifier' for its semantics.  Otherwise LOCALE
606   specifies the locale under which the specified instantiator(s)
607   will be added, and defaults to 'global.
608
609 See `set-face-property' for more information."
610   (interactive (face-interactive "background-pixmap"))
611   (set-face-property face 'background-pixmap pixmap locale tag-set how-to-add))
612
613 (defun face-display-table (face &optional locale tag-set exact-p)
614   "Return the display table of FACE in LOCALE.
615
616 A vector (as returned by `make-display-table') will be returned.
617
618 LOCALE may be a locale (the instantiators for that particular locale
619   will be returned), a locale type (the specifications for all locales
620   of that type will be returned), 'all (all specifications will be
621   returned), or nil (the actual specifier object will be returned).
622
623 See `face-property' for more information."
624   (face-property face 'display-table locale tag-set exact-p))
625
626 (defun face-display-table-instance (face &optional domain default no-fallback)
627   "Return the instance of FACE's display table in DOMAIN.
628 A vector (as returned by `make-display-table') will be returned.
629
630 See `face-property-instance' for the semantics of the DOMAIN argument."
631   (face-property-instance face 'display-table domain default no-fallback))
632
633 (defun set-face-display-table (face display-table &optional locale tag-set
634                                     how-to-add)
635   "Change the display table of FACE to DISPLAY-TABLE in LOCALE.
636 DISPLAY-TABLE should be a vector as returned by `make-display-table'.
637
638 See `set-face-property' for the semantics of the LOCALE, TAG-SET, and
639   HOW-TO-ADD arguments."
640   (interactive (face-interactive "display-table"))
641   (set-face-property face 'display-table display-table locale tag-set
642                      how-to-add))
643
644 ;; The following accessors and mutators are, IMHO, good
645 ;; implementation.  Cf. with `make-face-bold'.
646
647 (defun face-underline-p (face &optional domain default no-fallback)
648   "Return t if FACE is underlined in DOMAIN.
649 See `face-property-instance' for the semantics of the DOMAIN argument."
650   (face-property-instance face 'underline domain default no-fallback))
651
652 (defun set-face-underline-p (face underline-p &optional locale tag-set
653                                   how-to-add)
654   "Change the underline property of FACE to UNDERLINE-P.
655 UNDERLINE-P is normally a face-boolean instantiator; see
656  `make-face-boolean-specifier'.
657 See `set-face-property' for the semantics of the LOCALE, TAG-SET, and
658  HOW-TO-ADD arguments."
659   (interactive (face-interactive "underline-p" "underlined"))
660   (set-face-property face 'underline underline-p locale tag-set how-to-add))
661
662 (defun face-strikethru-p (face &optional domain default no-fallback)
663   "Return t if FACE is strikethru-d (i.e. struck through) in DOMAIN.
664 See `face-property-instance' for the semantics of the DOMAIN argument."
665   (face-property-instance face 'strikethru domain default no-fallback))
666
667 (defun set-face-strikethru-p (face strikethru-p &optional locale tag-set
668                                   how-to-add)
669   "Change whether FACE is strikethru-d (i.e. struck through) in LOCALE.
670 STRIKETHRU-P is normally a face-boolean instantiator; see
671  `make-face-boolean-specifier'.
672 See `set-face-property' for the semantics of the LOCALE, TAG-SET, and
673  HOW-TO-ADD arguments."
674   (interactive (face-interactive "strikethru-p" "strikethru-d"))
675   (set-face-property face 'strikethru strikethru-p locale tag-set how-to-add))
676
677 (defun face-highlight-p (face &optional domain default no-fallback)
678   "Return t if FACE is highlighted in DOMAIN (TTY domains only).
679 See `face-property-instance' for the semantics of the DOMAIN argument."
680   (face-property-instance face 'highlight domain default no-fallback))
681
682 (defun set-face-highlight-p (face highlight-p &optional locale tag-set
683                                   how-to-add)
684   "Change whether FACE is highlighted in LOCALE (TTY locales only).
685 HIGHLIGHT-P is normally a face-boolean instantiator; see
686  `make-face-boolean-specifier'.
687 See `set-face-property' for the semantics of the LOCALE, TAG-SET, and
688  HOW-TO-ADD arguments."
689   (interactive (face-interactive "highlight-p" "highlighted"))
690   (set-face-property face 'highlight highlight-p locale tag-set how-to-add))
691
692 (defun face-dim-p (face &optional domain default no-fallback)
693   "Return t if FACE is dimmed in DOMAIN.
694 See `face-property-instance' for the semantics of the DOMAIN argument."
695   (face-property-instance face 'dim domain default no-fallback))
696
697 (defun set-face-dim-p (face dim-p &optional locale tag-set how-to-add)
698   "Change whether FACE is dimmed in LOCALE.
699 DIM-P is normally a face-boolean instantiator; see
700  `make-face-boolean-specifier'.
701 See `set-face-property' for the semantics of the LOCALE, TAG-SET, and
702  HOW-TO-ADD arguments."
703   (interactive (face-interactive "dim-p" "dimmed"))
704   (set-face-property face 'dim dim-p locale tag-set how-to-add))
705
706 (defun face-blinking-p (face &optional domain default no-fallback)
707   "Return t if FACE is blinking in DOMAIN (TTY domains only).
708 See `face-property-instance' for the semantics of the DOMAIN argument."
709   (face-property-instance face 'blinking domain default no-fallback))
710
711 (defun set-face-blinking-p (face blinking-p &optional locale tag-set
712                                  how-to-add)
713   "Change whether FACE is blinking in LOCALE (TTY locales only).
714 BLINKING-P is normally a face-boolean instantiator; see
715  `make-face-boolean-specifier'.
716 See `set-face-property' for the semantics of the LOCALE, TAG-SET, and
717  HOW-TO-ADD arguments."
718   (interactive (face-interactive "blinking-p" "blinking"))
719   (set-face-property face 'blinking blinking-p locale tag-set how-to-add))
720
721 (defun face-reverse-p (face &optional domain default no-fallback)
722   "Return t if FACE is reversed in DOMAIN (TTY domains only).
723 See `face-property-instance' for the semantics of the DOMAIN argument."
724   (face-property-instance face 'reverse domain default no-fallback))
725
726 (defun set-face-reverse-p (face reverse-p &optional locale tag-set how-to-add)
727   "Change whether FACE is reversed in LOCALE (TTY locales only).
728 REVERSE-P is normally a face-boolean instantiator; see
729  `make-face-boolean-specifier'.
730 See `set-face-property' for the semantics of the LOCALE, TAG-SET, and
731  HOW-TO-ADD arguments."
732   (interactive (face-interactive "reverse-p" "reversed"))
733   (set-face-property face 'reverse reverse-p locale tag-set how-to-add))
734
735 \f
736 (defun face-property-equal (face1 face2 prop domain)
737   (equal (face-property-instance face1 prop domain)
738          (face-property-instance face2 prop domain)))
739
740 (defun face-equal-loop (props face1 face2 domain)
741   (while (and props
742               (face-property-equal face1 face2 (car props) domain))
743     (setq props (cdr props)))
744   (null props))
745
746 (defun face-equal (face1 face2 &optional domain)
747   "Return t if FACE1 and FACE2 will display in the same way in DOMAIN.
748 See `face-property-instance' for the semantics of the DOMAIN argument."
749   (if (null domain) (setq domain (selected-window)))
750   (if (not (valid-specifier-domain-p domain))
751       (error "Invalid specifier domain"))
752   (let ((device (dfw-device domain))
753         (common-props '(foreground background font display-table underline
754                                    dim))
755         (win-props '(background-pixmap strikethru))
756         (tty-props '(highlight blinking reverse)))
757
758     ;; First check the properties which are used in common between the
759     ;; x and tty devices.  Then, check those properties specific to
760     ;; the particular device type.
761     (and (face-equal-loop common-props face1 face2 domain)
762          (cond ((eq 'tty (device-type device))
763                 (face-equal-loop tty-props face1 face2 domain))
764                ;; #### Why isn't this (console-on-window-system-p (device-console device))?
765                ;; #### FIXME!
766                ((or (eq 'x (device-type device))
767                     (eq 'gtk (device-type device))
768                     (eq 'mswindows (device-type device)))
769                 (face-equal-loop win-props face1 face2 domain))
770                (t t)))))
771
772 (defun face-differs-from-default-p (face &optional domain)
773   "Return t if FACE will display differently from the default face in DOMAIN.
774 See `face-property-instance' for the semantics of the DOMAIN argument."
775   (not (face-equal face 'default domain)))
776
777 ; moved from x-faces.el
778 (defun try-font-name (name &optional device)
779   ;; yes, name really should be here twice.
780   (and name (make-font-instance name device t) name))
781
782 \f
783 ;; This function is a terrible, disgusting hack!!!!  Need to
784 ;; separate out the font elements as separate face properties!
785
786 ;; WE DEMAND LEXICAL SCOPING!!!
787 ;; WE DEMAND LEXICAL SCOPING!!!
788 ;; WE DEMAND LEXICAL SCOPING!!!
789 ;; WE DEMAND LEXICAL SCOPING!!!
790 ;; WE DEMAND LEXICAL SCOPING!!!
791 ;; WE DEMAND LEXICAL SCOPING!!!
792 ;; WE DEMAND LEXICAL SCOPING!!!
793 ;; WE DEMAND LEXICAL SCOPING!!!
794 ;; WE DEMAND LEXICAL SCOPING!!!
795 ;; WE DEMAND LEXICAL SCOPING!!!
796 ;; WE DEMAND LEXICAL SCOPING!!!
797 ;; WE DEMAND LEXICAL SCOPING!!!
798 ;; WE DEMAND LEXICAL SCOPING!!!
799 ;; WE DEMAND LEXICAL SCOPING!!!
800 ;; WE DEMAND LEXICAL SCOPING!!!
801 (defun frob-face-property (face property func device-tags &optional
802 locale tags)
803   "Change the specifier for FACE's PROPERTY according to FUNC, in LOCALE.
804 This function is ugly and messy and is primarily used as an internal
805 helper function for `make-face-bold' et al., so you probably don't
806 want to use it or read the rest of the documentation.  But if you do ...
807
808 FUNC should be a function of two arguments (an instance and a device)
809 that returns a modified name that is valid for the given device.
810 If LOCALE specifies a valid domain (i.e. a window, frame, or device),
811 this function instantiates the specifier over that domain, applies FUNC
812 to the resulting instance, and adds the result back as an instantiator
813 for that locale.  Otherwise, LOCALE should be a locale, locale type, or
814 'all (defaults to 'all if omitted).  For each specification thusly
815 included: if the locale given is a valid domain, FUNC will be
816 iterated over all valid instantiators for the device of the domain
817 until a non-nil result is found (if there is no such result, the
818 first valid instantiator is used), and that result substituted for
819 the specification; otherwise, the process just outlined is
820 iterated over each existing device and the concatenated results
821 substituted for the specification.
822
823 DEVICE-TAGS is a list of tags that each device must match in order for
824 the function to be called on it."
825   (let ((sp (face-property face property))
826         temp-sp)
827     (if (valid-specifier-domain-p locale)
828         ;; this is easy.
829         (let* ((inst (face-property-instance face property locale))
830                (name (and inst
831                           (device-matches-specifier-tag-set-p
832                            (dfw-device locale) device-tags)
833                           (funcall func inst (dfw-device locale)))))
834           (when name
835             (add-spec-to-specifier sp name locale tags)))
836       ;; otherwise, map over all specifications ...
837       ;; but first, some further kludging:
838       ;; (1) if we're frobbing the global property, make sure
839       ;;     that something is there (copy from the default face,
840       ;;     if necessary).  Otherwise, something like
841       ;;     (make-face-larger 'modeline)
842       ;;     won't do anything at all if the modeline simply
843       ;;     inherits its font from 'default.
844       ;; (2) if we're frobbing a particular locale, nothing would
845       ;;     happen if that locale has no instantiators.  So signal
846       ;;     an error to indicate this.
847
848
849       (setq temp-sp (copy-specifier sp))
850       (if (and (or (eq locale 'global) (eq locale 'all) (not locale))
851                (not (face-property face property 'global)))
852           (copy-specifier (face-property 'default property)
853                           temp-sp 'global))
854       (if (and (valid-specifier-locale-p locale)
855                (not (specifier-specs temp-sp locale)))
856           (error "Property must have a specification in locale %S" locale))
857       (map-specifier
858        temp-sp
859        (lambda (sp-arg locale inst-list func)
860          (let* ((device (dfw-device locale))
861                 ;; if a device can be derived from the locale,
862                 ;; call frob-face-property-1 for that device.
863                 ;; Otherwise map frob-face-property-1 over each device.
864                 (result
865                  (if device
866                      (list (and (device-matches-specifier-tag-set-p
867                                  device device-tags)
868                                 (frob-face-property-1 sp-arg device inst-list
869                                                       func)))
870                    (mapcar (lambda (device)
871                              (and (device-matches-specifier-tag-set-p
872                                    device device-tags)
873                                   (frob-face-property-1 sp-arg device
874                                                         inst-list func)))
875                            (device-list))))
876                 new-result)
877            ;; remove duplicates and nils from the obtained list of
878            ;; instantiators. Also add tags amd remove 'defaults'.
879            (mapcar (lambda (arg)
880                      (when arg
881                        (if (not (consp arg))
882                            (setq arg (cons tags arg))
883                          (setcar arg (append tags (delete 'default
884                                                           (car arg))))))
885                      (when (and arg (not (member arg new-result)))
886                        (setq new-result (cons arg new-result))))
887                    result)
888            ;; add back in.
889            (add-spec-list-to-specifier sp (list (cons locale new-result)))
890            ;; tell map-specifier to keep going.
891            nil))
892        locale
893        func))))
894
895 (defun frob-face-property-1 (sp device inst-list func)
896   (let
897       (first-valid result)
898     (while (and inst-list (not result))
899       (let* ((inst-pair (car inst-list))
900              (tag-set (car inst-pair))
901              (sp-inst (specifier-instance-from-inst-list
902                        sp device (list inst-pair))))
903         (if sp-inst
904             (progn
905               (if (not first-valid)
906                   (setq first-valid inst-pair))
907               (setq result (funcall func sp-inst device))
908               (if result
909                   (setq result (cons tag-set result))))))
910       (setq inst-list (cdr inst-list)))
911     (or result first-valid)))
912
913 (defcustom face-frob-from-locale-first nil
914   "*If non nil, use kludgy way of frobbing fonts suitable for non-mule
915 multi-charset environments."
916   :group 'faces
917   :type 'boolean)
918
919 (defun frob-face-font-2 (face locale tags unfrobbed-face frobbed-face
920                               tty-thunk ws-thunk standard-face-mapping)
921   ;; another kludge to make things more intuitive.  If we're
922   ;; inheriting from a standard face in this locale, frob the
923   ;; inheritance as appropriate.  Else, if, after the first
924   ;; window-system frobbing pass, the face hasn't changed and still
925   ;; looks like the standard unfrobbed face (e.g. 'default), make it
926   ;; inherit from the standard frobbed face (e.g. 'bold).  Regardless
927   ;; of things, do the TTY frobbing.
928
929   ;; yuck -- The LOCALE argument to make-face-bold is not actually a locale,
930   ;; but is a "locale, locale-type, or nil for all".  So ...  do our extra
931   ;; frobbing only if it's actually a locale; or for nil, do the frobbing
932   ;; on 'global.  This specifier stuff needs some rethinking.
933   (let* ((the-locale (cond ((null locale) 'global)
934                            ((valid-specifier-locale-p locale) locale)
935                            (t nil)))
936          (spec-list
937           (and
938            the-locale
939            (specifier-spec-list (get (get-face face) 'font) the-locale tags t)))
940          (change-it
941           (and
942            spec-list
943            (cdr (assoc (cdadar spec-list) standard-face-mapping)))))
944     (if (and change-it
945              (not (memq (face-name (find-face face))
946                         '(default bold italic bold-italic))))
947         (progn
948           (or (equal change-it t)
949               (set-face-property face 'font change-it the-locale tags))
950           (funcall tty-thunk))
951       (let* ((domain (cond ((null the-locale) nil)
952                            ((valid-specifier-domain-p the-locale) the-locale)
953                            ;; OK, this next one is truly a kludge, but
954                            ;; it results in more intuitive behavior most
955                            ;; of the time. (really!)
956                            ((or (eq the-locale 'global) (eq the-locale 'all))
957                             (selected-device))
958                            (t nil)))
959              (inst (and domain (face-property-instance face 'font domain))))
960         ;; If it's reasonable to do the inherit-from-standard-face trick,
961         ;; and it's called for, then do it now.
962         (if (and
963              face-frob-from-locale-first
964              (eq the-locale 'global)
965              domain
966              (equal inst (face-property-instance face 'font domain))
967              ;; don't do it for standard faces, or you'll get inheritance loops.
968              ;; #### This makes XEmacs seg fault! fix this bug.
969              (not (memq (face-name (find-face face))
970                         '(default bold italic bold-italic)))
971              (equal (face-property-instance face 'font domain)
972                     (face-property-instance unfrobbed-face 'font domain)))
973             (set-face-property face 'font (vector frobbed-face)
974                                the-locale tags)
975           ;; and only otherwise try to build new property value artificially
976           (funcall tty-thunk)
977           (funcall ws-thunk)
978           (and
979            domain
980            (equal inst (face-property-instance face 'font domain))
981            ;; don't do it for standard faces, or you'll get inheritance loops.
982            ;; #### This makes XEmacs seg fault! fix this bug.
983            (not (memq (face-name (find-face face))
984                       '(default bold italic bold-italic)))
985            (equal (face-property-instance face 'font domain)
986                   (face-property-instance unfrobbed-face 'font domain))
987            (set-face-property face 'font (vector frobbed-face) the-locale tags)))))))
988
989 ;; WE DEMAND FOUNDRY FROBBING!
990
991 ;; Family frobbing
992 ;; Thx Jan Vroonhof, Ref xemacs-beta <87oflypbum.fsf@petteflet.ntlworld.com>
993 ;; Brainlessly derived from make-face-size by Stephen; don't blame Jan.
994 ;; I'm long since flown to Rio, it does you little good to blame me, either.
995 (defun make-face-family (face family &optional locale tags)
996   "Set FACE's family to FAMILY in LOCALE, if possible.
997
998 Add/replace settings specified by TAGS only."
999   (frob-face-property face 'font
1000                       ;; uses dynamic scope of family
1001                       #'(lambda (f d)
1002                           ;; keep the dependency on font.el for now
1003                           (let ((fo (font-create-object (font-instance-name f)
1004                                                         d)))
1005                             (set-font-family fo family)
1006                             (font-create-name fo d)))
1007                       nil locale tags))
1008
1009 ;; Style (ie, typographical face) frobbing
1010 (defun make-face-bold (face &optional locale tags)
1011   "Make FACE bold in LOCALE, if possible.
1012 This will attempt to make the font bold for X/MSW locales and will set the
1013 highlight flag for TTY locales.
1014
1015 If LOCALE is nil, omitted, or `all', this will attempt to frob all
1016 font specifications for FACE to make them appear bold.  Similarly, if
1017 LOCALE is a locale type, this frobs all font specifications for locales
1018 of that type.  If LOCALE is a particular locale, what happens depends on
1019 what sort of locale is given.  If you gave a device, frame, or window,
1020 then it's always possible to determine what the font actually will be,
1021 so this is determined and the resulting font is frobbed and added back as a
1022 specification for this locale.  If LOCALE is a buffer, however, you can't
1023 determine what the font will actually be unless there's actually a
1024 specification given for that particular buffer (otherwise, it depends
1025 on what window and frame the buffer appears in, and might not even be
1026 well-defined if the buffer appears multiple times in different places);
1027 therefore you will get an error unless there's a specification for the
1028 buffer.
1029
1030 Finally, in some cases (specifically, when LOCALE is not a locale type),
1031 if the frobbing didn't actually make the font look any different
1032 \(this happens, for example, if your font specification is already bold
1033 or has no bold equivalent), and currently looks like the font of the
1034 'default face, it is set to inherit from the 'bold face.  This is kludgy
1035 but it makes `make-face-bold' have more intuitive behavior in many
1036 circumstances."
1037   (interactive (list (read-face-name "Make which face bold: ")))
1038   (frob-face-font-2
1039    face locale tags 'default 'bold
1040    (lambda ()
1041      ;; handle TTY specific entries
1042      (when (featurep 'tty)
1043        (set-face-highlight-p face t locale (cons 'tty tags))))
1044    (lambda ()
1045      ;; handle window-system specific entries
1046      (when (featurep 'gtk)
1047        (frob-face-property face 'font 'gtk-make-font-bold
1048                            '(gtk) locale tags))
1049      (when (featurep 'x)
1050        (frob-face-property face 'font 'x-make-font-bold
1051                            '(x) locale tags))
1052      (when (featurep 'mswindows)
1053        (frob-face-property face 'font 'mswindows-make-font-bold
1054                            '(mswindows) locale tags))
1055      )
1056    '(([default] . [bold])
1057      ([bold] . t)
1058      ([italic] . [bold-italic])
1059      ([bold-italic] . t))))
1060
1061 (defun make-face-italic (face &optional locale tags)
1062   "Make FACE italic in LOCALE, if possible.
1063 This will attempt to make the font italic for X/MS Windows locales and
1064 will set the underline flag for TTY locales.  See `make-face-bold' for
1065 the semantics of the LOCALE argument and for more specifics on exactly
1066 how this function works."
1067   (interactive (list (read-face-name "Make which face italic: ")))
1068   (frob-face-font-2
1069    face locale tags 'default 'italic
1070    (lambda ()
1071      ;; handle TTY specific entries
1072      (when (featurep 'tty)
1073        (set-face-underline-p face t locale (cons 'tty tags))))
1074    (lambda ()
1075      ;; handle window-system specific entries
1076      (when (featurep 'gtk)
1077        (frob-face-property face 'font 'gtk-make-font-italic
1078                            '(gtk) locale tags))
1079      (when (featurep 'x)
1080        (frob-face-property face 'font 'x-make-font-italic
1081                            '(x) locale tags))
1082      (when (featurep 'mswindows)
1083        (frob-face-property face 'font 'mswindows-make-font-italic
1084                            '(mswindows) locale tags))
1085      )
1086    '(([default] . [italic])
1087      ([bold] . [bold-italic])
1088      ([italic] . t)
1089      ([bold-italic] . t))))
1090
1091 (defun make-face-bold-italic (face &optional locale tags)
1092   "Make FACE bold and italic in LOCALE, if possible.
1093 This will attempt to make the font bold-italic for X/MS Windows
1094 locales and will set the highlight and underline flags for TTY
1095 locales.  See `make-face-bold' for the semantics of the LOCALE
1096 argument and for more specifics on exactly how this function works."
1097   (interactive (list (read-face-name "Make which face bold-italic: ")))
1098   (frob-face-font-2
1099    face locale tags 'default 'bold-italic
1100    (lambda ()
1101      ;; handle TTY specific entries
1102      (when (featurep 'tty)
1103        (set-face-highlight-p face t locale (cons 'tty tags))
1104        (set-face-underline-p face t locale (cons 'tty tags))))
1105    (lambda ()
1106      ;; handle window-system specific entries
1107      (when (featurep 'gtk)
1108        (frob-face-property face 'font 'gtk-make-font-bold-italic
1109                            '(gtk) locale tags))
1110      (when (featurep 'x)
1111        (frob-face-property face 'font 'x-make-font-bold-italic
1112                            '(x) locale tags))
1113      (when (featurep 'mswindows)
1114        (frob-face-property face 'font 'mswindows-make-font-bold-italic
1115                            '(mswindows) locale tags))
1116      )
1117    '(([default] . [italic])
1118      ([bold] . [bold-italic])
1119      ([italic] . [bold-italic])
1120      ([bold-italic] . t))))
1121
1122 (defun make-face-unbold (face &optional locale tags)
1123   "Make FACE non-bold in LOCALE, if possible.
1124 This will attempt to make the font non-bold for X/MS Windows locales
1125 and will unset the highlight flag for TTY locales.  See
1126 `make-face-bold' for the semantics of the LOCALE argument and for more
1127 specifics on exactly how this function works."
1128   (interactive (list (read-face-name "Make which face non-bold: ")))
1129   (frob-face-font-2
1130    face locale tags 'bold 'default
1131    (lambda ()
1132      ;; handle TTY specific entries
1133      (when (featurep 'tty)
1134        (set-face-highlight-p face nil locale (cons 'tty tags))))
1135    (lambda ()
1136      ;; handle window-system specific entries
1137      (when (featurep 'gtk)
1138        (frob-face-property face 'font 'gtk-make-font-unbold
1139                            '(gtk) locale tags))
1140      (when (featurep 'x)
1141        (frob-face-property face 'font 'x-make-font-unbold
1142                            '(x) locale tags))
1143      (when (featurep 'mswindows)
1144        (frob-face-property face 'font 'mswindows-make-font-unbold
1145                            '(mswindows) locale tags))
1146      )
1147    '(([default] . t)
1148      ([bold] . [default])
1149      ([italic] . t)
1150      ([bold-italic] . [italic]))))
1151
1152 (defun make-face-unitalic (face &optional locale tags)
1153   "Make FACE non-italic in LOCALE, if possible.
1154 This will attempt to make the font non-italic for X/MS Windows locales
1155 and will unset the underline flag for TTY locales.  See
1156 `make-face-bold' for the semantics of the LOCALE argument and for more
1157 specifics on exactly how this function works."
1158   (interactive (list (read-face-name "Make which face non-italic: ")))
1159   (frob-face-font-2
1160    face locale tags 'italic 'default
1161    (lambda ()
1162      ;; handle TTY specific entries
1163      (when (featurep 'tty)
1164        (set-face-underline-p face nil locale (cons 'tty tags))))
1165    (lambda ()
1166      ;; handle window-system specific entries
1167      (when (featurep 'gtk)
1168        (frob-face-property face 'font 'gtk-make-font-unitalic
1169                            '(gtk) locale tags))
1170      (when (featurep 'x)
1171        (frob-face-property face 'font 'x-make-font-unitalic
1172                            '(x) locale tags))
1173      (when (featurep 'mswindows)
1174        (frob-face-property face 'font 'mswindows-make-font-unitalic
1175                            '(mswindows) locale tags))
1176      )
1177    '(([default] . t)
1178      ([bold] . t)
1179      ([italic] . [default])
1180      ([bold-italic] . [bold]))))
1181
1182
1183 ;; Size frobbing
1184 ;; Thx Jan Vroonhof, Ref xemacs-beta <87oflypbum.fsf@petteflet.ntlworld.com>
1185 ;; Jan had a separate helper function 
1186 (defun make-face-size (face size &optional locale tags)
1187   "Adjust FACE to SIZE in LOCALE, if possible.
1188
1189 Add/replace settings specified by TAGS only."
1190   (frob-face-property face 'font
1191                       ;; uses dynamic scope of size
1192                       #'(lambda (f d)
1193                           ;; keep the dependency on font.el for now
1194                           (let ((fo (font-create-object (font-instance-name f)
1195                                                         d)))
1196                             (set-font-size fo size)
1197                             (font-create-name fo d)))
1198                       nil locale tags))
1199
1200 ;; Why do the following two functions lose so badly in so many
1201 ;; circumstances?
1202
1203 (defun make-face-smaller (face &optional locale)
1204   "Make the font of FACE be smaller, if possible.
1205 LOCALE works as in `make-face-bold' et al., but the ``inheriting-
1206 from-the-bold-face'' operations described there are not done
1207 because they don't make sense in this context."
1208   (interactive (list (read-face-name "Shrink which face: ")))
1209   ;; handle X specific entries
1210   (when (featurep 'x)
1211     (frob-face-property face 'font 'x-find-smaller-font
1212                         '(x) locale))
1213   (when (featurep 'mswindows)
1214     (frob-face-property face 'font 'mswindows-find-smaller-font
1215                         '(mswindows) locale)))
1216
1217 (defun make-face-larger (face &optional locale)
1218   "Make the font of FACE be larger, if possible.
1219 See `make-face-smaller' for the semantics of the LOCALE argument."
1220   (interactive (list (read-face-name "Enlarge which face: ")))
1221   ;; handle X specific entries
1222   (when (featurep 'x)
1223     (frob-face-property face 'font 'x-find-larger-font
1224                         '(x) locale))
1225   (when (featurep 'mswindows)
1226     (frob-face-property face 'font 'mswindows-find-larger-font
1227                         '(mswindows) locale)))
1228
1229 (defun invert-face (face &optional locale)
1230   "Swap the foreground and background colors of the face."
1231   (interactive (list (read-face-name "Invert face: ")))
1232   (if (valid-specifier-domain-p locale)
1233       (let ((foreface (face-foreground-instance face locale)))
1234         (set-face-foreground face (face-background-instance face locale)
1235                              locale)
1236         (set-face-background face foreface locale))
1237     (let ((forespec (copy-specifier (face-foreground face) nil locale)))
1238       (copy-specifier (face-background face) (face-foreground face) locale)
1239       (copy-specifier forespec (face-background face) locale))))
1240
1241 \f
1242 ;;; Convenience functions
1243
1244 (defun face-ascent (face &optional domain charset)
1245   "Return the ascent of FACE in DOMAIN.
1246 See `face-property-instance' for the semantics of the DOMAIN argument."
1247   (font-ascent (face-font face) domain charset))
1248
1249 (defun face-descent (face &optional domain charset)
1250   "Return the descent of FACE in DOMAIN.
1251 See `face-property-instance' for the semantics of the DOMAIN argument."
1252   (font-descent (face-font face) domain charset))
1253
1254 (defun face-width (face &optional domain charset)
1255   "Return the width of FACE in DOMAIN.
1256 See `face-property-instance' for the semantics of the DOMAIN argument."
1257   (font-width (face-font face) domain charset))
1258
1259 (defun face-height (face &optional domain charset)
1260   "Return the height of FACE in DOMAIN.
1261 See `face-property-instance' for the semantics of the DOMAIN argument."
1262   (+ (face-ascent face domain charset) (face-descent face domain charset)))
1263
1264 (defun face-proportional-p (face &optional domain charset)
1265   "Return t if FACE is proportional in DOMAIN.
1266 See `face-property-instance' for the semantics of the DOMAIN argument."
1267   (font-proportional-p (face-font face) domain charset))
1268
1269 \f
1270 ;; Functions that used to be in cus-face.el, but logically go here.
1271
1272 (defcustom frame-background-mode nil
1273   "*The brightness of the background.
1274 Set this to the symbol dark if your background color is dark, light if
1275 your background is light, or nil (default) if you want Emacs to
1276 examine the brightness for you."
1277   :group 'faces
1278   :type '(choice (choice-item dark)
1279                  (choice-item light)
1280                  (choice-item :tag "Auto" nil)))
1281
1282 ;; The old variable that many people still have in .emacs files.
1283 (define-obsolete-variable-alias 'custom-background-mode
1284   'frame-background-mode)
1285
1286 (defun get-frame-background-mode (frame)
1287   "Detect background mode for FRAME."
1288   (let* ((color-instance (face-background-instance 'default frame))
1289          (mode (condition-case nil
1290                    (if (< (apply '+ (color-instance-rgb-components
1291                                      color-instance)) 65536)
1292                        'dark 'light)
1293                  ;; Here, we get an error on a TTY.  As we don't have
1294                  ;; a good way of detecting whether a TTY is light or
1295                  ;; dark, we'll guess it's dark.
1296                  (error 'dark))))
1297     (set-frame-property frame 'background-mode mode)
1298     mode))
1299
1300 (defun extract-custom-frame-properties (frame)
1301   "Return a plist with the frame properties of FRAME used by custom."
1302   (list 'type (or (frame-property frame 'display-type)
1303                   (device-type (frame-device frame)))
1304         'class (device-class (frame-device frame))
1305         'background (or frame-background-mode
1306                         (frame-property frame 'background-mode)
1307                         (get-frame-background-mode frame))))
1308
1309 (defcustom init-face-from-resources t
1310   "If non nil, attempt to initialize faces from the resource database."
1311   :group 'faces
1312   :type 'boolean)
1313
1314 ;; Old name, used by custom.  Also, FSFmacs name.
1315 (defvaralias 'initialize-face-resources 'init-face-from-resources)
1316
1317 ;; Make sure all custom setting are added with this tag so we can
1318 ;; identify-them
1319 (define-specifier-tag 'custom)
1320
1321 (defun face-spec-set (face spec &optional frame tags)
1322   "Set FACE's face attributes according to the first matching entry in SPEC.
1323 If optional FRAME is non-nil, set it for that frame only.
1324 If it is nil, then apply SPEC to each frame individually.
1325 See `defface' for information about SPEC."
1326   (if frame
1327       (progn
1328         (reset-face face frame tags)
1329         (face-display-set face spec frame tags)
1330         (init-face-from-resources face frame))
1331     (let ((frames (relevant-custom-frames)))
1332       (reset-face face nil tags)
1333       ;; This should not be needed. We only remove our own specifiers
1334       ;; (if (and (eq 'default face) (featurep 'x))
1335       ;;          (x-init-global-faces))
1336       (face-display-set face spec nil tags)
1337       (while frames
1338         (face-display-set face spec (car frames) tags)
1339         (pop frames))
1340       (init-face-from-resources face))))
1341
1342 (defun face-display-set (face spec &optional frame tags)
1343   "Set FACE to the attributes to the first matching entry in SPEC.
1344 Iff optional FRAME is non-nil, set it for that frame only.
1345 See `defface' for information about SPEC."
1346   (while spec
1347     (let ((display (caar spec))
1348           (atts (cadar spec)))
1349       (pop spec)
1350       (when (face-spec-set-match-display display frame)
1351         ;; Avoid creating frame local duplicates of the global face.
1352         (unless (and frame (eq display (get face 'custom-face-display)))
1353           (apply 'face-custom-attributes-set face frame tags atts))
1354         (unless frame
1355           (put face 'custom-face-display display))
1356         (setq spec nil)))))
1357
1358 (defvar default-custom-frame-properties nil
1359   "The frame properties used for the global faces.
1360 Frames not matching these properties should have frame local faces.
1361 The value should be nil, if uninitialized, or a plist otherwise.
1362 See `defface' for a list of valid keys and values for the plist.")
1363
1364 (defun get-custom-frame-properties (&optional frame)
1365   "Return a plist with the frame properties of FRAME used by custom.
1366 If FRAME is nil, return the default frame properties."
1367   (cond (frame
1368          ;; Try to get from cache.
1369          (let ((cache (frame-property frame 'custom-properties)))
1370            (unless cache
1371              ;; Oh well, get it then.
1372              (setq cache (extract-custom-frame-properties frame))
1373              ;; and cache it...
1374              (set-frame-property frame 'custom-properties cache))
1375            cache))
1376         (default-custom-frame-properties)
1377         (t
1378          (setq default-custom-frame-properties
1379                (extract-custom-frame-properties (selected-frame))))))
1380
1381 (defun face-spec-update-all-matching (spec display plist)
1382   "Update all entries in the face spec that could match display to
1383 have the entries from the new plist and return the new spec."
1384   (mapcar
1385    (lambda (e)
1386      (let ((entries (car e))
1387            (options (cadr e))
1388            (match t)
1389            dplist
1390            (new-options plist)
1391            )
1392        (unless (eq display t)
1393          (mapc (lambda (arg)
1394                  (setq dplist (plist-put dplist (car arg) (cadr arg))))
1395                display))
1396        (unless (eq entries t)
1397          (mapc (lambda (arg)
1398                  (setq match (and match (eq (cadr arg)
1399                                             (plist-get
1400                                               dplist (car arg)
1401                                               (cadr arg))))))
1402                entries))
1403        (if (not match)
1404            e
1405          (while new-options
1406            (setq options
1407                  (plist-put options (car new-options) (cadr new-options)))
1408            (setq new-options (cddr new-options)))
1409          (list entries options))))
1410    (copy-sequence spec)))
1411
1412
1413
1414 (defun face-spec-set-match-display (display &optional frame)
1415   "Return non-nil if DISPLAY matches FRAME.
1416 DISPLAY is part of a spec such as can be used in `defface'.
1417 If FRAME is nil or omitted, the selected frame is used."
1418   (if (eq display t)
1419       t
1420     (let* ((props (get-custom-frame-properties frame))
1421            (type (plist-get props 'type))
1422            (class (plist-get props 'class))
1423            (background (plist-get props 'background))
1424            (match t)
1425            (entries display)
1426            entry req options)
1427       (while (and entries match)
1428         (setq entry (car entries)
1429               entries (cdr entries)
1430               req (car entry)
1431               options (cdr entry)
1432               match (case req
1433                       (type       (memq type options))
1434                       (class      (memq class options))
1435                       (background (memq background options))
1436                       (t (warn "Unknown req `%S' with options `%S'"
1437                                req options)
1438                          nil))))
1439       match)))
1440
1441 (defun relevant-custom-frames ()
1442   "List of frames whose custom properties differ from the default."
1443   (let ((relevant nil)
1444         (default (get-custom-frame-properties))
1445         (frames (frame-list))
1446         frame)
1447     (while frames
1448       (setq frame (car frames)
1449             frames (cdr frames))
1450       (unless (equal default (get-custom-frame-properties frame))
1451         (push frame relevant)))
1452     relevant))
1453
1454 (defun initialize-custom-faces (&optional frame)
1455   "Initialize all custom faces for FRAME.
1456 If FRAME is nil or omitted, initialize them for all frames."
1457   (mapc (lambda (symbol)
1458           (let ((spec (or (get symbol 'saved-face)
1459                           (get symbol 'face-defface-spec))))
1460             (when spec
1461               ;; No need to init-face-from-resources -- code in
1462               ;; `init-frame-faces' does it already.
1463               (face-display-set symbol spec frame))))
1464         (face-list)))
1465
1466 (defun custom-initialize-frame (frame)
1467   "Initialize frame-local custom faces for FRAME if necessary."
1468   (unless (equal (get-custom-frame-properties)
1469                  (get-custom-frame-properties frame))
1470     (initialize-custom-faces frame)))
1471
1472 (defun startup-initialize-custom-faces ()
1473   "Reset faces created by defface.  Only called at startup.
1474 Don't use this function in your program."
1475   (when default-custom-frame-properties
1476     ;; Reset default value to the actual frame, not stream.
1477     (setq default-custom-frame-properties
1478           (extract-custom-frame-properties (selected-frame)))
1479     ;; like initialize-custom-faces but removes property first.
1480     (mapc (lambda (symbol)
1481             (let ((spec (or (get symbol 'saved-face)
1482                             (get symbol 'face-defface-spec))))
1483               (when spec
1484                 ;; Reset faces created during auto-autoloads loading.
1485                 (reset-face symbol)
1486                 ;; And set it according to the spec.
1487                 (face-display-set symbol spec nil))))
1488           (face-list))))
1489
1490 \f
1491 (defun make-empty-face (name &optional doc-string temporary)
1492   "Like `make-face', but doesn't query the resource database."
1493   (let ((init-face-from-resources nil))
1494     (make-face name doc-string temporary)))
1495
1496 (defun init-face-from-resources (face &optional locale)
1497   "Initialize FACE from the resource database.
1498 If LOCALE is specified, it should be a frame, device, or 'global, and
1499 the face will be resourced over that locale.  Otherwise, the face will
1500 be resourced over all possible locales (i.e. all frames, all devices,
1501 and 'global)."
1502   (cond ((null init-face-from-resources)
1503          ;; Do nothing.
1504          )
1505         ((not locale)
1506          ;; Global, set for all frames.
1507          (progn
1508            (init-face-from-resources face 'global)
1509            (let ((devices (device-list)))
1510              (while devices
1511                (init-face-from-resources face (car devices))
1512                (setq devices (cdr devices))))
1513            (let ((frames (frame-list)))
1514              (while frames
1515                (init-face-from-resources face (car frames))
1516                (setq frames (cdr frames))))))
1517         (t
1518          ;; Specific.
1519          (let ((devtype (cond ((devicep locale) (device-type locale))
1520                               ((framep locale) (frame-type locale))
1521                               (t nil))))
1522            (cond ((or (and (not devtype) (featurep 'x)) (eq 'x devtype))
1523                   (x-init-face-from-resources face locale))
1524                  ((or (not devtype) (eq 'tty devtype))
1525                   ;; Nothing to do for TTYs?
1526                   ))))))
1527
1528 (defun init-device-faces (device)
1529   ;; First, add any device-local face resources.
1530   (when init-face-from-resources
1531     (loop for face in (face-list) do
1532           (init-face-from-resources face device))
1533     ;; Then do any device-specific initialization.
1534     (cond ((eq 'x (device-type device))
1535            (x-init-device-faces device))
1536           ((eq 'gtk (device-type device))
1537            (gtk-init-device-faces device))
1538           ((eq 'mswindows (device-type device))
1539            (mswindows-init-device-faces device))
1540           ;; Nothing to do for TTYs?
1541           )
1542     (or (eq 'stream (device-type device))
1543         (init-other-random-faces device))))
1544
1545 (defun init-frame-faces (frame)
1546   (when init-face-from-resources
1547     ;; First, add any frame-local face resources.
1548     (loop for face in (face-list) do
1549           (init-face-from-resources face frame))
1550     ;; Then do any frame-specific initialization.
1551     (cond ((eq 'x (frame-type frame))
1552            (x-init-frame-faces frame))
1553           ((eq 'gtk (frame-type frame))
1554            (gtk-init-frame-faces frame))
1555           ((eq 'mswindows (frame-type frame))
1556            (mswindows-init-frame-faces frame))
1557           ;; Is there anything which should be done for TTY's?
1558           )))
1559
1560 ;; #### This is somewhat X-specific, and is called when the first
1561 ;; X device is created (even if there were TTY devices created
1562 ;; beforehand).  The concept of resources has not been generalized
1563 ;; outside of X-specificness, so we have to live with this
1564 ;; breach of device-independence.
1565
1566 (defun init-global-faces ()
1567   ;; Look for global face resources.
1568   (loop for face in (face-list) do
1569         (init-face-from-resources face 'global))
1570   ;; Further X frobbing.
1571   (and (featurep 'x) (x-init-global-faces))
1572   (and (featurep 'gtk) (gtk-init-global-faces))
1573
1574   ;; for bold and the like, make the global specification be bold etc.
1575   ;; if the user didn't already specify a value.  These will also be
1576   ;; frobbed further in init-other-random-faces.
1577   (unless (face-font 'bold 'global)
1578     (make-face-bold 'bold 'global))
1579   ;;
1580   (unless (face-font 'italic 'global)
1581     (make-face-italic 'italic 'global))
1582   ;;
1583   (unless (face-font 'bold-italic 'global)
1584     (make-face-bold-italic 'bold-italic 'global)
1585     (unless (face-font 'bold-italic 'global)
1586       (copy-face 'bold 'bold-italic)
1587       (make-face-italic 'bold-italic)))
1588
1589   (when (face-equal 'bold 'bold-italic)
1590     (copy-face 'italic 'bold-italic)
1591     (make-face-bold 'bold-italic))
1592   ;;
1593   ;; Nothing more to be done for X or TTY's?
1594   )
1595
1596
1597 ;; These warnings are there for a reason.  Just specify your fonts
1598 ;; correctly.  Deal with it.  Additionally, one can use
1599 ;; `log-warning-minimum-level' instead of this.
1600 ;(defvar inhibit-font-complaints nil
1601 ;  "Whether to suppress complaints about incomplete sets of fonts.")
1602
1603 (defun face-complain-about-font (face device)
1604   (if (symbolp face) (setq face (symbol-name face)))
1605 ;;  (if (not inhibit-font-complaints)
1606   (display-warning
1607    'font
1608    (let ((default-name (face-font-name 'default device)))
1609      (format "%s: couldn't deduce %s %s version of the font
1610 %S.
1611
1612 Please specify X resources to make the %s face
1613 visually distinguishable from the default face.
1614 For example, you could add one of the following to $HOME/Emacs:
1615
1616 Emacs.%s.attributeFont: -dt-*-medium-i-*
1617 or
1618 Emacs.%s.attributeForeground: hotpink\n"
1619              invocation-name
1620              (if (string-match "\\`[aeiouAEIOU]" face) "an" "a")
1621              face
1622              default-name
1623              face
1624              face
1625              face
1626              ))))
1627
1628
1629 ;; #### This is quite a mess.  We should use the custom mechanism for
1630 ;; most of this stuff.  Currently we don't do it, because Custom
1631 ;; doesn't use specifiers (yet.)  FSF does it the Right Way.
1632
1633 ;; For instance, the definition of `bold' should be something like
1634 ;; (defface bold ((t (:bold t))) "Bold text.") -- and `:bold t' should
1635 ;; make sure that everything works properly.
1636
1637 (defun init-other-random-faces (device)
1638   "Initialize the colors and fonts of the bold, italic, bold-italic,
1639 zmacs-region, list-mode-item-selected, highlight, primary-selection,
1640 secondary-selection, and isearch faces when each device is created.  If
1641 you want to add code to do stuff like this, use the create-device-hook."
1642
1643   ;; try to make 'bold look different from the default on this device.
1644   ;; If that doesn't work at all, then issue a warning.
1645   (unless (face-differs-from-default-p 'bold device)
1646     (make-face-bold 'bold device)
1647     (unless (face-differs-from-default-p 'bold device)
1648       (make-face-unbold 'bold device)
1649       (unless (face-differs-from-default-p 'bold device)
1650         ;; the luser specified one of the bogus font names
1651         (face-complain-about-font 'bold device))))
1652
1653   ;; Similar for italic.
1654   ;; It's unreasonable to expect to be able to make a font italic all
1655   ;; the time.  For many languages, italic is an alien concept.
1656   ;; Basically, because italic is not a globally meaningful concept,
1657   ;; the use of the italic face should really be obsoleted.
1658
1659   ;; I disagree with above.  In many languages, the concept of capital
1660   ;; letters is just as alien, and yet we use them.  Italic is here to
1661   ;; stay.  -hniksic
1662
1663   ;; In a Solaris Japanese environment, there just aren't any italic
1664   ;; fonts - period.  CDE recognizes this reality, and fonts
1665   ;; -dt-interface user-medium-r-normal-*-*-*-*-*-*-*-*-* don't come
1666   ;; in italic versions.  So we first try to make the font bold before
1667   ;; complaining.
1668   (unless (face-differs-from-default-p 'italic device)
1669     (make-face-italic 'italic device)
1670     (unless (face-differs-from-default-p 'italic device)
1671       (make-face-bold 'italic device)
1672       (unless (face-differs-from-default-p 'italic device)
1673         (face-complain-about-font 'italic device))))
1674
1675   ;; similar for bold-italic.
1676   (unless (face-differs-from-default-p 'bold-italic device)
1677     (make-face-bold-italic 'bold-italic device)
1678     ;; if we couldn't get a bold-italic version, try just bold.
1679     (unless (face-differs-from-default-p 'bold-italic device)
1680       (make-face-bold 'bold-italic device)
1681       ;; if we couldn't get bold or bold-italic, then that's probably because
1682       ;; the default font is bold, so make the `bold-italic' face be unbold.
1683       (unless (face-differs-from-default-p 'bold-italic device)
1684         (make-face-unbold 'bold-italic device)
1685         (make-face-italic 'bold-italic device)
1686         (unless (face-differs-from-default-p 'bold-italic device)
1687           ;; if that didn't work, try plain italic
1688           ;; (can this ever happen? what the hell.)
1689           (make-face-italic 'bold-italic device)
1690           (unless (face-differs-from-default-p 'bold-italic device)
1691             ;; then bitch and moan.
1692             (face-complain-about-font 'bold-italic device))))))
1693
1694   ;; Set the text-cursor colors unless already specified.
1695   (when (and (not (eq 'tty (device-type device)))
1696              (not (face-background 'text-cursor 'global))
1697              (face-property-equal 'text-cursor 'default 'background device))
1698     (set-face-background 'text-cursor [default foreground] 'global
1699                          nil 'append))
1700   (when (and (not (eq 'tty (device-type device)))
1701              (not (face-foreground 'text-cursor 'global))
1702              (face-property-equal 'text-cursor 'default 'foreground device))
1703     (set-face-foreground 'text-cursor [default background] 'global
1704                          nil 'append))
1705   )
1706
1707 ;; New function with 20.1, suggested by Per Abrahamsen, coded by Kyle
1708 ;; Jones and Hrvoje Niksic.
1709 (defun set-face-stipple (face pixmap &optional frame)
1710   "Change the stipple pixmap of FACE to PIXMAP.
1711 This is an Emacs compatibility function; consider using
1712 set-face-background-pixmap instead.
1713
1714 PIXMAP should be a string, the name of a file of pixmap data.
1715 The directories listed in the variables `x-bitmap-file-path' and
1716 `mswindows-bitmap-file-path' under X and MS Windows respectively
1717 are searched.
1718
1719 Alternatively, PIXMAP may be a list of the form (WIDTH HEIGHT
1720 DATA) where WIDTH and HEIGHT are the size in pixels, and DATA is
1721 a string, containing the raw bits of the bitmap.  XBM data is
1722 expected in this case, other types of image data will not work.
1723
1724 If the optional FRAME argument is provided, change only
1725 in that frame; otherwise change each frame."
1726   (while (not (find-face face))
1727     (setq face (wrong-type-argument 'facep face)))
1728   (let ((bitmap-path (ecase (console-type)
1729                        (x         x-bitmap-file-path)
1730                        (mswindows mswindows-bitmap-file-path)))
1731         instantiator)
1732     (while
1733         (null
1734          (setq instantiator
1735                (cond ((stringp pixmap)
1736                       (let ((file (if (file-name-absolute-p pixmap)
1737                                       pixmap
1738                                     (locate-file pixmap bitmap-path
1739                                                  '(".xbm" "")))))
1740                         (and file
1741                              `[xbm :file ,file])))
1742                      ((and (listp pixmap) (= (length pixmap) 3))
1743                       `[xbm :data ,pixmap])
1744                      (t nil))))
1745       ;; We're signaling a continuable error; let's make sure the
1746       ;; function `stipple-pixmap-p' at least exists.
1747       (flet ((stipple-pixmap-p (pixmap)
1748                (or (stringp pixmap)
1749                    (and (listp pixmap) (= (length pixmap) 3)))))
1750         (setq pixmap (signal 'wrong-type-argument
1751                              (list 'stipple-pixmap-p pixmap)))))
1752     (check-type frame (or null frame))
1753     (set-face-background-pixmap face instantiator frame)))
1754
1755 \f
1756 ;; Create the remaining standard faces now.  This way, packages that we dump
1757 ;; can reference these faces as parents.
1758 ;;
1759 ;; The default, modeline, left-margin, right-margin, text-cursor,
1760 ;; and pointer faces are created in C.
1761
1762 (make-face 'bold "Bold text.")
1763 (make-face 'italic "Italic text.")
1764 (make-face 'bold-italic "Bold-italic text.")
1765 (make-face 'underline "Underlined text.")
1766 (or (face-differs-from-default-p 'underline)
1767     (set-face-underline-p 'underline t 'global '(default)))
1768 (make-face 'zmacs-region "Used on highlightes region between point and mark.")
1769 (make-face 'isearch "Used on region matched by isearch.")
1770 (make-face 'isearch-secondary "Face to use for highlighting all matches.")
1771 (make-face 'list-mode-item-selected
1772            "Face for the selected list item in list-mode.")
1773 (make-face 'highlight "Highlight face.")
1774 (make-face 'primary-selection "Primary selection face.")
1775 (make-face 'secondary-selection "Secondary selection face.")
1776
1777 ;; Several useful color faces.
1778 (eval-when-compile (load "cl-macs"))
1779 (dolist (color '(red green blue yellow))
1780   (make-face color (concat (symbol-name color) " text."))
1781   (set-face-foreground color (symbol-name color) nil 'color))
1782
1783 ;; Make some useful faces.  This happens very early, before creating
1784 ;; the first non-stream device.
1785
1786 (set-face-background 'text-cursor
1787                      '(((x default) . "Red3")
1788                        ((mswindows default) . "Red3"))
1789                      'global)
1790
1791 ;; some older X servers don't recognize "darkseagreen2"
1792 (set-face-background 'highlight
1793                      '(((x default color) . "darkseagreen2")
1794                        ((x default color) . "green")
1795                        ((x default grayscale) . "gray53")
1796                        ((mswindows default color) . "darkseagreen2")
1797                        ((mswindows default color) . "green")
1798                        ((mswindows default grayscale) . "gray53"))
1799                      'global)
1800 (set-face-background-pixmap 'highlight
1801                             '(((x default mono) . "gray1")
1802                               ((gtk default mono) . "gray1")
1803                               ((mswindows default mono) . "gray1"))
1804                             'global)
1805
1806 (set-face-background 'zmacs-region
1807                      '(((x default color) . "gray65")
1808                        ((x default grayscale) . "gray65")
1809                        ((mswindows default color) . "gray65")
1810                        ((mswindows default grayscale) . "gray65"))
1811                      'global)
1812 (set-face-background-pixmap 'zmacs-region
1813                             '(((x default mono) . "gray3")
1814                               ((gtk default mono) . "gray3")
1815                               ((mswindows default mono) . "gray3"))
1816                             'global)
1817
1818 (set-face-background 'list-mode-item-selected
1819                      '(((x default color) . "gray68")
1820                        ((x default grayscale) . "gray68")
1821                        ((x default mono) . [default foreground])
1822                        ((gtk default color) . "gray68")
1823                        ((gtk default grayscale) . "gray68")
1824                        ((gtk default mono) . [default foreground])
1825                        ((mswindows default color) . "gray68")
1826                        ((mswindows default grayscale) . "gray68")
1827                        ((mswindows default mono) . [default foreground]))
1828                      'global)
1829 (set-face-foreground 'list-mode-item-selected
1830                      '(((x default mono) . [default background])
1831                        ((mswindows default mono) . [default background]))
1832                      'global)
1833
1834 (set-face-background 'primary-selection
1835                      '(((x default color) . "gray65")
1836                        ((x default grayscale) . "gray65")
1837                        ((mswindows default color) . "gray65")
1838                        ((mswindows default grayscale) . "gray65"))
1839                      'global)
1840 (set-face-background-pixmap 'primary-selection
1841                             '(((x default mono) . "gray3")
1842                               ((gtk default mono) . "gray3")
1843                               ((mswindows default mono) . "gray3"))
1844                             'global)
1845
1846 (set-face-background 'secondary-selection
1847                      '(((x default color) . "paleturquoise")
1848                        ((x default color) . "green")
1849                        ((x default grayscale) . "gray53")
1850                        ((gtk default color) . "paleturquoise")
1851                        ((gtk default color) . "green")
1852                        ((gtk default grayscale) . "gray53")
1853                        ((mswindows default color) . "paleturquoise")
1854                        ((mswindows default color) . "green")
1855                        ((mswindows default grayscale) . "gray53"))
1856                      'global)
1857 (set-face-background-pixmap 'secondary-selection
1858                             '(((x default mono) . "gray1")
1859                               ((gtk default mono) . "gray1")
1860                               ((mswindows default mono) . "gray1"))
1861                             'global)
1862
1863 (set-face-background 'isearch
1864                      '(((x default color) . "paleturquoise")
1865                        ((x default color) . "green")
1866                        ((gtk default color) . "paleturquoise")
1867                        ((gtk default color) . "green")
1868                        ((mswindows default color) . "paleturquoise")
1869                        ((mswindows default color) . "green"))
1870                      'global)
1871
1872 ;; #### This should really, I mean *really*, be converted to some form
1873 ;; of `defface' one day.
1874 (set-face-foreground 'isearch-secondary
1875                      '(((x default color) . "red3")
1876                        ((mswindows default color) . "red3"))
1877                      'global)
1878
1879 ;; Define some logical color names to be used when reading the pixmap files.
1880 (if (featurep 'xpm)
1881     (setq xpm-color-symbols
1882           (list
1883            '("foreground" (face-foreground 'default))
1884            '("background" (face-background 'default))
1885            '("backgroundToolBarColor"
1886              (or
1887               (and
1888                (featurep 'x)
1889                (x-get-resource "backgroundToolBarColor"
1890                                "BackgroundToolBarColor" 'string
1891                                nil nil 'warn))
1892
1893               (face-background 'toolbar)))
1894            '("foregroundToolBarColor"
1895              (or
1896               (and
1897                (featurep 'x)
1898                (x-get-resource "foregroundToolBarColor"
1899                                "ForegroundToolBarColor" 'string
1900                                nil nil 'warn))
1901               (face-foreground 'toolbar)))
1902            )))
1903
1904 (when (featurep 'tty)
1905   (set-face-highlight-p 'bold                    t 'global '(default tty))
1906   (set-face-underline-p 'italic                  t 'global '(default tty))
1907   (set-face-highlight-p 'bold-italic             t 'global '(default tty))
1908   (set-face-underline-p 'bold-italic             t 'global '(default tty))
1909   (set-face-highlight-p 'highlight               t 'global '(default tty))
1910   (set-face-reverse-p   'text-cursor             t 'global '(default tty))
1911   (set-face-reverse-p   'modeline                t 'global '(default tty))
1912   (set-face-reverse-p   'zmacs-region            t 'global '(default tty))
1913   (set-face-reverse-p   'primary-selection       t 'global '(default tty))
1914   (set-face-underline-p 'secondary-selection     t 'global '(default tty))
1915   (set-face-reverse-p   'list-mode-item-selected t 'global '(default tty))
1916   (set-face-reverse-p   'isearch                 t 'global '(default tty))
1917   )
1918
1919 ;;; faces.el ends here