]> code.delx.au - gnu-emacs/blobdiff - lisp/cus-edit.el
(japanese-katakana-region): Fix handling HANKAKU argument.
[gnu-emacs] / lisp / cus-edit.el
index cb6e8282038815dc8e38719e0864ba47f5df1358..ae4277ea098d1170b2300d60bcd2009331f7236a 100644 (file)
@@ -1,10 +1,9 @@
-;;; cus-edit.el --- Tools for customizating Emacs and Lisp packages.
+;;; cus-edit.el --- Tools for customizing Emacs and Lisp packages.
 ;;
-;; Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc.
 ;;
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Keywords: help, faces
-;; X-URL: http://www.dina.kvl.dk/~abraham/custom/ (probably obsolete)
 
 ;; This file is part of GNU Emacs.
 
@@ -37,9 +36,7 @@
 
 (require 'cus-face)
 (require 'wid-edit)
-(require 'easymenu)
 (eval-when-compile
-  (require 'cl)
   (defvar custom-versions-load-alist)) ; from cus-load
 
 (condition-case nil
 (defun custom-quote (sexp)
   "Quote SEXP iff it is not self quoting."
   (if (or (memq sexp '(t nil))
-         (and (symbolp sexp)
-              (eq (aref (symbol-name sexp) 0) ?:))
+         (keywordp sexp)
          (and (listp sexp)
               (memq (car sexp) '(lambda)))
          (stringp sexp)
@@ -387,7 +383,6 @@ IF REGEXP is not a string, return it unchanged."
     regexp))
 
 (defun custom-variable-prompt ()
-  ;; Code stolen from `help.el'.
   "Prompt for a variable, defaulting to the variable at point.
 Return a list suitable for use in `interactive'."
    (let ((v (variable-at-point))
@@ -401,7 +396,7 @@ Return a list suitable for use in `interactive'."
                          (and (boundp symbol)
                               (or (get symbol 'custom-type)
                                   (get symbol 'custom-loads)
-                                  (user-variable-p symbol)))) t))
+                                  (get symbol 'standard-value)))) t))
      (list (if (equal val "")
               (if (symbolp v) v nil)
             (intern val)))))
@@ -426,7 +421,7 @@ WIDGET is the widget to apply the filter entries of MENU on."
 ;;; Unlispify.
 
 (defvar custom-prefix-list nil
-  "List of prefixes that should be ignored by `custom-unlispify'")
+  "List of prefixes that should be ignored by `custom-unlispify'.")
 
 (defcustom custom-unlispify-menu-entries t
   "Display menu entries as words instead of symbols if non nil."
@@ -439,7 +434,7 @@ WIDGET is the widget to apply the filter entries of MENU on."
   :type 'boolean)
 
 (defun custom-unlispify-menu-entry (symbol &optional no-suffix)
-  "Convert symbol into a menu entry."
+  "Convert SYMBOL into a menu entry."
   (cond ((not custom-unlispify-menu-entries)
         (symbol-name symbol))
        ((get symbol 'custom-tag)
@@ -479,12 +474,12 @@ WIDGET is the widget to apply the filter entries of MENU on."
   :type 'boolean)
 
 (defun custom-unlispify-tag-name (symbol)
-  "Convert symbol into a menu entry."
+  "Convert SYMBOL into a menu entry."
   (let ((custom-unlispify-menu-entries custom-unlispify-tag-names))
     (custom-unlispify-menu-entry symbol t)))
 
 (defun custom-prefix-add (symbol prefixes)
-  ;; Addd SYMBOL to list of ignored PREFIXES.
+  "Add SYMBOL to list of ignored PREFIXES."
   (cons (or (get symbol 'custom-prefix)
            (concat (symbol-name symbol) "-"))
        prefixes))
@@ -611,7 +606,7 @@ groups after non-groups, if nil do not order groups at all."
   (sort (copy-sequence items)
    (lambda (a b)
      (let ((typea (nth 1 a)) (typeb (nth 1 b))
-          (namea (symbol-name (nth 0 a))) (nameb (symbol-name (nth 0 b))))
+          (namea (nth 0 a)) (nameb (nth 0 b)))
        (cond ((not order-groups)
              ;; Since we don't care about A and B order, maybe sort.
              (when sort-alphabetically
@@ -638,29 +633,29 @@ groups after non-groups, if nil do not order groups at all."
   "Set changes in all modified options."
   (interactive)
   (let ((children custom-options))
-    (mapcar (lambda (child)
-             (when (eq (widget-get child :custom-state) 'modified)
-               (widget-apply child :custom-set)))
+    (mapc (lambda (child)
+           (when (eq (widget-get child :custom-state) 'modified)
+             (widget-apply child :custom-set)))
            children)))
 
 (defun Custom-save ()
   "Set all modified group members and save them."
   (interactive)
   (let ((children custom-options))
-    (mapcar (lambda (child)
-             (when (memq (widget-get child :custom-state)
-                         '(modified set changed rogue))
-               (widget-apply child :custom-save)))
+    (mapc (lambda (child)
+           (when (memq (widget-get child :custom-state)
+                       '(modified set changed rogue))
+             (widget-apply child :custom-save)))
            children))
   (custom-save-all))
 
 (defvar custom-reset-menu
   '(("Current" . Custom-reset-current)
     ("Saved" . Custom-reset-saved)
-    ("Standard Settings" . Custom-reset-standard))
+    ("Erase Customization (use standard settings)" . Custom-reset-standard))
   "Alist of actions for the `Reset' button.
 The key is a string containing the name of the action, the value is a
-lisp function taking the widget as an element which will be called
+Lisp function taking the widget as an element which will be called
 when the action is chosen.")
 
 (defun custom-reset (event)
@@ -676,33 +671,36 @@ when the action is chosen.")
   "Reset all modified group members to their current value."
   (interactive)
   (let ((children custom-options))
-    (mapcar (lambda (widget)
-             (and (default-boundp (widget-value widget))
-                  (if (memq (widget-get widget :custom-state)
-                            '(modified changed))
-                      (widget-apply widget :custom-reset-current))))
+    (mapc (lambda (widget)
+           (and (default-boundp (widget-value widget))
+                (if (memq (widget-get widget :custom-state)
+                          '(modified changed))
+                    (widget-apply widget :custom-reset-current))))
            children)))
 
 (defun Custom-reset-saved (&rest ignore)
   "Reset all modified or set group members to their saved value."
   (interactive)
   (let ((children custom-options))
-    (mapcar (lambda (widget)
-             (and (get (widget-value widget) 'saved-value)
-                  (if (memq (widget-get widget :custom-state)
-                            '(modified set changed rogue))
-                      (widget-apply widget :custom-reset-saved))))
+    (mapc (lambda (widget)
+           (and (get (widget-value widget) 'saved-value)
+                (if (memq (widget-get widget :custom-state)
+                          '(modified set changed rogue))
+                    (widget-apply widget :custom-reset-saved))))
            children)))
 
 (defun Custom-reset-standard (&rest ignore)
-  "Reset all modified, set, or saved group members to their standard settings."
+  "Erase all customization (either current or saved) for the group members.
+The immediate result is to restore them to their standard settings.
+This operation eliminates any saved settings for the group members,
+making them as if they had never been customized at all."
   (interactive)
   (let ((children custom-options))
-    (mapcar (lambda (widget)
-             (and (get (widget-value widget) 'standard-value)
-                  (if (memq (widget-get widget :custom-state)
-                            '(modified set changed saved rogue))
-                      (widget-apply widget :custom-reset-standard))))
+    (mapc (lambda (widget)
+           (and (get (widget-value widget) 'standard-value)
+                (if (memq (widget-get widget :custom-state)
+                          '(modified set changed saved rogue))
+                    (widget-apply widget :custom-reset-standard))))
            children)))
 
 ;;; The Customize Commands
@@ -770,7 +768,7 @@ If given a prefix (or a COMMENT argument), also prompt for a comment."
         (put var 'variable-comment comment))))
 
 ;;;###autoload
-(defun customize-set-variable (var val &optional comment)
+(defun customize-set-variable (variable value &optional comment)
   "Set the default for VARIABLE to VALUE.  VALUE is a Lisp object.
 
 If VARIABLE has a `custom-set' property, that is used for setting
@@ -789,17 +787,17 @@ If given a prefix (or a COMMENT argument), also prompt for a comment."
   (interactive (custom-prompt-variable "Set variable: "
                                       "Set customized value for %s to: "
                                       current-prefix-arg))
-  (funcall (or (get var 'custom-set) 'set-default) var val)
-  (put var 'customized-value (list (custom-quote val)))
+  (funcall (or (get variable 'custom-set) 'set-default) variable value)
+  (put variable 'customized-value (list (custom-quote value)))
   (cond ((string= comment "")
-        (put var 'variable-comment nil)
-        (put var 'customized-variable-comment nil))
+        (put variable 'variable-comment nil)
+        (put variable 'customized-variable-comment nil))
        (comment
-        (put var 'variable-comment comment)
-        (put var 'customized-variable-comment comment))))
+        (put variable 'variable-comment comment)
+        (put variable 'customized-variable-comment comment))))
 
 ;;;###autoload
-(defun customize-save-variable (var val &optional comment)
+(defun customize-save-variable (var value &optional comment)
   "Set the default for VARIABLE to VALUE, and save it for future sessions.
 If VARIABLE has a `custom-set' property, that is used for setting
 VARIABLE, otherwise `set-default' is used.
@@ -817,8 +815,8 @@ If given a prefix (or a COMMENT argument), also prompt for a comment."
   (interactive (custom-prompt-variable "Set and ave variable: "
                                       "Set and save value for %s as: "
                                       current-prefix-arg))
-  (funcall (or (get var 'custom-set) 'set-default) var val)
-  (put var 'saved-value (list (custom-quote val)))
+  (funcall (or (get var 'custom-set) 'set-default) var value)
+  (put var 'saved-value (list (custom-quote value)))
   (cond ((string= comment "")
         (put var 'variable-comment nil)
         (put var 'saved-variable-comment nil))
@@ -938,7 +936,11 @@ version."
 
   (interactive "sCustomize options changed, since version (default all versions): ")
   (if (equal since-version "")
-      (setq since-version nil))
+      (setq since-version nil)
+    (unless (condition-case nil
+               (numberp (read since-version))
+             (error nil))
+      (signal 'wrong-type-argument (list 'numberp since-version))))
   (unless since-version
     (setq since-version customize-changed-options-previous-release))
   (let ((found nil)
@@ -989,17 +991,24 @@ version."
                            "*Customize Changed Options*"))))
 
 (defun customize-version-lessp (version1 version2)
+  ;; Why are the versions strings, and given that they are, why aren't
+  ;; they converted to numbers and compared as such here?  -- fx
+
   ;; In case someone made a mistake and left out the quotes
   ;; in the :version value.
   (if (numberp version2)
       (setq version2 (prin1-to-string version2)))
   (let (major1 major2 minor1 minor2)
-    (string-match "\\([0-9]+\\)[.]\\([0-9]+\\)" version1)
-    (setq major1 (read (match-string 1 version1)))
-    (setq minor1 (read (match-string 2 version1)))
-    (string-match "\\([0-9]+\\)[.]\\([0-9]+\\)" version2)
-    (setq major2 (read (match-string 1 version2)))
-    (setq minor2 (read (match-string 2 version2)))
+    (string-match "\\([0-9]+\\)\\(\\.\\([0-9]+\\)\\)?" version1)
+    (setq major1 (read (or (match-string 1 version1)
+                          "0")))
+    (setq minor1 (read (or (match-string 3 version1)
+                          "0")))
+    (string-match "\\([0-9]+\\)\\(\\.\\([0-9]+\\)\\)?" version2)
+    (setq major2 (read (or (match-string 1 version2)
+                          "0")))
+    (setq minor2 (read (or (match-string 3 version2)
+                          "0")))
     (or (< major1 major2)
        (and (= major1 major2)
             (< minor1 minor2)))))
@@ -1039,7 +1048,7 @@ If SYMBOL is nil, customize all faces."
 
 ;;;###autoload
 (defun customize-face-other-window (&optional symbol)
-  "Show customization buffer for FACE in other window."
+  "Show customization buffer for face SYMBOL in other window."
   (interactive (list (completing-read "Customize face: "
                                      obarray 'custom-facep t)))
   (if (or (null symbol) (and (stringp symbol) (zerop (length symbol))))
@@ -1279,17 +1288,27 @@ Reset all values in this buffer to their saved settings."
                   :action 'Custom-reset-saved)
     (widget-insert " ")
     (widget-create 'push-button
-                  :tag "Reset to Standard"
+                  :tag "Erase Customization"
                   :help-echo "\
-Reset all values in this buffer to their standard settings."
+Un-customize all values in this buffer.  They get their standard settings."
                   :action 'Custom-reset-standard))
   (widget-insert "   ")
   (widget-create 'push-button
                 :tag "Finish"
-                :help-echo "Bury or kill the buffer."
+                :help-echo
+                (lambda (&rest ignore)
+                  (concat (cond
+                           ((eq custom-buffer-done-function
+                                'custom-bury-buffer)
+                            "Bury")
+                           ((eq custom-buffer-done-function 'kill-buffer)
+                            "Kill")
+                           (t "Finish with"))              
+                          " the buffer."))
                 :action #'Custom-buffer-done)
   (widget-insert "\n\n")
   (message "Creating customization items...")
+  (buffer-disable-undo)
   (setq custom-options
        (if (= (length options) 1)
            (mapcar (lambda (entry)
@@ -1319,9 +1338,10 @@ Reset all values in this buffer to their standard settings."
     (widget-insert "\n"))
   (message "Creating customization items ...%2d%%done" 100)
   (unless (eq custom-buffer-style 'tree)
-    (mapcar 'custom-magic-reset custom-options))
+    (mapc 'custom-magic-reset custom-options))
   (message "Creating customization setup...")
   (widget-setup)
+  (buffer-enable-undo)
   (goto-char (point-min))
   (message "Creating customization buffer...done"))
 
@@ -1606,7 +1626,7 @@ and `face'."
           'hidden)))
 
 (defun custom-magic-value-create (widget)
-  ;; Create compact status report for WIDGET.
+  "Create compact status report for WIDGET."
   (let* ((parent (widget-get widget :parent))
         (state (widget-get parent :custom-state))
         (hidden (eq state 'hidden))
@@ -1686,7 +1706,11 @@ and `face'."
 
 (defface custom-button-face
   '((((type x) (class color))          ; Like default modeline
-     (:box (:line-width 2 :style released-button) :background "lightgrey"))
+     (:box (:line-width 2 :style released-button)
+          :background "lightgrey" :foreground "black"))
+    (((type w32) (class color))                ; Like default modeline
+     (:box (:line-width 2 :style released-button)
+          :background "lightgrey" :foreground "black"))
     (t
      nil))
   "Face used for buttons in customization buffers."
@@ -1695,7 +1719,11 @@ and `face'."
 
 (defface custom-button-pressed-face
   '((((type x) (class color))
-     (:box (:line-width 2 :style pressed-button) :background "lightgrey"))
+     (:box (:line-width 2 :style pressed-button)
+          :background "lightgrey" :foreground "black"))
+    (((type w32) (class color))
+     (:box (:line-width 2 :style pressed-button)
+          :background "lightgrey" :foreground "black"))
     (t
      (:inverse-video t)))
   "Face used for buttons in customization buffers."
@@ -1732,7 +1760,7 @@ and `face'."
   :match (lambda (widget value) (symbolp value)))
 
 (defun custom-convert-widget (widget)
-  ;; Initialize :value and :tag from :args in WIDGET.
+  "Initialize :value and :tag from :args in WIDGET."
   (let ((args (widget-get widget :args)))
     (when args
       (widget-put widget :value (widget-apply widget
@@ -1982,13 +2010,24 @@ If INITIAL-STRING is non-nil, use that rather than \"Parent groups:\"."
 
 ;;; The `custom-variable' Widget.
 
-(defface custom-variable-tag-face '((((class color)
-                                     (background dark))
-                                    (:foreground "light blue" :underline t))
-                                   (((class color)
-                                     (background light))
-                                    (:foreground "blue" :underline t))
-                                   (t (:underline t)))
+;; When this was underlined blue, users confused it with a
+;; Mosaic-style hyperlink...
+(defface custom-variable-tag-face
+  `((((class color)
+      (background dark))
+     (:foreground "light blue" :bold t :family "helv"
+                 :height ,(let ((height (face-attribute 'default :height)))
+                            (if (numberp height)
+                                (floor height 0.9)
+                              height))))
+    (((class color)
+      (background light))
+     (:foreground "blue" :family "helv" :bold t
+                 :height ,(let ((height (face-attribute 'default :height)))
+                            (if (numberp height)
+                                (floor height 0.9)
+                              height))))
+    (t (:bold t)))
   "Face used for unpushable variable tags."
   :group 'custom-faces)
 
@@ -2253,7 +2292,7 @@ Otherwise, look up symbol in `custom-guess-type-alist'."
                (get (widget-value widget) 'saved-variable-comment))
            (memq (widget-get widget :custom-state)
                  '(modified set changed rogue)))))
-    ("Reset to Standard Settings" custom-variable-reset-standard
+    ("Erase Customization" custom-variable-reset-standard
      (lambda (widget)
        (and (get (widget-value widget) 'standard-value)
            (memq (widget-get widget :custom-state)
@@ -2272,7 +2311,7 @@ Each entry has the form (NAME ACTION FILTER) where NAME is the name of
 the menu entry, ACTION is the function to call on the widget when the
 menu is selected, and FILTER is a predicate which takes a `custom-variable'
 widget as an argument, and returns non-nil if ACTION is valid on that
-widget. If FILTER is nil, ACTION is always valid.")
+widget.  If FILTER is nil, ACTION is always valid.")
 
 (defun custom-variable-action (widget &optional event)
   "Show the menu for `custom-variable' WIDGET.
@@ -2299,7 +2338,7 @@ Optional EVENT is the location for the menu."
   (custom-redraw widget))
 
 (defun custom-variable-edit-lisp (widget)
-  "Edit the lisp representation of the value of WIDGET."
+  "Edit the Lisp representation of the value of WIDGET."
   (widget-put widget :custom-state 'unknown)
   (widget-put widget :custom-form 'lisp)
   (custom-redraw widget))
@@ -2384,7 +2423,6 @@ Optional EVENT is the location for the menu."
   "Restore the saved value for the variable being edited by WIDGET."
   (let* ((symbol (widget-value widget))
         (set (or (get symbol 'custom-set) 'set-default))
-        (comment-widget (widget-get widget :comment-widget))
         (value (get symbol 'saved-value))
         (comment (get symbol 'saved-variable-comment)))
     (cond ((or value comment)
@@ -2401,10 +2439,11 @@ Optional EVENT is the location for the menu."
     (custom-redraw widget)))
 
 (defun custom-variable-reset-standard (widget)
-  "Restore the standard setting for the variable being edited by WIDGET."
+  "Restore the standard setting for the variable being edited by WIDGET.
+This operation eliminates any saved setting for the variable,
+restoring it to the state of a variable that has never been customized."
   (let* ((symbol (widget-value widget))
-        (set (or (get symbol 'custom-set) 'set-default))
-        (comment-widget (widget-get widget :comment-widget)))
+        (set (or (get symbol 'custom-set) 'set-default)))
     (if (get symbol 'standard-value)
        (funcall set symbol (eval (car (get symbol 'standard-value))))
       (error "No standard setting known for %S" symbol))
@@ -2508,7 +2547,12 @@ Match frames with dark backgrounds.")
 
 ;;; The `custom-face' Widget.
 
-(defface custom-face-tag-face '((t (:underline t)))
+(defface custom-face-tag-face
+  `((t (:bold t :family "helv"
+             :height ,(let ((height (face-attribute 'default :height)))
+                            (if (numberp height)
+                                (floor height 0.9)
+                              height)))))
   "Face used for face tags."
   :group 'custom-faces)
 
@@ -2524,8 +2568,7 @@ Match frames with dark backgrounds.")
   "Customize face."
   :sample-face 'custom-face-tag-face
   :help-echo "Set or reset this face."
-  :documentation-property '(lambda (face)
-                            (face-doc-string face))
+  :documentation-property #'face-doc-string
   :value-create 'custom-face-value-create
   :action 'custom-face-action
   :custom-category 'face
@@ -2682,7 +2725,7 @@ Match frames with dark backgrounds.")
      (lambda (widget)
        (or (get (widget-value widget) 'saved-face)
           (get (widget-value widget) 'saved-face-comment))))
-    ("Reset to Standard Setting" custom-face-reset-standard
+    ("Erase Customization" custom-face-reset-standard
      (lambda (widget)
        (get (widget-value widget) 'face-defface-spec)))
     ("---" ignore ignore)
@@ -2702,7 +2745,7 @@ Each entry has the form (NAME ACTION FILTER) where NAME is the name of
 the menu entry, ACTION is the function to call on the widget when the
 menu is selected, and FILTER is a predicate which takes a `custom-face'
 widget as an argument, and returns non-nil if ACTION is valid on that
-widget. If FILTER is nil, ACTION is always valid.")
+widget.  If FILTER is nil, ACTION is always valid.")
 
 (defun custom-face-edit-selected (widget)
   "Edit selected attributes of the value of WIDGET."
@@ -2717,7 +2760,7 @@ widget. If FILTER is nil, ACTION is always valid.")
   (custom-redraw widget))
 
 (defun custom-face-edit-lisp (widget)
-  "Edit the lisp representation of the value of WIDGET."
+  "Edit the Lisp representation of the value of WIDGET."
   (widget-put widget :custom-state 'unknown)
   (widget-put widget :custom-form 'lisp)
   (custom-redraw widget))
@@ -2828,7 +2871,9 @@ Optional EVENT is the location for the menu."
     (custom-redraw-magic widget)))
 
 (defun custom-face-reset-standard (widget)
-  "Restore WIDGET to the face's standard settings."
+  "Restore WIDGET to the face's standard settings.
+This operation eliminates any saved setting for the face,
+restoring it to the state of a face that has never been customized."
   (let* ((symbol (widget-value widget))
         (child (car (widget-get widget :children)))
         (value (get symbol 'face-defface-spec))
@@ -2864,10 +2909,10 @@ Optional EVENT is the location for the menu."
   :value-get 'widget-value-value-get
   :validate 'widget-children-validate
   :action 'widget-face-action
-  :match '(lambda (widget value) (symbolp value)))
+  :match (lambda (widget value) (symbolp value)))
 
 (defun widget-face-value-create (widget)
-  ;; Create a `custom-face' child.
+  "Create a `custom-face' child."
   (let* ((symbol (widget-value widget))
         (custom-buffer-style 'face)
         (child (widget-create-child-and-convert
@@ -2879,7 +2924,7 @@ Optional EVENT is the location for the menu."
     (widget-put widget :children (list child))))
 
 (defun widget-face-value-delete (widget)
-  ;; Remove the child from the options.
+  "Remove the child from the options."
   (let ((child (car (widget-get widget :children))))
     (setq custom-options (delq child custom-options))
     (widget-children-value-delete widget)))
@@ -2911,11 +2956,18 @@ Optional EVENT is the location for the menu."
   :match (lambda (widget value)
           (or (symbolp value)
               (widget-group-match widget value)))
+  ;; Avoid adding undefined functions to the hook, especially for
+  ;; things like `find-file-hook' or even more basic ones, to avoid
+  ;; chaos.
+  :set (lambda (symbol value)
+        (dolist (elt value)
+          (if (fboundp elt)
+              (add-hook symbol elt))))
   :convert-widget 'custom-hook-convert-widget
   :tag "Hook")
 
 (defun custom-hook-convert-widget (widget)
-  ;; Handle `:custom-options'.
+  ;; Handle `:options'.
   (let* ((options (widget-get widget :options))
         (other `(editable-list :inline t
                                :entry-format "%i %d%v"
@@ -2952,22 +3004,42 @@ and so forth.  The remaining group tags are shown with
   :type '(repeat face)
   :group 'custom-faces)
 
-(defface custom-group-tag-face-1 '((((class color)
-                                    (background dark))
-                                   (:foreground "pink" :underline t))
-                                  (((class color)
-                                    (background light))
-                                   (:foreground "red" :underline t))
-                                  (t (:underline t)))
-  "Face used for group tags.")
-
-(defface custom-group-tag-face '((((class color)
-                                  (background dark))
-                                 (:foreground "light blue" :underline t))
-                                (((class color)
-                                  (background light))
-                                 (:foreground "blue" :underline t))
-                                (t (:underline t)))
+(defface custom-group-tag-face-1
+  `((((class color)
+      (background dark))
+     (:foreground "pink" :family "helv"
+                 :height ,(let ((height (face-attribute 'default :height)))
+                            (if (numberp height)
+                                (floor height 0.9)
+                              height))
+                 :bold t))
+    (((class color)
+      (background light))
+     (:foreground "red" :bold t
+                 :height ,(let ((height (face-attribute 'default :height)))
+                            (if (numberp height)
+                                (floor height 0.9)
+                              height))))
+    (t (:bold t)))
+  "Face used for group tags."
+  :group 'custom-faces)
+
+(defface custom-group-tag-face
+  `((((class color)
+      (background dark))
+     (:foreground "light blue" :bold t
+                 :height ,(let ((height (face-attribute 'default :height)))
+                            (if (numberp height)
+                                (floor height 0.9)
+                              height))))
+    (((class color)
+      (background light))
+     (:foreground "blue" :bold t
+                 :height ,(let ((height (face-attribute 'default :height)))
+                            (if (numberp height)
+                                (floor height 0.9)
+                              height))))
+    (t (:bold t)))
   "Face used for low level group tags."
   :group 'custom-faces)
 
@@ -3222,7 +3294,7 @@ Creating group members... %2d%%"
                                          (widget-insert "\n"))))
                                    members)))
             (message "Creating group magic...")
-            (mapcar 'custom-magic-reset children)
+            (mapc 'custom-magic-reset children)
             (message "Creating group state...")
             (widget-put widget :children children)
             (custom-group-state-update widget)
@@ -3275,42 +3347,42 @@ Optional EVENT is the location for the menu."
 (defun custom-group-set (widget)
   "Set changes in all modified group members."
   (let ((children (widget-get widget :children)))
-    (mapcar (lambda (child)
-             (when (eq (widget-get child :custom-state) 'modified)
-               (widget-apply child :custom-set)))
+    (mapc (lambda (child)
+           (when (eq (widget-get child :custom-state) 'modified)
+             (widget-apply child :custom-set)))
            children )))
 
 (defun custom-group-save (widget)
   "Save all modified group members."
   (let ((children (widget-get widget :children)))
-    (mapcar (lambda (child)
-             (when (memq (widget-get child :custom-state) '(modified set))
-               (widget-apply child :custom-save)))
+    (mapc (lambda (child)
+           (when (memq (widget-get child :custom-state) '(modified set))
+             (widget-apply child :custom-save)))
            children )))
 
 (defun custom-group-reset-current (widget)
   "Reset all modified group members."
   (let ((children (widget-get widget :children)))
-    (mapcar (lambda (child)
-             (when (eq (widget-get child :custom-state) 'modified)
-               (widget-apply child :custom-reset-current)))
+    (mapc (lambda (child)
+           (when (eq (widget-get child :custom-state) 'modified)
+             (widget-apply child :custom-reset-current)))
            children )))
 
 (defun custom-group-reset-saved (widget)
   "Reset all modified or set group members."
   (let ((children (widget-get widget :children)))
-    (mapcar (lambda (child)
-             (when (memq (widget-get child :custom-state) '(modified set))
-               (widget-apply child :custom-reset-saved)))
+    (mapc (lambda (child)
+           (when (memq (widget-get child :custom-state) '(modified set))
+             (widget-apply child :custom-reset-saved)))
            children )))
 
 (defun custom-group-reset-standard (widget)
   "Reset all modified, set, or saved group members."
   (let ((children (widget-get widget :children)))
-    (mapcar (lambda (child)
-             (when (memq (widget-get child :custom-state)
-                         '(modified set saved))
-               (widget-apply child :custom-reset-standard)))
+    (mapc (lambda (child)
+           (when (memq (widget-get child :custom-state)
+                       '(modified set saved))
+             (widget-apply child :custom-reset-standard)))
            children )))
 
 (defun custom-group-state-update (widget)
@@ -3338,7 +3410,12 @@ Optional EVENT is the location for the menu."
   "File used for storing customization information.
 The default is nil, which means to use your init file
 as specified by `user-init-file'.  If you specify some other file,
-you need to explicitly load that file for the settings to take effect."
+you need to explicitly load that file for the settings to take effect.
+
+When you change this variable, look in the previous custom file
+\(usually your init file) for the forms `(custom-set-variables ...)'
+and `(custom-set-faces ...)', and copy them (whichever ones you find)
+to the new custom file.  This will preserve your existing customizations."
   :type '(choice (const :tag "Your Emacs init file" nil) file)
   :group 'customize)
 
@@ -3351,8 +3428,9 @@ you need to explicitly load that file for the settings to take effect."
                            "~/" nil nil ".emacs"))))
 
 (defun custom-save-delete (symbol)
-  "Delete the call to SYMBOL from `custom-file'.
-Leave point at the location of the call, or after the last expression."
+  "Visit `custom-file' and delete all calls to SYMBOL from it.
+Leave point at the old location of the first such call,
+or (if there were none) at the end of the buffer."
   (let ((default-major-mode))
     (set-buffer (find-file-noselect (custom-file))))
   (goto-char (point-min))
@@ -3360,18 +3438,23 @@ Leave point at the location of the call, or after the last expression."
   (while (forward-comment 1))
   (or (eobp)
       (save-excursion (forward-sexp (buffer-size)))) ; Test for scan errors.
-  (catch 'found
-    (while t
-      ;; Skip all whitespace and comments.
-      (while (forward-comment 1))
-      (let ((start (point))
-           (sexp (condition-case nil
-                     (read (current-buffer))
-                   (end-of-file (throw 'found nil)))))
-       (when (and (listp sexp)
-                  (eq (car sexp) symbol))
-         (delete-region start (point))
-         (throw 'found nil))))))
+  (let (first)
+    (catch 'found
+      (while t ;; We exit this loop only via throw.
+       ;; Skip all whitespace and comments.
+       (while (forward-comment 1))
+       (let ((start (point))
+             (sexp (condition-case nil
+                       (read (current-buffer))
+                     (end-of-file (throw 'found nil)))))
+         (when (and (listp sexp)
+                    (eq (car sexp) symbol))
+           (delete-region start (point))
+           (unless first
+             (setq first (point)))))))
+    (if first
+       (goto-char first)
+      (goto-char (point-max)))))
 
 (defun custom-save-variables ()
   "Save all customized variables in `custom-file'."
@@ -3388,7 +3471,9 @@ Leave point at the location of the call, or after the last expression."
       (setq saved-list (sort (cdr saved-list) 'string<))
       (unless (bolp)
        (princ "\n"))
-      (princ "(custom-set-variables")
+      (princ "(custom-set-variables
+  ;; custom-set-variables was added by Custom -- don't edit or cut/paste it!
+  ;; Your init file must only contain one such instance.\n")
       (mapcar
        (lambda (symbol)
         (let ((value (get symbol 'saved-value))
@@ -3399,7 +3484,9 @@ Leave point at the location of the call, or after the last expression."
               (comment (get symbol 'saved-variable-comment))
               sep)
           (when (or value comment)
-            (princ "\n '(")
+            (unless (bolp)
+              (princ "\n"))
+            (princ " '(")
             (prin1 symbol)
             (princ " ")
             (prin1 (car value))
@@ -3424,6 +3511,8 @@ Leave point at the location of the call, or after the last expression."
                   (t
                    (princ ")"))))))
        saved-list)
+      (if (bolp)
+         (princ " "))
       (princ ")")
       (unless (looking-at "\n")
        (princ "\n")))))
@@ -3446,7 +3535,9 @@ Leave point at the location of the call, or after the last expression."
          (setq saved-list (cons 'default (delq 'default saved-list))))
       (unless (bolp)
        (princ "\n"))
-      (princ "(custom-set-faces")
+      (princ "(custom-set-faces
+  ;; custom-set-faces was added by Custom -- don't edit or cut/paste it!
+  ;; Your init file must only contain one such instance.\n")
       (mapcar
        (lambda (symbol)
         (let ((value (get symbol 'saved-face))
@@ -3456,7 +3547,9 @@ Leave point at the location of the call, or after the last expression."
               (comment (get 'default 'saved-face-comment)))
           (unless (eq symbol 'default))
           ;; Don't print default face here.
-          (princ "\n '(")
+          (unless (bolp)
+            (princ "\n"))
+          (princ " '(")
           (prin1 symbol)
           (princ " ")
           (prin1 value)
@@ -3474,6 +3567,8 @@ Leave point at the location of the call, or after the last expression."
                 (t
                  (princ ")")))))
        saved-list)
+      (if (bolp)
+         (princ " "))
       (princ ")")
       (unless (looking-at "\n")
        (princ "\n")))))
@@ -3548,20 +3643,11 @@ Leave point at the location of the call, or after the last expression."
                                   ':style 'toggle
                                   ':selected symbol)))
 
-;; Fixme: sort out use of :filter in Emacs 21.
-(if nil ; (string-match "XEmacs" emacs-version)
-    ;; XEmacs can create menus dynamically.
-    (defun custom-group-menu-create (widget symbol)
-      "Ignoring WIDGET, create a menu entry for customization group SYMBOL."
-      `( ,(custom-unlispify-menu-entry symbol t)
-        :filter (lambda (&rest junk)
-                  (cdr (custom-menu-create ',symbol)))))
-  ;; But emacs can't.
-  (defun custom-group-menu-create (widget symbol)
-    "Ignoring WIDGET, create a menu entry for customization group SYMBOL."
-    ;; Limit the nesting.
-    (let ((custom-menu-nesting (1- custom-menu-nesting)))
-      (custom-menu-create symbol))))
+(defun custom-group-menu-create (widget symbol)
+  "Ignoring WIDGET, create a menu entry for customization group SYMBOL."
+  `( ,(custom-unlispify-menu-entry symbol t)
+     :filter (lambda (&rest junk)
+              (cdr (custom-menu-create ',symbol)))))
 
 ;;;###autoload
 (defun custom-menu-create (symbol)
@@ -3598,14 +3684,9 @@ Otherwise the menu will be named `Customize'.
 The format is suitable for use with `easy-menu-define'."
   (unless name
     (setq name "Customize"))
-  ;; Fixme: sort out use of :filter in Emacs 21.
-  (if nil ;(string-match "XEmacs" emacs-version)
-      ;; We can delay it under XEmacs.
-      `(,name
-       :filter (lambda (&rest junk)
-                 (cdr (custom-menu-create ',symbol))))
-    ;; But we must create it now under Emacs.
-    (cons name (cdr (custom-menu-create symbol)))))
+  `(,name
+    :filter (lambda (&rest junk)
+             (cdr (custom-menu-create ',symbol)))))
 
 ;;; The Custom Mode.
 
@@ -3711,6 +3792,10 @@ if that value is non-nil."
   (add-hook 'widget-edit-functions 'custom-state-buffer-message nil t)
   (run-hooks 'custom-mode-hook))
 
+(add-to-list
+ 'debug-ignored-errors
+ "^No user options have changed defaults in recent Emacs versions$")
+
 ;;; The End.
 
 (provide 'cus-edit)