(custom-theme-set-faces): Undo previous change.
[bpt/emacs.git] / lisp / cus-face.el
CommitLineData
e8af40ee 1;;; cus-face.el --- customization support for faces
d543e20b 2;;
0d30b337 3;; Copyright (C) 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2004,
d7a0267c 4;; 2005, 2006, 2007 Free Software Foundation, Inc.
d543e20b
PA
5;;
6;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
7;; Keywords: help, faces
d543e20b 8
6c283d44 9;; This file is part of GNU Emacs.
d543e20b 10
6c283d44
RS
11;; GNU Emacs is free software; you can redistribute it and/or modify
12;; it under the terms of the GNU General Public License as published by
b4aa6026 13;; the Free Software Foundation; either version 3, or (at your option)
6c283d44 14;; any later version.
d543e20b 15
6c283d44
RS
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
d543e20b 20
6c283d44
RS
21;; You should have received a copy of the GNU General Public License
22;; along with GNU Emacs; see the file COPYING. If not, write to the
086add15
LK
23;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24;; Boston, MA 02110-1301, USA.
d543e20b 25
6c283d44
RS
26;;; Commentary:
27;;
28;; See `custom.el'.
d543e20b 29
6c283d44 30;;; Code:
d543e20b 31
da0b1f56 32(defalias 'custom-facep 'facep)
ccd0d40c 33
d543e20b
PA
34;;; Declaring a face.
35
36;;;###autoload
37(defun custom-declare-face (face spec doc &rest args)
38 "Like `defface', but FACE is evaluated as a normal argument."
6c283d44 39 (unless (get face 'face-defface-spec)
d543e20b 40 (when (fboundp 'facep)
6c283d44 41 (unless (facep face)
d543e20b
PA
42 ;; If the user has already created the face, respect that.
43 (let ((value (or (get face 'saved-face) spec))
987a3489 44 (have-window-system (memq initial-window-system '(x w32))))
d543e20b
PA
45 ;; Create global face.
46 (make-empty-face face)
b5188bcd 47 ;; Create frame-local faces
f4db5253 48 (dolist (frame (frame-list))
2246281f 49 (face-spec-set face value frame)
6dc59f76 50 (when (memq (window-system frame) '(x w32 mac))
2246281f
KL
51 (setq have-window-system t)))
52 ;; When making a face after frames already exist
53 (if have-window-system
54 (make-face-x-resource-internal face)))))
b5188bcd
RS
55 ;; Don't record SPEC until we see it causes no errors.
56 (put face 'face-defface-spec spec)
4829145a 57 (push (cons 'defface face) current-load-list)
209ddde3 58 (when (and doc (null (face-documentation face)))
08449ec1 59 (set-face-documentation face (purecopy doc)))
d543e20b
PA
60 (custom-handle-all-keywords face args 'custom-face)
61 (run-hooks 'custom-define-hook))
62 face)
63
da0b1f56
GM
64;;; Face attributes.
65
1265f177 66;;;###autoload
d543e20b 67(defconst custom-face-attributes
da0b1f56 68 '((:family
c165ad40
MB
69 (string :tag "Font Family"
70 :help-echo "Font family or fontset alias name."))
a3997907 71
da0b1f56
GM
72 (:width
73 (choice :tag "Width"
74 :help-echo "Font width."
c165ad40 75 :value normal ; default
da0b1f56
GM
76 (const :tag "compressed" condensed)
77 (const :tag "condensed" condensed)
78 (const :tag "demiexpanded" semi-expanded)
79 (const :tag "expanded" expanded)
80 (const :tag "extracondensed" extra-condensed)
81 (const :tag "extraexpanded" extra-expanded)
82 (const :tag "medium" normal)
83 (const :tag "narrow" condensed)
84 (const :tag "normal" normal)
85 (const :tag "regular" normal)
86 (const :tag "semicondensed" semi-condensed)
87 (const :tag "semiexpanded" semi-expanded)
88 (const :tag "ultracondensed" ultra-condensed)
89 (const :tag "ultraexpanded" ultra-expanded)
51a1edab 90 (const :tag "wide" extra-expanded)))
71296446 91
da0b1f56
GM
92 (:height
93 (choice :tag "Height"
94 :help-echo "Face's font height."
c165ad40 95 :value 1.0 ; default
6bca3005 96 (integer :tag "Height in 1/10 pt")
51a1edab 97 (number :tag "Scale" 1.0)))
6bca3005 98
da0b1f56
GM
99 (:weight
100 (choice :tag "Weight"
101 :help-echo "Font weight."
c165ad40 102 :value normal ; default
992f7c96 103 (const :tag "black" ultra-bold)
da0b1f56
GM
104 (const :tag "bold" bold)
105 (const :tag "book" semi-light)
106 (const :tag "demibold" semi-bold)
107 (const :tag "extralight" extra-light)
108 (const :tag "extrabold" extra-bold)
109 (const :tag "heavy" extra-bold)
110 (const :tag "light" light)
111 (const :tag "medium" normal)
112 (const :tag "normal" normal)
113 (const :tag "regular" normal)
114 (const :tag "semibold" semi-bold)
115 (const :tag "semilight" semi-light)
116 (const :tag "ultralight" ultra-light)
51a1edab 117 (const :tag "ultrabold" ultra-bold)))
71296446 118
da0b1f56
GM
119 (:slant
120 (choice :tag "Slant"
121 :help-echo "Font slant."
c165ad40 122 :value normal ; default
da0b1f56
GM
123 (const :tag "italic" italic)
124 (const :tag "oblique" oblique)
51a1edab 125 (const :tag "normal" normal)))
71296446 126
da0b1f56
GM
127 (:underline
128 (choice :tag "Underline"
129 :help-echo "Control text underlining."
c165ad40 130 (const :tag "Off" nil)
da0b1f56 131 (const :tag "On" t)
51a1edab 132 (color :tag "Colored")))
71296446 133
da0b1f56
GM
134 (:overline
135 (choice :tag "Overline"
136 :help-echo "Control text overlining."
c165ad40 137 (const :tag "Off" nil)
da0b1f56 138 (const :tag "On" t)
51a1edab 139 (color :tag "Colored")))
71296446 140
da0b1f56
GM
141 (:strike-through
142 (choice :tag "Strike-through"
143 :help-echo "Control text strike-through."
c165ad40 144 (const :tag "Off" nil)
da0b1f56 145 (const :tag "On" t)
51a1edab 146 (color :tag "Colored")))
71296446 147
da0b1f56 148 (:box
1743c17a 149 ;; Fixme: this can probably be done better.
da0b1f56
GM
150 (choice :tag "Box around text"
151 :help-echo "Control box around text."
c165ad40 152 (const :tag "Off" nil)
da0b1f56 153 (list :tag "Box"
36b80a0d 154 :value (:line-width 2 :color "grey75" :style released-button)
1743c17a 155 (const :format "" :value :line-width)
da0b1f56 156 (integer :tag "Width")
1743c17a
DL
157 (const :format "" :value :color)
158 (choice :tag "Color" (const :tag "*" nil) color)
159 (const :format "" :value :style)
160 (choice :tag "Style"
161 (const :tag "Raised" released-button)
162 (const :tag "Sunken" pressed-button)
163 (const :tag "None" nil))))
51a1edab
MB
164 ;; filter to make value suitable for customize
165 (lambda (real-value)
c165ad40
MB
166 (and real-value
167 (let ((lwidth
168 (or (and (consp real-value)
169 (plist-get real-value :line-width))
170 (and (integerp real-value) real-value)
171 1))
172 (color
173 (or (and (consp real-value) (plist-get real-value :color))
174 (and (stringp real-value) real-value)
175 nil))
176 (style
177 (and (consp real-value) (plist-get real-value :style))))
178 (list :line-width lwidth :color color :style style))))
36b80a0d
MB
179 ;; filter to make customized-value suitable for storing
180 (lambda (cus-value)
c165ad40
MB
181 (and cus-value
182 (let ((lwidth (plist-get cus-value :line-width))
183 (color (plist-get cus-value :color))
184 (style (plist-get cus-value :style)))
185 (cond ((and (null color) (null style))
186 lwidth)
187 ((and (null lwidth) (null style))
188 ;; actually can't happen, because LWIDTH is always an int
189 color)
190 (t
191 ;; Keep as a plist, but remove null entries
192 (nconc (and lwidth `(:line-width ,lwidth))
193 (and color `(:color ,color))
194 (and style `(:style ,style)))))))))
71296446 195
da0b1f56
GM
196 (:inverse-video
197 (choice :tag "Inverse-video"
198 :help-echo "Control whether text should be in inverse-video."
c165ad40
MB
199 (const :tag "Off" nil)
200 (const :tag "On" t)))
71296446 201
da0b1f56 202 (:foreground
c165ad40 203 (color :tag "Foreground"
4bbe6176 204 :help-echo "Set foreground color (name or #RRGGBB hex spec)."))
71296446 205
da0b1f56 206 (:background
c165ad40 207 (color :tag "Background"
4bbe6176 208 :help-echo "Set background color (name or #RRGGBB hex spec)."))
71296446 209
da0b1f56
GM
210 (:stipple
211 (choice :tag "Stipple"
675f1fcb 212 :help-echo "Background bit-mask"
c165ad40 213 (const :tag "None" nil)
675f1fcb
MB
214 (file :tag "File"
215 :help-echo "Name of bitmap file."
216 :must-match t)))
6bca3005
MB
217
218 (:inherit
219 (repeat :tag "Inherit"
220 :help-echo "List of faces to inherit attributes from."
221 (face :Tag "Face" default))
51a1edab
MB
222 ;; filter to make value suitable for customize
223 (lambda (real-value)
224 (cond ((or (null real-value) (eq real-value 'unspecified))
225 nil)
226 ((symbolp real-value)
227 (list real-value))
228 (t
229 real-value)))
230 ;; filter to make customized-value suitable for storing
231 (lambda (cus-value)
232 (if (and (consp cus-value) (null (cdr cus-value)))
233 (car cus-value)
234 cus-value))))
71296446 235
da0b1f56
GM
236 "Alist of face attributes.
237
51a1edab
MB
238The elements are of the form (KEY TYPE PRE-FILTER POST-FILTER),
239where KEY is the name of the attribute, TYPE is a widget type for
240editing the attribute, PRE-FILTER is a function to make the attribute's
241value suitable for the customization widget, and POST-FILTER is a
242function to make the customized value suitable for storing. PRE-FILTER
243and POST-FILTER are optional.
d543e20b 244
51a1edab
MB
245The PRE-FILTER should take a single argument, the attribute value as
246stored, and should return a value for customization (using the
247customization type TYPE).
d543e20b 248
51a1edab
MB
249The POST-FILTER should also take a single argument, the value after
250being customized, and should return a value suitable for setting the
251given face attribute.")
d543e20b
PA
252
253(defun custom-face-attributes-get (face frame)
6c283d44
RS
254 "For FACE on FRAME, return an alternating list describing its attributes.
255The list has the form (KEYWORD VALUE KEYWORD VALUE...).
d543e20b
PA
256Each keyword should be listed in `custom-face-attributes'.
257
6c283d44 258If FRAME is nil, use the global defaults for FACE."
da0b1f56
GM
259 (let ((attrs custom-face-attributes)
260 plist)
261 (while attrs
262 (let* ((attribute (car (car attrs)))
263 (value (face-attribute face attribute frame)))
264 (setq attrs (cdr attrs))
6bca3005
MB
265 (unless (or (eq value 'unspecified)
266 (and (null value) (memq attribute '(:inherit))))
da0b1f56
GM
267 (setq plist (cons attribute (cons value plist))))))
268 plist))
d543e20b 269
d543e20b
PA
270;;; Initializing.
271
d543e20b
PA
272;;;###autoload
273(defun custom-set-faces (&rest args)
274 "Initialize faces according to user preferences.
a3997907
RS
275This associates the settings with the `user' theme.
276The arguments should be a list where each entry has the form:
277
278 (FACE SPEC [NOW [COMMENT]])
279
280SPEC is stored as the saved value for FACE, as well as the value for the
281`user' theme. The `user' theme is one of the default themes known to Emacs.
282See `custom-known-themes' for more information on the known themes.
283See `custom-theme-set-faces' for more information on the interplay
284between themes and faces.
285See `defface' for the format of SPEC.
286
287If NOW is present and non-nil, FACE is created now, according to SPEC.
288COMMENT is a string comment about FACE."
289 (apply 'custom-theme-set-faces 'user args))
290
291(defun custom-theme-set-faces (theme &rest args)
292 "Initialize faces for theme THEME.
d543e20b
PA
293The arguments should be a list where each entry has the form:
294
1743c17a 295 (FACE SPEC [NOW [COMMENT]])
d543e20b 296
a3997907
RS
297SPEC is stored as the saved value for FACE, as well as the value for the
298`user' theme. The `user' theme is one of the default themes known to Emacs.
299See `custom-known-themes' for more information on the known themes.
300See `custom-theme-set-faces' for more information on the interplay
301between themes and faces.
302See `defface' for the format of SPEC.
303
6c283d44 304If NOW is present and non-nil, FACE is created now, according to SPEC.
1743c17a 305COMMENT is a string comment about FACE.
d543e20b 306
a3997907
RS
307Several properties of THEME and FACE are used in the process:
308
309If THEME property `theme-immediate' is non-nil, this is equivalent of
310providing the NOW argument to all faces in the argument list: FACE is
311created now. The only difference is FACE property `force-face': if NOW
312is non-nil, FACE property `force-face' is set to the symbol `rogue', else
313if THEME property `theme-immediate' is non-nil, FACE property `force-face'
314is set to the symbol `immediate'.
315
316SPEC itself is saved in FACE property `saved-face' and it is stored in
317FACE's list property `theme-face' \(using `custom-push-theme')."
318 (custom-check-theme theme)
319 (let ((immediate (get theme 'theme-immediate)))
320 (while args
321 (let ((entry (car args)))
322 (if (listp entry)
323 (let ((face (nth 0 entry))
324 (spec (nth 1 entry))
325 (now (nth 2 entry))
e335f09e
CY
326 (comment (nth 3 entry))
327 oldspec)
403546cb
LT
328 ;; If FACE is actually an alias, customize the face it
329 ;; is aliased to.
330 (if (get face 'face-alias)
331 (setq face (get face 'face-alias)))
e335f09e
CY
332
333 (setq oldspec (get face 'theme-face))
334 (when (not (and oldspec (eq 'user (caar oldspec))))
335 (put face 'saved-face spec)
336 (put face 'saved-face-comment comment))
337
a3997907
RS
338 (custom-push-theme 'theme-face face theme 'set spec)
339 (when (or now immediate)
340 (put face 'force-face (if now 'rogue 'immediate)))
341 (when (or now immediate (facep face))
342 (unless (facep face)
343 (make-empty-face face))
344 (put face 'face-comment comment)
578b4e9d
RS
345 (face-spec-set face spec nil))
346 (setq args (cdr args)))
347 ;; Old format, a plist of FACE SPEC pairs.
348 (let ((face (nth 0 args))
349 (spec (nth 1 args)))
350 (if (get face 'face-alias)
351 (setq face (get face 'face-alias)))
352 (put face 'saved-face spec)
353 (custom-push-theme 'theme-face face theme 'set spec))
354 (setq args (cdr (cdr args))))))))
a3997907 355
d358aa10
CY
356;; XEmacs compability function. In XEmacs, when you reset a Custom
357;; Theme, you have to specify the theme to reset it to. We just apply
358;; the next theme.
a3997907
RS
359;;;###autoload
360(defun custom-theme-reset-faces (theme &rest args)
2c9e973f
RS
361 "Reset the specs in THEME of some faces to their specs in other themes.
362Each of the arguments ARGS has this form:
a3997907 363
d358aa10 364 (FACE IGNORED)
a3997907 365
d358aa10 366This means reset FACE. The argument IGNORED is ignored."
a3997907 367 (custom-check-theme theme)
2c9e973f 368 (dolist (arg args)
d358aa10 369 (custom-push-theme 'theme-face (car arg) theme 'reset)))
a3997907
RS
370
371;;;###autoload
372(defun custom-reset-faces (&rest args)
2c9e973f
RS
373 "Reset the specs of some faces to their specs in specified themes.
374This creates settings in the `user' theme.
375
376Each of the arguments ARGS has this form:
377
378 (FACE FROM-THEME)
a3997907 379
2c9e973f 380This means reset FACE to its value in FROM-THEME."
a3997907 381 (apply 'custom-theme-reset-faces 'user args))
d543e20b
PA
382
383;;; The End.
384
385(provide 'cus-face)
386
ab5796a9 387;;; arch-tag: 9a5c4b63-0d27-4c92-a5af-f2c7ed764c2b
1743c17a 388;;; cus-face.el ends here