1 ;;; cus-face.el --- customization support for faces
3 ;; Copyright (C) 1996, 1997, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
5 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
6 ;; Keywords: help, faces
8 ;; This file is part of GNU Emacs.
10 ;; GNU Emacs is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
15 ;; GNU Emacs is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING. If not, write to the
22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
31 (defalias 'custom-facep
'facep
)
36 (defun custom-declare-face (face spec doc
&rest args
)
37 "Like `defface', but FACE is evaluated as a normal argument."
38 (unless (get face
'face-defface-spec
)
39 (when (fboundp 'facep
)
41 ;; If the user has already created the face, respect that.
42 (let ((value (or (get face
'saved-face
) spec
)))
43 ;; Create global face.
44 (make-empty-face face
)
45 ;; Create frame-local faces
46 (dolist (frame (frame-list))
47 (face-spec-set face value frame
)))
48 ;; When making a face after frames already exist
49 (if (memq window-system
'(x w32
))
50 (make-face-x-resource-internal face
))))
51 ;; Don't record SPEC until we see it causes no errors.
52 (put face
'face-defface-spec spec
)
53 (when (and doc
(null (face-documentation face
)))
54 (set-face-documentation face
(purecopy doc
)))
55 (custom-handle-all-keywords face args
'custom-face
)
56 (run-hooks 'custom-define-hook
))
61 (defconst custom-face-attributes
63 (string :tag
"Font Family"
64 :help-echo
"Font family or fontset alias name."))
68 :help-echo
"Font width."
69 :value normal
; default
70 (const :tag
"compressed" condensed
)
71 (const :tag
"condensed" condensed
)
72 (const :tag
"demiexpanded" semi-expanded
)
73 (const :tag
"expanded" expanded
)
74 (const :tag
"extracondensed" extra-condensed
)
75 (const :tag
"extraexpanded" extra-expanded
)
76 (const :tag
"medium" normal
)
77 (const :tag
"narrow" condensed
)
78 (const :tag
"normal" normal
)
79 (const :tag
"regular" normal
)
80 (const :tag
"semicondensed" semi-condensed
)
81 (const :tag
"semiexpanded" semi-expanded
)
82 (const :tag
"ultracondensed" ultra-condensed
)
83 (const :tag
"ultraexpanded" ultra-expanded
)
84 (const :tag
"wide" extra-expanded
)))
88 :help-echo
"Face's font height."
90 (integer :tag
"Height in 1/10 pt")
91 (number :tag
"Scale" 1.0)))
95 :help-echo
"Font weight."
96 :value normal
; default
97 (const :tag
"black" ultra-bold
)
98 (const :tag
"bold" bold
)
99 (const :tag
"book" semi-light
)
100 (const :tag
"demibold" semi-bold
)
101 (const :tag
"extralight" extra-light
)
102 (const :tag
"extrabold" extra-bold
)
103 (const :tag
"heavy" extra-bold
)
104 (const :tag
"light" light
)
105 (const :tag
"medium" normal
)
106 (const :tag
"normal" normal
)
107 (const :tag
"regular" normal
)
108 (const :tag
"semibold" semi-bold
)
109 (const :tag
"semilight" semi-light
)
110 (const :tag
"ultralight" ultra-light
)
111 (const :tag
"ultrabold" ultra-bold
)))
115 :help-echo
"Font slant."
116 :value normal
; default
117 (const :tag
"italic" italic
)
118 (const :tag
"oblique" oblique
)
119 (const :tag
"normal" normal
)))
122 (choice :tag
"Underline"
123 :help-echo
"Control text underlining."
124 (const :tag
"Off" nil
)
126 (color :tag
"Colored")))
129 (choice :tag
"Overline"
130 :help-echo
"Control text overlining."
131 (const :tag
"Off" nil
)
133 (color :tag
"Colored")))
136 (choice :tag
"Strike-through"
137 :help-echo
"Control text strike-through."
138 (const :tag
"Off" nil
)
140 (color :tag
"Colored")))
143 ;; Fixme: this can probably be done better.
144 (choice :tag
"Box around text"
145 :help-echo
"Control box around text."
146 (const :tag
"Off" nil
)
148 :value
(:line-width
2 :color
"grey75" :style released-button
)
149 (const :format
"" :value
:line-width
)
150 (integer :tag
"Width")
151 (const :format
"" :value
:color
)
152 (choice :tag
"Color" (const :tag
"*" nil
) color
)
153 (const :format
"" :value
:style
)
155 (const :tag
"Raised" released-button
)
156 (const :tag
"Sunken" pressed-button
)
157 (const :tag
"None" nil
))))
158 ;; filter to make value suitable for customize
162 (or (and (consp real-value
)
163 (plist-get real-value
:line-width
))
164 (and (integerp real-value
) real-value
)
167 (or (and (consp real-value
) (plist-get real-value
:color
))
168 (and (stringp real-value
) real-value
)
171 (and (consp real-value
) (plist-get real-value
:style
))))
172 (list :line-width lwidth
:color color
:style style
))))
173 ;; filter to make customized-value suitable for storing
176 (let ((lwidth (plist-get cus-value
:line-width
))
177 (color (plist-get cus-value
:color
))
178 (style (plist-get cus-value
:style
)))
179 (cond ((and (null color
) (null style
))
181 ((and (null lwidth
) (null style
))
182 ;; actually can't happen, because LWIDTH is always an int
185 ;; Keep as a plist, but remove null entries
186 (nconc (and lwidth
`(:line-width
,lwidth
))
187 (and color
`(:color
,color
))
188 (and style
`(:style
,style
)))))))))
191 (choice :tag
"Inverse-video"
192 :help-echo
"Control whether text should be in inverse-video."
193 (const :tag
"Off" nil
)
194 (const :tag
"On" t
)))
197 (color :tag
"Foreground"
198 :help-echo
"Set foreground color."))
201 (color :tag
"Background"
202 :help-echo
"Set background color."))
205 (choice :tag
"Stipple"
206 :help-echo
"Background bit-mask"
207 (const :tag
"None" nil
)
209 :help-echo
"Name of bitmap file."
213 (repeat :tag
"Inherit"
214 :help-echo
"List of faces to inherit attributes from."
215 (face :Tag
"Face" default
))
216 ;; filter to make value suitable for customize
218 (cond ((or (null real-value
) (eq real-value
'unspecified
))
220 ((symbolp real-value
)
224 ;; filter to make customized-value suitable for storing
226 (if (and (consp cus-value
) (null (cdr cus-value
)))
230 "Alist of face attributes.
232 The elements are of the form (KEY TYPE PRE-FILTER POST-FILTER),
233 where KEY is the name of the attribute, TYPE is a widget type for
234 editing the attribute, PRE-FILTER is a function to make the attribute's
235 value suitable for the customization widget, and POST-FILTER is a
236 function to make the customized value suitable for storing. PRE-FILTER
237 and POST-FILTER are optional.
239 The PRE-FILTER should take a single argument, the attribute value as
240 stored, and should return a value for customization (using the
241 customization type TYPE).
243 The POST-FILTER should also take a single argument, the value after
244 being customized, and should return a value suitable for setting the
245 given face attribute.")
247 (defun custom-face-attributes-get (face frame
)
248 "For FACE on FRAME, return an alternating list describing its attributes.
249 The list has the form (KEYWORD VALUE KEYWORD VALUE...).
250 Each keyword should be listed in `custom-face-attributes'.
252 If FRAME is nil, use the global defaults for FACE."
253 (let ((attrs custom-face-attributes
)
256 (let* ((attribute (car (car attrs
)))
257 (value (face-attribute face attribute frame
)))
258 (setq attrs
(cdr attrs
))
259 (unless (or (eq value
'unspecified
)
260 (and (null value
) (memq attribute
'(:inherit
))))
261 (setq plist
(cons attribute
(cons value plist
))))))
267 (defun custom-set-faces (&rest args
)
268 "Initialize faces according to user preferences.
269 This associates the settings with the `user' theme.
270 The arguments should be a list where each entry has the form:
272 (FACE SPEC [NOW [COMMENT]])
274 SPEC is stored as the saved value for FACE, as well as the value for the
275 `user' theme. The `user' theme is one of the default themes known to Emacs.
276 See `custom-known-themes' for more information on the known themes.
277 See `custom-theme-set-faces' for more information on the interplay
278 between themes and faces.
279 See `defface' for the format of SPEC.
281 If NOW is present and non-nil, FACE is created now, according to SPEC.
282 COMMENT is a string comment about FACE."
283 (apply 'custom-theme-set-faces
'user args
))
285 (defun custom-theme-set-faces (theme &rest args
)
286 "Initialize faces for theme THEME.
287 The arguments should be a list where each entry has the form:
289 (FACE SPEC [NOW [COMMENT]])
291 SPEC is stored as the saved value for FACE, as well as the value for the
292 `user' theme. The `user' theme is one of the default themes known to Emacs.
293 See `custom-known-themes' for more information on the known themes.
294 See `custom-theme-set-faces' for more information on the interplay
295 between themes and faces.
296 See `defface' for the format of SPEC.
298 If NOW is present and non-nil, FACE is created now, according to SPEC.
299 COMMENT is a string comment about FACE.
301 Several properties of THEME and FACE are used in the process:
303 If THEME property `theme-immediate' is non-nil, this is equivalent of
304 providing the NOW argument to all faces in the argument list: FACE is
305 created now. The only difference is FACE property `force-face': if NOW
306 is non-nil, FACE property `force-face' is set to the symbol `rogue', else
307 if THEME property `theme-immediate' is non-nil, FACE property `force-face'
308 is set to the symbol `immediate'.
310 SPEC itself is saved in FACE property `saved-face' and it is stored in
311 FACE's list property `theme-face' \(using `custom-push-theme')."
312 (custom-check-theme theme
)
313 (let ((immediate (get theme
'theme-immediate
)))
315 (let ((entry (car args
)))
317 (let ((face (nth 0 entry
))
320 (comment (nth 3 entry
)))
321 (put face
'saved-face spec
)
322 (put face
'saved-face-comment comment
)
323 (custom-push-theme 'theme-face face theme
'set spec
)
324 (when (or now immediate
)
325 (put face
'force-face
(if now
'rogue
'immediate
)))
326 (when (or now immediate
(facep face
))
328 (make-empty-face face
))
329 (put face
'face-comment comment
)
330 (face-spec-set face spec
))
331 (setq args
(cdr args
)))
332 ;; Old format, a plist of FACE SPEC pairs.
333 (let ((face (nth 0 args
))
335 (put face
'saved-face spec
)
336 (custom-push-theme 'theme-face face theme
'set spec
))
337 (setq args
(cdr (cdr args
))))))))
340 (defun custom-theme-face-value (face theme
)
341 "Return spec of FACE in THEME if THEME modifies FACE.
342 Value is nil otherwise. The association between theme and spec for FACE
343 is stored in FACE's property `theme-face'. The appropriate face
344 is retrieved using `custom-theme-value'."
345 ;; Returns car because the value is stored inside a one element list
346 (car-safe (custom-theme-value theme
(get face
'theme-face
))))
348 (defun custom-theme-reset-internal-face (face to-theme
)
349 "Reset FACE to the value defined by TO-THEME.
350 If FACE is not defined in TO-THEME, reset FACE to the standard
351 value. See `custom-theme-face-value'. The standard value is
352 stored in SYMBOL's property `face-defface-spec' by `defface'."
353 (let ((spec (custom-theme-face-value face to-theme
))
355 (setq was-in-theme spec
)
356 (setq spec
(or spec
(get face
'face-defface-spec
)))
358 (put face
'save-face was-in-theme
)
359 (when (or (get face
'force-face
) (facep face
))
361 (make-empty-face face
))
362 (face-spec-set face spec
)))
366 (defun custom-theme-reset-faces (theme &rest args
)
367 "Reset the value of the face to values previously defined.
368 Associate this setting with THEME.
370 ARGS is a list of lists of the form
374 This means reset FACE to its value in TO-THEME."
375 (custom-check-theme theme
)
376 (mapcar '(lambda (arg)
377 (apply 'custom-theme-reset-internal-face arg
)
378 (custom-push-theme 'theme-face
(car arg
) theme
'reset
(cadr arg
)))
382 (defun custom-reset-faces (&rest args
)
383 "Reset the value of the face to values previously saved.
384 This is the setting assosiated the `user' theme.
386 ARGS is defined as for `custom-theme-reset-faces'"
387 (apply 'custom-theme-reset-faces
'user args
))
393 ;;; arch-tag: 9a5c4b63-0d27-4c92-a5af-f2c7ed764c2b
394 ;;; cus-face.el ends here