Comment fix.
[bpt/emacs.git] / lisp / facemenu.el
CommitLineData
4e8aa578 1;;; facemenu.el -- Create a face menu for interactively adding fonts to text
732be465 2;; Copyright (c) 1994, 1995 Free Software Foundation, Inc.
4e8aa578
RS
3
4;; Author: Boris Goldowsky <boris@cs.rochester.edu>
5;; Keywords: faces
6
7;; This file is part of GNU Emacs.
8
9;; GNU Emacs is free software; you can redistribute it and/or modify
10;; it under the terms of the GNU General Public License as published by
11;; the Free Software Foundation; either version 2, or (at your option)
12;; any later version.
13
14;; GNU Emacs is distributed in the hope that it will be useful,
15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;; GNU General Public License for more details.
18
19;; You should have received a copy of the GNU General Public License
20;; along with GNU Emacs; see the file COPYING. If not, write to
21;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22
23;;; Commentary:
bf7d4561
BG
24;; This file defines a menu of faces (bold, italic, etc) which allows you to
25;; set the face used for a region of the buffer. Some faces also have
26;; keybindings, which are shown in the menu. Faces with names beginning with
88d690a9 27;; "fg:" or "bg:", as in "fg:red", are treated specially.
bf7d4561
BG
28;; Such faces are assumed to consist only of a foreground (if "fg:") or
29;; background (if "bg:") color. They are thus put into the color submenus
88d690a9
RS
30;; rather than the general Face submenu. These faces can also be
31;; automatically created by selecting the "Other..." menu items in the
32;; "Foreground" and "Background" submenus.
33;;
34;; The menu also contains submenus for indentation and justification-changing
35;; commands.
4e8aa578 36
4e8aa578 37;;; Usage:
bf7d4561
BG
38;; Selecting a face from the menu or typing the keyboard equivalent will
39;; change the region to use that face. If you use transient-mark-mode and the
40;; region is not active, the face will be remembered and used for the next
41;; insertion. It will be forgotten if you move point or make other
42;; modifications before inserting or typing anything.
4e8aa578
RS
43;;
44;; Faces can be selected from the keyboard as well.
88d690a9
RS
45;; The standard keybindings are M-g (or ESC g) + letter:
46;; M-g i = "set italic", M-g b = "set bold", etc.
4e8aa578
RS
47
48;;; Customization:
49;; An alternative set of keybindings that may be easier to type can be set up
88d690a9
RS
50;; using "Alt" or "Hyper" keys. This requires that you either have or create
51;; an Alt or Hyper key on your keyboard. On my keyboard, there is a key
52;; labeled "Alt", but to make it act as an Alt key I have to put this command
53;; into my .xinitrc:
54;; xmodmap -e "add Mod3 = Alt_L"
55;; Or, I can make it into a Hyper key with this:
4e8aa578 56;; xmodmap -e "keysym Alt_L = Hyper_L" -e "add Mod2 = Hyper_L"
88d690a9
RS
57;; Check with local X-perts for how to do it on your system.
58;; Then you can define your keybindings with code like this in your .emacs:
4e8aa578
RS
59;; (setq facemenu-keybindings
60;; '((default . [?\H-d])
61;; (bold . [?\H-b])
62;; (italic . [?\H-i])
88d690a9 63;; (bold-italic . [?\H-l])
4e8aa578
RS
64;; (underline . [?\H-u])))
65;; (setq facemenu-keymap global-map)
66;; (setq facemenu-key nil)
88d690a9
RS
67;; (define-key global-map [?\H-c] 'facemenu-set-foreground) ; set fg color
68;; (define-key global-map [?\H-C] 'facemenu-set-background) ; set bg color
69;; (require 'facemenu)
4e8aa578 70;;
88d690a9
RS
71;; The order of the faces that appear in the menu and their keybindings can be
72;; controlled by setting the variables `facemenu-keybindings' and
73;; `facemenu-new-faces-at-end'. List faces that you don't use in documents
74;; (eg, `region') in `facemenu-unlisted-faces'.
4e8aa578
RS
75
76;;; Known Problems:
88d690a9
RS
77;; Bold and Italic do not combine to create bold-italic if you select them
78;; both, although most other combinations (eg bold + underline + some color)
79;; do the intuitive thing.
80;;
4e8aa578
RS
81;; There is at present no way to display what the faces look like in
82;; the menu itself.
83;;
84;; `list-faces-display' shows the faces in a different order than
85;; this menu, which could be confusing. I do /not/ sort the list
86;; alphabetically, because I like the default order: it puts the most
87;; basic, common fonts first.
88;;
89;; Please send me any other problems, comments or ideas.
90
91;;; Code:
92
93(provide 'facemenu)
94
9dc90430
BG
95;;; Provide some binding for startup:
96;;;###autoload (define-key global-map "\M-g" 'facemenu-keymap)
97;;;###autoload (autoload 'facemenu-keymap "facemenu" "Keymap for face-changing commands." t 'keymap)
98
d2eafd88 99(defvar facemenu-key "\M-g"
9dc90430 100 "Prefix key to use for facemenu commands.")
4e8aa578 101
4e8aa578
RS
102(defvar facemenu-keybindings
103 '((default . "d")
104 (bold . "b")
105 (italic . "i")
88d690a9 106 (bold-italic . "l") ; {bold} intersect {italic} = {l}
4e8aa578
RS
107 (underline . "u"))
108 "Alist of interesting faces and keybindings.
109Each element is itself a list: the car is the name of the face,
110the next element is the key to use as a keyboard equivalent of the menu item;
111the binding is made in facemenu-keymap.
112
113The faces specifically mentioned in this list are put at the top of
114the menu, in the order specified. All other faces which are defined,
115except for those in `facemenu-unlisted-faces', are listed after them,
116but get no keyboard equivalents.
117
118If you change this variable after loading facemenu.el, you will need to call
119`facemenu-update' to make it take effect.")
120
88d690a9
RS
121(defvar facemenu-new-faces-at-end t
122 "Where in the menu to insert newly-created faces.
123This should be nil to put them at the top of the menu, or t to put them
124just before \"Other\" at the end.")
125
4e8aa578 126(defvar facemenu-unlisted-faces
da627a71
BG
127 '(modeline region secondary-selection highlight scratch-face
128 font-lock-comment-face font-lock-string-face font-lock-keyword-face
129 font-lock-function-name-face font-lock-variable-name-face
130 font-lock-type-face font-lock-reference-face)
88d690a9 131 "List of faces not to include in the Face menu.
4e8aa578 132Set this before loading facemenu.el, or call `facemenu-update' after
88d690a9 133changing it.
4e8aa578 134
88d690a9
RS
135If this variable is t, no faces will be added to the menu. This is useful for
136temporarily turning off the feature that automatically adds faces to the menu
137when they are created.")
138
9dc90430 139;;;###autoload
88d690a9 140(defvar facemenu-face-menu
bf7d4561 141 (let ((map (make-sparse-keymap "Face")))
88d690a9 142 (define-key map "o" (cons "Other..." 'facemenu-set-face))
bf7d4561
BG
143 map)
144 "Menu keymap for faces.")
9dc90430 145;;;###autoload
88d690a9 146(defalias 'facemenu-face-menu facemenu-face-menu)
bf7d4561 147
9dc90430 148;;;###autoload
bf7d4561
BG
149(defvar facemenu-foreground-menu
150 (let ((map (make-sparse-keymap "Foreground Color")))
151 (define-key map "o" (cons "Other" 'facemenu-set-foreground))
152 map)
153 "Menu keymap for foreground colors.")
9dc90430 154;;;###autoload
88d690a9 155(defalias 'facemenu-foreground-menu facemenu-foreground-menu)
bf7d4561 156
9dc90430 157;;;###autoload
bf7d4561
BG
158(defvar facemenu-background-menu
159 (let ((map (make-sparse-keymap "Background Color")))
160 (define-key map "o" (cons "Other" 'facemenu-set-background))
161 map)
162 "Menu keymap for background colors")
9dc90430 163;;;###autoload
88d690a9 164(defalias 'facemenu-background-menu facemenu-background-menu)
bf7d4561 165
9dc90430 166;;;###autoload
bf7d4561
BG
167(defvar facemenu-special-menu
168 (let ((map (make-sparse-keymap "Special")))
169 (define-key map [read-only] (cons "Read-Only" 'facemenu-set-read-only))
170 (define-key map [invisible] (cons "Invisible" 'facemenu-set-invisible))
7c49006b 171 (define-key map [intangible] (cons "Intangible" 'facemenu-set-intangible))
bf7d4561
BG
172 map)
173 "Menu keymap for non-face text-properties.")
9dc90430 174;;;###autoload
88d690a9
RS
175(defalias 'facemenu-special-menu facemenu-special-menu)
176
9dc90430 177;;;###autoload
88d690a9
RS
178(defvar facemenu-justification-menu
179 (let ((map (make-sparse-keymap "Justification")))
9dc90430
BG
180 (define-key map [?c] (cons "Center" 'set-justification-center))
181 (define-key map [?b] (cons "Full" 'set-justification-full))
182 (define-key map [?r] (cons "Right" 'set-justification-right))
183 (define-key map [?l] (cons "Left" 'set-justification-left))
184 (define-key map [?u] (cons "Unfilled" 'set-justification-none))
88d690a9
RS
185 map)
186 "Submenu for text justification commands.")
9dc90430 187;;;###autoload
88d690a9
RS
188(defalias 'facemenu-justification-menu facemenu-justification-menu)
189
9dc90430 190;;;###autoload
88d690a9
RS
191(defvar facemenu-indentation-menu
192 (let ((map (make-sparse-keymap "Indentation")))
193 (define-key map [UnIndentRight]
194 (cons "UnIndentRight" 'decrease-right-margin))
195 (define-key map [IndentRight]
196 (cons "IndentRight" 'increase-right-margin))
197 (define-key map [Unindent]
198 (cons "UnIndent" 'decrease-left-margin))
199 (define-key map [Indent]
200 (cons "Indent" 'increase-left-margin))
201 map)
202 "Submenu for indentation commands.")
9dc90430 203;;;###autoload
88d690a9 204(defalias 'facemenu-indentation-menu facemenu-indentation-menu)
bf7d4561 205
9dc90430 206;;;###autoload
bf7d4561
BG
207(defvar facemenu-menu
208 (let ((map (make-sparse-keymap "Face")))
88d690a9
RS
209 (define-key map [dc] (cons "Display Colors" 'list-colors-display))
210 (define-key map [df] (cons "Display Faces" 'list-faces-display))
c0a7db84
BG
211 (define-key map [dp] (cons "List Properties" 'list-text-properties-at))
212 (define-key map [rm] (cons "Remove Properties" 'facemenu-remove-all))
88d690a9
RS
213 (define-key map [s1] (list "-----------------"))
214 (define-key map [in] (cons "Indentation" 'facemenu-indentation-menu))
215 (define-key map [ju] (cons "Justification" 'facemenu-justification-menu))
216 (define-key map [s2] (list "-----------------"))
217 (define-key map [sp] (cons "Special Props" 'facemenu-special-menu))
218 (define-key map [bg] (cons "Background Color" 'facemenu-background-menu))
219 (define-key map [fg] (cons "Foreground Color" 'facemenu-foreground-menu))
220 (define-key map [fc] (cons "Face" 'facemenu-face-menu))
bf7d4561 221 map)
535d2617 222 "Facemenu top-level menu keymap.")
9dc90430 223;;;###autoload
88d690a9 224(defalias 'facemenu-menu facemenu-menu)
bf7d4561 225
88d690a9
RS
226(defvar facemenu-keymap
227 (let ((map (make-sparse-keymap "Set face")))
228 (define-key map "o" (cons "Other" 'facemenu-set-face))
229 map)
9dc90430 230 "Keymap for face-changing commands.
bf7d4561 231`Facemenu-update' fills in the keymap according to the bindings
535d2617 232requested in `facemenu-keybindings'.")
88d690a9 233(defalias 'facemenu-keymap facemenu-keymap)
bf7d4561
BG
234
235;;; Internal Variables
236
237(defvar facemenu-color-alist nil
238 ;; Don't initialize here; that doesn't work if preloaded.
239 "Alist of colors, used for completion.
240If null, `facemenu-read-color' will set it.")
4a24b314 241
4e8aa578 242(defun facemenu-update ()
bf7d4561
BG
243 "Add or update the \"Face\" menu in the menu bar.
244You can call this to update things if you change any of the menu configuration
245variables."
4e8aa578
RS
246 (interactive)
247
bf7d4561 248 ;; Global bindings:
88d690a9
RS
249 (define-key global-map [C-down-mouse-2] 'facemenu-menu)
250 (if facemenu-key (define-key global-map facemenu-key 'facemenu-keymap))
4e8aa578 251
bf7d4561
BG
252 ;; Add each defined face to the menu.
253 (facemenu-iterate 'facemenu-add-new-face
254 (facemenu-complete-face-list facemenu-keybindings)))
4a24b314 255
4e8aa578
RS
256;;;###autoload
257(defun facemenu-set-face (face &optional start end)
4a24b314
RS
258 "Add FACE to the region or next character typed.
259It will be added to the top of the face list; any faces lower on the list that
260will not show through at all will be removed.
261
262Interactively, the face to be used is prompted for.
263If the region is active, it will be set to the requested face. If
4e8aa578 264it is inactive \(even if mark-even-if-inactive is set) the next
88d690a9 265character that is typed \(or otherwise inserted) will be set to
f61deddc 266the selected face. Moving point or switching buffers before
4e8aa578
RS
267typing a character cancels the request."
268 (interactive (list (read-face-name "Use face: ")))
88d690a9
RS
269 (barf-if-buffer-read-only)
270 (facemenu-add-new-face face)
4e8aa578 271 (if mark-active
4a24b314
RS
272 (let ((start (or start (region-beginning)))
273 (end (or end (region-end))))
274 (facemenu-add-face face start end))
7fce8c91 275 (facemenu-self-insert-face face)))
4a24b314 276
bf7d4561 277;;;###autoload
4a24b314
RS
278(defun facemenu-set-foreground (color &optional start end)
279 "Set the foreground color of the region or next character typed.
280The color is prompted for. A face named `fg:color' is used \(or created).
281If the region is active, it will be set to the requested face. If
282it is inactive \(even if mark-even-if-inactive is set) the next
283character that is typed \(via `self-insert-command') will be set to
f61deddc 284the selected face. Moving point or switching buffers before
4a24b314
RS
285typing a character cancels the request."
286 (interactive (list (facemenu-read-color "Foreground color: ")))
287 (let ((face (intern (concat "fg:" color))))
288 (or (facemenu-get-face face)
289 (error "Unknown color: %s" color))
290 (facemenu-set-face face start end)))
291
bf7d4561 292;;;###autoload
4a24b314
RS
293(defun facemenu-set-background (color &optional start end)
294 "Set the background color of the region or next character typed.
295The color is prompted for. A face named `bg:color' is used \(or created).
296If the region is active, it will be set to the requested face. If
297it is inactive \(even if mark-even-if-inactive is set) the next
298character that is typed \(via `self-insert-command') will be set to
f61deddc 299the selected face. Moving point or switching buffers before
4a24b314
RS
300typing a character cancels the request."
301 (interactive (list (facemenu-read-color "Background color: ")))
302 (let ((face (intern (concat "bg:" color))))
303 (or (facemenu-get-face face)
304 (error "Unknown color: %s" color))
305 (facemenu-set-face face start end)))
4e8aa578 306
9dc90430 307;;;###autoload
4e8aa578
RS
308(defun facemenu-set-face-from-menu (face start end)
309 "Set the face of the region or next character typed.
310This function is designed to be called from a menu; the face to use
311is the menu item's name.
312If the region is active, it will be set to the requested face. If
313it is inactive \(even if mark-even-if-inactive is set) the next
88d690a9 314character that is typed \(or otherwise inserted) will be set to
f61deddc 315the selected face. Moving point or switching buffers before
4e8aa578 316typing a character cancels the request."
4a24b314
RS
317 (interactive (list last-command-event
318 (if mark-active (region-beginning))
319 (if mark-active (region-end))))
88d690a9 320 (barf-if-buffer-read-only)
4a24b314 321 (facemenu-get-face face)
4e8aa578 322 (if start
4a24b314 323 (facemenu-add-face face start end)
7fce8c91
RS
324 (facemenu-self-insert-face face)))
325
326(defun facemenu-self-insert-face (face)
41e5bf66
BG
327 (setq self-insert-face (if (eq last-command self-insert-face-command)
328 (cons face (if (listp self-insert-face)
329 self-insert-face
330 (list self-insert-face)))
331 face)
7fce8c91 332 self-insert-face-command this-command))
4e8aa578 333
9dc90430 334;;;###autoload
4e8aa578
RS
335(defun facemenu-set-invisible (start end)
336 "Make the region invisible.
337This sets the `invisible' text property; it can be undone with
338`facemenu-remove-all'."
339 (interactive "r")
340 (put-text-property start end 'invisible t))
341
9dc90430 342;;;###autoload
4e8aa578
RS
343(defun facemenu-set-intangible (start end)
344 "Make the region intangible: disallow moving into it.
345This sets the `intangible' text property; it can be undone with
346`facemenu-remove-all'."
347 (interactive "r")
348 (put-text-property start end 'intangible t))
349
9dc90430 350;;;###autoload
4e8aa578
RS
351(defun facemenu-set-read-only (start end)
352 "Make the region unmodifiable.
353This sets the `read-only' text property; it can be undone with
354`facemenu-remove-all'."
355 (interactive "r")
356 (put-text-property start end 'read-only t))
357
9dc90430 358;;;###autoload
4e8aa578
RS
359(defun facemenu-remove-all (start end)
360 "Remove all text properties that facemenu added to region."
361 (interactive "*r") ; error if buffer is read-only despite the next line.
362 (let ((inhibit-read-only t))
363 (remove-text-properties
364 start end '(face nil invisible nil intangible nil
365 read-only nil category nil))))
366
c0a7db84
BG
367;;;###autoload
368(defun list-text-properties-at (p)
369 "Pop up a buffer listing text-properties at LOCATION."
370 (interactive "d")
371 (let ((props (text-properties-at p)))
372 (if (null props)
373 (message "None")
374 (with-output-to-temp-buffer "*Text Properties*"
375 (princ (format "Text properties at %d:\n\n" p))
376 (while props
377 (princ (format "%-20s %S\n"
378 (car props) (car (cdr props))))
379 (setq props (cdr (cdr props))))))))
380
bf7d4561 381;;;###autoload
da627a71 382(defun facemenu-read-color (&optional prompt)
bf7d4561 383 "Read a color using the minibuffer."
da627a71 384 (let ((col (completing-read (or prompt "Color: ")
bf7d4561
BG
385 (or facemenu-color-alist
386 (if (eq 'x window-system)
387 (mapcar 'list (x-defined-colors))))
388 nil t)))
389 (if (equal "" col)
390 nil
391 col)))
4e8aa578 392
88d690a9
RS
393;;;###autoload
394(defun list-colors-display (&optional list)
7c49006b
RS
395 "Display names of defined colors, and show what they look like.
396If the optional argument LIST is non-nil, it should be a list of
397colors to display. Otherwise, this command computes a list
398of colors that the current display can handle."
88d690a9
RS
399 (interactive)
400 (if (and (null list) (eq 'x window-system))
7c49006b
RS
401 (progn
402 (setq list (x-defined-colors))
403 ;; Delete duplicate colors.
404 (let ((l list))
405 (while (cdr l)
406 (if (facemenu-color-equal (car l) (car (cdr l)))
407 (setcdr l (cdr (cdr l)))
408 (setq l (cdr l)))))))
88d690a9
RS
409 (with-output-to-temp-buffer "*Colors*"
410 (save-excursion
411 (set-buffer standard-output)
412 (let ((facemenu-unlisted-faces t)
413 s)
414 (while list
415 (setq s (point))
416 (insert (car list))
417 (indent-to 20)
418 (put-text-property s (point) 'face
419 (facemenu-get-face
420 (intern (concat "bg:" (car list)))))
421 (setq s (point))
422 (insert " " (car list) "\n")
423 (put-text-property s (point) 'face
424 (facemenu-get-face
425 (intern (concat "fg:" (car list)))))
426 (setq list (cdr list)))))))
427
428(defun facemenu-color-equal (a b)
429 "Return t if colors A and B are the same color.
7c49006b
RS
430A and B should be strings naming colors.
431This function queries the window-system server to find out what the
432color names mean. It returns nil if the colors differ or if it can't
433determine the correct answer."
88d690a9
RS
434 (cond ((equal a b) t)
435 ((and (eq 'x window-system)
436 (equal (x-color-values a) (x-color-values b))))))
437
4a24b314
RS
438(defun facemenu-add-face (face start end)
439 "Add FACE to text between START and END.
440For each section of that region that has a different face property, FACE will
441be consed onto it, and other faces that are completely hidden by that will be
bf7d4561
BG
442removed from the list.
443
444As a special case, if FACE is `default', then the region is left with NO face
445text property. Otherwise, selecting the default face would not have any
446effect."
4a24b314 447 (interactive "*xFace:\nr")
bf7d4561
BG
448 (if (eq face 'default)
449 (remove-text-properties start end '(face default))
450 (let ((part-start start) part-end)
451 (while (not (= part-start end))
452 (setq part-end (next-single-property-change part-start 'face nil end))
453 (let ((prev (get-text-property part-start 'face)))
454 (put-text-property part-start part-end 'face
455 (if (null prev)
456 face
457 (facemenu-discard-redundant-faces
458 (cons face
459 (if (listp prev) prev (list prev)))))))
460 (setq part-start part-end)))))
4a24b314
RS
461
462(defun facemenu-discard-redundant-faces (face-list &optional mask)
463 "Remove from FACE-LIST any faces that won't show at all.
464This means they have no non-nil elements that aren't also non-nil in an
465earlier face."
466 (let ((useful nil))
467 (cond ((null face-list) nil)
468 ((null mask)
469 (cons (car face-list)
470 (facemenu-discard-redundant-faces
471 (cdr face-list)
472 (copy-sequence (internal-get-face (car face-list))))))
473 ((let ((i (length mask))
474 (face (internal-get-face (car face-list))))
475 (while (>= (setq i (1- i)) 0)
476 (if (and (aref face i)
477 (not (aref mask i)))
478 (progn (setq useful t)
479 (aset mask i t))))
480 useful)
481 (cons (car face-list)
482 (facemenu-discard-redundant-faces (cdr face-list) mask)))
483 (t (facemenu-discard-redundant-faces (cdr face-list) mask)))))
484
bf7d4561
BG
485(defun facemenu-get-face (symbol)
486 "Make sure FACE exists.
487If not, it is created. If it is created and is of the form `fg:color', then
488set the foreground to that color. If of the form `bg:color', set the
88d690a9
RS
489background. In any case, add it to the appropriate menu. Returns the face,
490or nil if given a bad color."
491 (if (or (internal-find-face symbol)
492 (let* ((face (make-face symbol))
493 (name (symbol-name symbol))
494 (color (substring name 3)))
495 (cond ((string-match "^fg:" name)
496 (set-face-foreground face color)
497 (and (eq 'x window-system) (x-color-defined-p color)))
498 ((string-match "^bg:" name)
499 (set-face-background face color)
500 (and (eq 'x window-system) (x-color-defined-p color)))
501 (t))))
502 symbol))
bf7d4561
BG
503
504(defun facemenu-add-new-face (face)
505 "Add a FACE to the appropriate Face menu.
506Automatically called when a new face is created."
507 (let* ((name (symbol-name face))
508 (menu (cond ((string-match "^fg:" name)
509 (setq name (substring name 3))
88d690a9 510 'facemenu-foreground-menu)
bf7d4561
BG
511 ((string-match "^bg:" name)
512 (setq name (substring name 3))
88d690a9
RS
513 'facemenu-background-menu)
514 (t 'facemenu-face-menu)))
515 (key (cdr (assoc face facemenu-keybindings)))
516 function menu-val)
517 (cond ((eq t facemenu-unlisted-faces))
518 ((memq face facemenu-unlisted-faces))
519 (key ; has a keyboard equivalent. These go at the front.
520 (setq function (intern (concat "facemenu-set-" name)))
521 (fset function
522 (` (lambda () (interactive)
523 (facemenu-set-face (quote (, face))))))
524 (define-key 'facemenu-keymap key (cons name function))
525 (define-key menu key (cons name function)))
526 ((facemenu-iterate ; check if equivalent face is already in the menu
527 (lambda (m) (and (listp m)
528 (symbolp (car m))
529 (face-equal (car m) face)))
530 (cdr (symbol-function menu))))
531 (t ; No keyboard equivalent. Figure out where to put it:
532 (setq key (vector face)
533 function 'facemenu-set-face-from-menu
534 menu-val (symbol-function menu))
535 (if (and facemenu-new-faces-at-end
536 (> (length menu-val) 3))
537 (define-key-after menu-val key (cons name function)
538 (car (nth (- (length menu-val) 3) menu-val)))
539 (define-key menu key (cons name function))))))
540 nil) ; Return nil for facemenu-iterate
bf7d4561 541
bf7d4561
BG
542(defun facemenu-complete-face-list (&optional oldlist)
543 "Return list of all faces that are look different.
544Starts with given ALIST of faces, and adds elements only if they display
545differently from any face already on the list.
546The faces on ALIST will end up at the end of the returned list, in reverse
547order."
548 (let ((list (nreverse (mapcar 'car oldlist))))
549 (facemenu-iterate
550 (lambda (new-face)
551 (if (not (memq new-face list))
552 (setq list (cons new-face list)))
553 nil)
554 (nreverse (face-list)))
555 list))
556
4e8aa578
RS
557(defun facemenu-iterate (func iterate-list)
558 "Apply FUNC to each element of LIST until one returns non-nil.
559Returns the non-nil value it found, or nil if all were nil."
560 (while (and iterate-list (not (funcall func (car iterate-list))))
561 (setq iterate-list (cdr iterate-list)))
562 (car iterate-list))
563
564(facemenu-update)
4e8aa578
RS
565
566;;; facemenu.el ends here