*** empty log message ***
[bpt/emacs.git] / lisp / cus-face.el
CommitLineData
e8af40ee 1;;; cus-face.el --- customization support for faces
d543e20b 2;;
51a1edab 3;; Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc.
d543e20b
PA
4;;
5;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
6;; Keywords: help, faces
5f0cfe8b 7;; Version: Emacs
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
13;; the Free Software Foundation; either version 2, or (at your option)
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
23;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24;; Boston, MA 02111-1307, 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
RS
39 (unless (get face 'face-defface-spec)
40 (put face 'face-defface-spec spec)
d543e20b 41 (when (fboundp 'facep)
6c283d44 42 (unless (facep face)
d543e20b
PA
43 ;; If the user has already created the face, respect that.
44 (let ((value (or (get face 'saved-face) spec))
6c283d44 45 (frames (frame-list))
d543e20b
PA
46 frame)
47 ;; Create global face.
48 (make-empty-face face)
d543e20b
PA
49 ;; Create frame local faces
50 (while frames
51 (setq frame (car frames)
52 frames (cdr frames))
971e48ca
RS
53 (face-spec-set face value frame)))
54 ;; When making a face after frames already exist
55 (if (memq window-system '(x w32))
56 (make-face-x-resource-internal face))))
209ddde3 57 (when (and doc (null (face-documentation face)))
08449ec1 58 (set-face-documentation face (purecopy doc)))
d543e20b
PA
59 (custom-handle-all-keywords face args 'custom-face)
60 (run-hooks 'custom-define-hook))
61 face)
62
da0b1f56
GM
63;;; Face attributes.
64
d543e20b 65(defconst custom-face-attributes
da0b1f56 66 '((:family
c165ad40
MB
67 (string :tag "Font Family"
68 :help-echo "Font family or fontset alias name."))
da0b1f56
GM
69
70 (:width
71 (choice :tag "Width"
72 :help-echo "Font width."
c165ad40 73 :value normal ; default
da0b1f56
GM
74 (const :tag "compressed" condensed)
75 (const :tag "condensed" condensed)
76 (const :tag "demiexpanded" semi-expanded)
77 (const :tag "expanded" expanded)
78 (const :tag "extracondensed" extra-condensed)
79 (const :tag "extraexpanded" extra-expanded)
80 (const :tag "medium" normal)
81 (const :tag "narrow" condensed)
82 (const :tag "normal" normal)
83 (const :tag "regular" normal)
84 (const :tag "semicondensed" semi-condensed)
85 (const :tag "semiexpanded" semi-expanded)
86 (const :tag "ultracondensed" ultra-condensed)
87 (const :tag "ultraexpanded" ultra-expanded)
51a1edab 88 (const :tag "wide" extra-expanded)))
da0b1f56
GM
89
90 (:height
91 (choice :tag "Height"
92 :help-echo "Face's font height."
c165ad40 93 :value 1.0 ; default
6bca3005 94 (integer :tag "Height in 1/10 pt")
51a1edab 95 (number :tag "Scale" 1.0)))
6bca3005 96
da0b1f56
GM
97 (:weight
98 (choice :tag "Weight"
99 :help-echo "Font weight."
c165ad40 100 :value normal ; default
992f7c96 101 (const :tag "black" ultra-bold)
da0b1f56
GM
102 (const :tag "bold" bold)
103 (const :tag "book" semi-light)
104 (const :tag "demibold" semi-bold)
105 (const :tag "extralight" extra-light)
106 (const :tag "extrabold" extra-bold)
107 (const :tag "heavy" extra-bold)
108 (const :tag "light" light)
109 (const :tag "medium" normal)
110 (const :tag "normal" normal)
111 (const :tag "regular" normal)
112 (const :tag "semibold" semi-bold)
113 (const :tag "semilight" semi-light)
114 (const :tag "ultralight" ultra-light)
51a1edab 115 (const :tag "ultrabold" ultra-bold)))
da0b1f56
GM
116
117 (:slant
118 (choice :tag "Slant"
119 :help-echo "Font slant."
c165ad40 120 :value normal ; default
da0b1f56
GM
121 (const :tag "italic" italic)
122 (const :tag "oblique" oblique)
51a1edab 123 (const :tag "normal" normal)))
da0b1f56
GM
124
125 (:underline
126 (choice :tag "Underline"
127 :help-echo "Control text underlining."
c165ad40 128 (const :tag "Off" nil)
da0b1f56 129 (const :tag "On" t)
51a1edab 130 (color :tag "Colored")))
da0b1f56
GM
131
132 (:overline
133 (choice :tag "Overline"
134 :help-echo "Control text overlining."
c165ad40 135 (const :tag "Off" nil)
da0b1f56 136 (const :tag "On" t)
51a1edab 137 (color :tag "Colored")))
da0b1f56
GM
138
139 (:strike-through
140 (choice :tag "Strike-through"
141 :help-echo "Control text strike-through."
c165ad40 142 (const :tag "Off" nil)
da0b1f56 143 (const :tag "On" t)
51a1edab 144 (color :tag "Colored")))
da0b1f56
GM
145
146 (:box
1743c17a 147 ;; Fixme: this can probably be done better.
da0b1f56
GM
148 (choice :tag "Box around text"
149 :help-echo "Control box around text."
c165ad40 150 (const :tag "Off" nil)
da0b1f56 151 (list :tag "Box"
36b80a0d 152 :value (:line-width 2 :color "grey75" :style released-button)
1743c17a 153 (const :format "" :value :line-width)
da0b1f56 154 (integer :tag "Width")
1743c17a
DL
155 (const :format "" :value :color)
156 (choice :tag "Color" (const :tag "*" nil) color)
157 (const :format "" :value :style)
158 (choice :tag "Style"
159 (const :tag "Raised" released-button)
160 (const :tag "Sunken" pressed-button)
161 (const :tag "None" nil))))
51a1edab
MB
162 ;; filter to make value suitable for customize
163 (lambda (real-value)
c165ad40
MB
164 (and real-value
165 (let ((lwidth
166 (or (and (consp real-value)
167 (plist-get real-value :line-width))
168 (and (integerp real-value) real-value)
169 1))
170 (color
171 (or (and (consp real-value) (plist-get real-value :color))
172 (and (stringp real-value) real-value)
173 nil))
174 (style
175 (and (consp real-value) (plist-get real-value :style))))
176 (list :line-width lwidth :color color :style style))))
36b80a0d
MB
177 ;; filter to make customized-value suitable for storing
178 (lambda (cus-value)
c165ad40
MB
179 (and cus-value
180 (let ((lwidth (plist-get cus-value :line-width))
181 (color (plist-get cus-value :color))
182 (style (plist-get cus-value :style)))
183 (cond ((and (null color) (null style))
184 lwidth)
185 ((and (null lwidth) (null style))
186 ;; actually can't happen, because LWIDTH is always an int
187 color)
188 (t
189 ;; Keep as a plist, but remove null entries
190 (nconc (and lwidth `(:line-width ,lwidth))
191 (and color `(:color ,color))
192 (and style `(:style ,style)))))))))
da0b1f56
GM
193
194 (:inverse-video
195 (choice :tag "Inverse-video"
196 :help-echo "Control whether text should be in inverse-video."
c165ad40
MB
197 (const :tag "Off" nil)
198 (const :tag "On" t)))
da0b1f56
GM
199
200 (:foreground
c165ad40
MB
201 (color :tag "Foreground"
202 :help-echo "Set foreground color."))
da0b1f56
GM
203
204 (:background
c165ad40
MB
205 (color :tag "Background"
206 :help-echo "Set background color."))
da0b1f56
GM
207
208 (:stipple
209 (choice :tag "Stipple"
675f1fcb 210 :help-echo "Background bit-mask"
c165ad40 211 (const :tag "None" nil)
675f1fcb
MB
212 (file :tag "File"
213 :help-echo "Name of bitmap file."
214 :must-match t)))
6bca3005
MB
215
216 (:inherit
217 (repeat :tag "Inherit"
218 :help-echo "List of faces to inherit attributes from."
219 (face :Tag "Face" default))
51a1edab
MB
220 ;; filter to make value suitable for customize
221 (lambda (real-value)
222 (cond ((or (null real-value) (eq real-value 'unspecified))
223 nil)
224 ((symbolp real-value)
225 (list real-value))
226 (t
227 real-value)))
228 ;; filter to make customized-value suitable for storing
229 (lambda (cus-value)
230 (if (and (consp cus-value) (null (cdr cus-value)))
231 (car cus-value)
232 cus-value))))
da0b1f56
GM
233
234 "Alist of face attributes.
235
51a1edab
MB
236The elements are of the form (KEY TYPE PRE-FILTER POST-FILTER),
237where KEY is the name of the attribute, TYPE is a widget type for
238editing the attribute, PRE-FILTER is a function to make the attribute's
239value suitable for the customization widget, and POST-FILTER is a
240function to make the customized value suitable for storing. PRE-FILTER
241and POST-FILTER are optional.
d543e20b 242
51a1edab
MB
243The PRE-FILTER should take a single argument, the attribute value as
244stored, and should return a value for customization (using the
245customization type TYPE).
d543e20b 246
51a1edab
MB
247The POST-FILTER should also take a single argument, the value after
248being customized, and should return a value suitable for setting the
249given face attribute.")
d543e20b 250
da0b1f56 251
d543e20b 252(defun custom-face-attributes-get (face frame)
6c283d44
RS
253 "For FACE on FRAME, return an alternating list describing its attributes.
254The list has the form (KEYWORD VALUE KEYWORD VALUE...).
d543e20b
PA
255Each keyword should be listed in `custom-face-attributes'.
256
6c283d44 257If FRAME is nil, use the global defaults for FACE."
da0b1f56
GM
258 (let ((attrs custom-face-attributes)
259 plist)
260 (while attrs
261 (let* ((attribute (car (car attrs)))
262 (value (face-attribute face attribute frame)))
263 (setq attrs (cdr attrs))
6bca3005
MB
264 (unless (or (eq value 'unspecified)
265 (and (null value) (memq attribute '(:inherit))))
da0b1f56
GM
266 (setq plist (cons attribute (cons value plist))))))
267 plist))
d543e20b 268
d543e20b
PA
269;;; Initializing.
270
d543e20b
PA
271;;;###autoload
272(defun custom-set-faces (&rest args)
273 "Initialize faces according to user preferences.
274The arguments should be a list where each entry has the form:
275
1743c17a 276 (FACE SPEC [NOW [COMMENT]])
d543e20b 277
6c283d44
RS
278SPEC is stored as the saved value for FACE.
279If NOW is present and non-nil, FACE is created now, according to SPEC.
1743c17a 280COMMENT is a string comment about FACE.
d543e20b
PA
281
282See `defface' for the format of SPEC."
283 (while args
284 (let ((entry (car args)))
285 (if (listp entry)
286 (let ((face (nth 0 entry))
287 (spec (nth 1 entry))
1743c17a
DL
288 (now (nth 2 entry))
289 (comment (nth 3 entry)))
d543e20b 290 (put face 'saved-face spec)
1743c17a 291 (put face 'saved-face-comment comment)
d543e20b
PA
292 (when now
293 (put face 'force-face t))
6c283d44 294 (when (or now (facep face))
1743c17a 295 (put face 'face-comment comment)
6c283d44
RS
296 (make-empty-face face)
297 (face-spec-set face spec))
d543e20b
PA
298 (setq args (cdr args)))
299 ;; Old format, a plist of FACE SPEC pairs.
300 (let ((face (nth 0 args))
301 (spec (nth 1 args)))
302 (put face 'saved-face spec))
303 (setq args (cdr (cdr args)))))))
304
305;;; The End.
306
307(provide 'cus-face)
308
1743c17a 309;;; cus-face.el ends here