Replace version 24.2 with 24.3 where appropriate (hopefully)
[bpt/emacs.git] / lisp / cus-edit.el
index 7c96b52..86a1913 100644 (file)
@@ -1,6 +1,6 @@
 ;;; cus-edit.el --- tools for customizing Emacs and Lisp packages
 ;;
-;; Copyright (C) 1996-1997, 1999-201 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1997, 1999-2012 Free Software Foundation, Inc.
 ;;
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Maintainer: FSF
   :group 'emacs)
 
 (defgroup languages nil
-  "Specialized modes for editing programming languages."
+  "Modes for editing programming languages."
   :group 'programming)
 
 (defgroup lisp nil
   :group 'applications)
 
 (defgroup news nil
-  "Support for netnews reading and posting."
+  "Reading and posting to newsgroups."
   :link '(custom-manual "(gnus)")
   :group 'applications)
 
   :group 'environment)
 
 (defgroup unix nil
-  "Front-ends/assistants for, or emulators of, UNIX features."
+  "Interfaces, assistants, and emulators for UNIX features."
   :group 'environment)
 
 (defgroup i18n nil
   :group 'editing)
 
 (defgroup mode-line nil
-  "Content of the modeline."
+  "Contents of the mode line."
   :group 'environment)
 
 (defgroup editing-basics nil
     (set-keymap-parent map widget-keymap)
     (define-key map [remap self-insert-command] 'Custom-no-edit)
     (define-key map "\^m" 'Custom-newline)
-    (define-key map " " 'scroll-up)
-    (define-key map "\177" 'scroll-down)
+    (define-key map " " 'scroll-up-command)
+    (define-key map "\177" 'scroll-down-command)
     (define-key map "\C-c\C-c" 'Custom-set)
     (define-key map "\C-x\C-s" 'Custom-save)
     (define-key map "q" 'Custom-buffer-done)
@@ -544,12 +544,6 @@ WIDGET is the widget to apply the filter entries of MENU on."
           (erase-buffer)
           (princ symbol (current-buffer))
           (goto-char (point-min))
-          ;; FIXME: Boolean variables are not predicates, so they shouldn't
-          ;; end with `-p'.  -stef
-          ;; (when (and (eq (get symbol 'custom-type) 'boolean)
-          ;;         (re-search-forward "-p\\'" nil t))
-          ;;   (replace-match "" t t)
-          ;;   (goto-char (point-min)))
           (if custom-unlispify-remove-prefixes
               (let ((prefixes custom-prefix-list)
                     prefix)
@@ -594,7 +588,7 @@ WIDGET is the widget to apply the filter entries of MENU on."
     ("-function\\'" function)
     ("-functions\\'" (repeat function))
     ("-list\\'" (repeat sexp))
-    ("-alist\\'" (repeat (cons sexp sexp))))
+    ("-alist\\'" (alist :key-type sexp :value-type sexp)))
   "Alist of (MATCH TYPE).
 
 MATCH should be a regexp matching the name of a symbol, and TYPE should
@@ -699,8 +693,6 @@ If `last', order groups after non-groups."
                 (const :tag "none" nil))
   :group 'custom-menu)
 
-;;;###autoload (add-hook 'same-window-regexps (purecopy "\\`\\*Customiz.*\\*\\'"))
-
 (defun custom-sort-items (items sort-alphabetically order-groups)
   "Return a sorted copy of ITEMS.
 ITEMS should be a `custom-group' property.
@@ -734,26 +726,26 @@ groups after non-groups, if nil do not order groups at all."
 ;; `custom-buffer-create-internal' if `custom-buffer-verbose-help' is non-nil.
 
 (defvar custom-commands
-  '((" Set for current session " Custom-set t
-     "Apply all settings in this buffer to the current session"
+  '((" Apply " Custom-set t
+     "Apply settings (for the current session only)"
      "index"
      "Apply")
-    (" Save for future sessions " Custom-save
+    (" Apply and Save " Custom-save
      (or custom-file user-init-file)
-     "Apply all settings in this buffer and save them for future Emacs sessions."
+     "Apply settings and save for future sessions."
      "save"
      "Save")
-    (" Undo edits " Custom-reset-current t
-     "Restore all settings in this buffer to reflect their current values."
+    (" Undo Edits " Custom-reset-current t
+     "Restore customization buffer to reflect existing settings."
      "refresh"
      "Undo")
-    (" Reset to saved " Custom-reset-saved t
-     "Restore all settings in this buffer to their saved values (if any)."
+    (" Reset Customizations " Custom-reset-saved t
+     "Undo any settings applied only for the current session."
      "undo"
      "Reset")
-    (" Erase customizations " Custom-reset-standard
+    (" Erase Customizations " Custom-reset-standard
      (or custom-file user-init-file)
-     "Un-customize all settings in this buffer and save them with standard values."
+     "Un-customize settings in this and future sessions."
      "delete"
      "Uncustomize")
     (" Help for Customize " Custom-help t
@@ -768,9 +760,9 @@ groups after non-groups, if nil do not order groups at all."
   (info "(emacs)Easy Customization"))
 
 (defvar custom-reset-menu
-  '(("Undo Edits" . Custom-reset-current)
-    ("Reset to Saved" . Custom-reset-saved)
-    ("Erase Customizations (use standard values)" . Custom-reset-standard))
+  '(("Undo Edits in Customization Buffer" . Custom-reset-current)
+    ("Revert This Session's Customizations" . Custom-reset-saved)
+    ("Erase Customizations" . 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
@@ -903,7 +895,8 @@ making them as if they had never been customized at all."
            (memq (widget-get widget :custom-state)
                  '(modified set changed saved rogue))
            (widget-apply widget :custom-mark-to-reset-standard)))
-     "Erase all customizations for settings in this buffer? " t)
+     "The settings will revert to their default values, in this
+and future sessions.  Really erase customizations? " t)
     (custom-reset-standard-save-and-update)))
 
 ;;; The Customize Commands
@@ -1033,9 +1026,36 @@ If given a prefix (or a COMMENT argument), also prompt for a comment."
         (put variable 'saved-variable-comment comment)))
   (put variable 'customized-value nil)
   (put variable 'customized-variable-comment nil)
-  (custom-save-all)
+  (if (custom-file t)
+      (custom-save-all)
+    (message "Setting `%s' temporarily since \"emacs -q\" would overwrite customizations"
+            variable)
+    (set variable value))
   value)
 
+;; Some parts of Emacs might prompt the user to save customizations,
+;; during startup before customizations are loaded.  This function
+;; handles this corner case by avoiding calling `custom-save-variable'
+;; too early, which could wipe out existing customizations.
+
+;;;###autoload
+(defun customize-push-and-save (list-var elts)
+  "Add ELTS to LIST-VAR and save for future sessions, safely.
+ELTS should be a list.  This function adds each entry to the
+value of LIST-VAR using `add-to-list'.
+
+If Emacs is initialized, call `customize-save-variable' to save
+the resulting list value now.  Otherwise, add an entry to
+`after-init-hook' to save it after initialization."
+  (dolist (entry elts)
+    (add-to-list list-var entry))
+  (if after-init-time
+      (let ((coding-system-for-read nil))
+       (customize-save-variable list-var (eval list-var)))
+    (add-hook 'after-init-hook
+             `(lambda ()
+                (customize-push-and-save ',list-var ',elts)))))
+
 ;;;###autoload
 (defun customize ()
   "Select a customization buffer which you can use to set user options.
@@ -1076,8 +1096,9 @@ then prompt for the MODE to customize."
                      t)))
 
 ;;;###autoload
-(defun customize-group (&optional group)
-  "Customize GROUP, which must be a customization group."
+(defun customize-group (&optional group other-window)
+  "Customize GROUP, which must be a customization group.
+If OTHER-WINDOW is non-nil, display in another window."
   (interactive (list (customize-read-group)))
   (when (stringp group)
     (if (string-equal "" group)
@@ -1085,29 +1106,32 @@ then prompt for the MODE to customize."
       (setq group (intern group))))
   (let ((name (format "*Customize Group: %s*"
                      (custom-unlispify-tag-name group))))
-    (if (get-buffer name)
-        (pop-to-buffer name)
-      (custom-buffer-create
-       (list (list group 'custom-group))
-       name
-       (concat " for group "
-               (custom-unlispify-tag-name group))))))
+    (cond
+     ((null (get-buffer name))
+      (funcall (if other-window
+                  'custom-buffer-create-other-window
+                'custom-buffer-create)
+              (list (list group 'custom-group))
+              name
+              (concat " for group "
+                      (custom-unlispify-tag-name group))))
+     (other-window
+      (switch-to-buffer-other-window name))
+     (t
+      (pop-to-buffer-same-window name)))))
 
 ;;;###autoload
 (defun customize-group-other-window (&optional group)
   "Customize GROUP, which must be a customization group, in another window."
   (interactive (list (customize-read-group)))
-  (let ((pop-up-windows t)
-        (same-window-buffer-names nil)
-        (same-window-regexps nil))
-    (customize-group group)))
+  (customize-group group t))
 
 ;;;###autoload
 (defalias 'customize-variable 'customize-option)
 
 ;;;###autoload
 (defun customize-option (symbol)
-  "Customize SYMBOL, which must be a user option variable."
+  "Customize SYMBOL, which must be a user option."
   (interactive (custom-variable-prompt))
   (unless symbol
     (error "No variable specified"))
@@ -1123,7 +1147,7 @@ then prompt for the MODE to customize."
 
 ;;;###autoload
 (defun customize-option-other-window (symbol)
-  "Customize SYMBOL, which must be a user option variable.
+  "Customize SYMBOL, which must be a user option.
 Show the buffer in another window, but don't select it."
   (interactive (custom-variable-prompt))
   (unless symbol
@@ -1135,7 +1159,7 @@ Show the buffer in another window, but don't select it."
     (unless (eq symbol basevar)
       (message "`%s' is an alias for `%s'" symbol basevar))))
 
-(defvar customize-changed-options-previous-release "23.1"
+(defvar customize-changed-options-previous-release "24.1"
   "Version for `customize-changed-options' to refer back to by default.")
 
 ;; Packages will update this variable, so make it available.
@@ -1177,9 +1201,10 @@ the official name of the package, such as MH-E or Gnus.")
 ;;;###autoload
 (defun customize-changed-options (&optional since-version)
   "Customize all settings whose meanings have changed in Emacs itself.
-This includes new user option variables and faces, and new
-customization groups, as well as older options and faces whose meanings
-or default values have changed since the previous major Emacs release.
+This includes new user options and faces, and new customization
+groups, as well as older options and faces whose meanings or
+default values have changed since the previous major Emacs
+release.
 
 With argument SINCE-VERSION (a string), customize all settings
 that were added or redefined since that version."
@@ -1229,8 +1254,8 @@ that were added or redefined since that version."
     (if found
        (custom-buffer-create (custom-sort-items found t 'first)
                              "*Customize Changed Options*")
-      (error "No user option defaults have been changed since Emacs %s"
-            since-version))))
+      (user-error "No user option defaults have been changed since Emacs %s"
+                  since-version))))
 
 (defun customize-package-emacs-version (symbol package-version)
   "Return the Emacs version in which SYMBOL's meaning last changed.
@@ -1281,11 +1306,13 @@ Emacs that is associated with version VERSION of PACKAGE."
             (< minor1 minor2)))))
 
 ;;;###autoload
-(defun customize-face (&optional face)
+(defun customize-face (&optional face other-window)
   "Customize FACE, which should be a face name or nil.
 If FACE is nil, customize all faces.  If FACE is actually a
 face-alias, customize the face it is aliased to.
 
+If OTHER-WINDOW is non-nil, display in another window.
+
 Interactively, when point is on text which has a face specified,
 suggest to customize that face, if it's customizable."
   (interactive (list (read-face-name "Customize face" "all faces" t)))
@@ -1293,21 +1320,24 @@ suggest to customize that face, if it's customizable."
       (setq face (face-list)))
   (if (and (listp face) (null (cdr face)))
       (setq face (car face)))
-  (if (listp face)
-      (custom-buffer-create
-       (custom-sort-items
-        (mapcar (lambda (s) (list s 'custom-face)) face)
-        t nil)
-       "*Customize Faces*")
-    ;; If FACE is actually an alias, customize the face it is aliased to.
-    (if (get face 'face-alias)
-        (setq face (get face 'face-alias)))
-    (unless (facep face)
-      (error "Invalid face %S" face))
-    (custom-buffer-create
-     (list (list face 'custom-face))
-     (format "*Customize Face: %s*"
-             (custom-unlispify-tag-name face)))))
+  (let ((display-fun (if other-window
+                        'custom-buffer-create-other-window
+                      'custom-buffer-create)))
+    (if (listp face)
+       (funcall display-fun
+                (custom-sort-items
+                 (mapcar (lambda (s) (list s 'custom-face)) face)
+                 t nil)
+                "*Customize Faces*")
+      ;; If FACE is actually an alias, customize the face it is aliased to.
+      (if (get face 'face-alias)
+         (setq face (get face 'face-alias)))
+      (unless (facep face)
+       (error "Invalid face %S" face))
+      (funcall display-fun
+              (list (list face 'custom-face))
+              (format "*Customize Face: %s*"
+                      (custom-unlispify-tag-name face))))))
 
 ;;;###autoload
 (defun customize-face-other-window (&optional face)
@@ -1317,16 +1347,13 @@ If FACE is actually a face-alias, customize the face it is aliased to.
 Interactively, when point is on text which has a face specified,
 suggest to customize that face, if it's customizable."
   (interactive (list (read-face-name "Customize face" "all faces" t)))
-  (let ((pop-up-windows t)
-        (same-window-buffer-names nil)
-        (same-window-regexps nil))
-    (customize-face face)))
+  (customize-face face t))
 
 (defalias 'customize-customized 'customize-unsaved)
 
 ;;;###autoload
 (defun customize-unsaved ()
-  "Customize all user options set in this session but not saved."
+  "Customize all options and faces set in this session but not saved."
   (interactive)
   (let ((found nil))
     (mapatoms (lambda (symbol)
@@ -1359,12 +1386,12 @@ suggest to customize that face, if it's customizable."
                                         (default-value symbol))))
                    (push (list symbol 'custom-variable) found)))))
     (if (not found)
-       (error "No rogue user options")
+       (user-error "No rogue user options")
       (custom-buffer-create (custom-sort-items found t nil)
                            "*Customize Rogue*"))))
 ;;;###autoload
 (defun customize-saved ()
-  "Customize all already saved user options."
+  "Customize all saved options and faces."
   (interactive)
   (let ((found nil))
     (mapatoms (lambda (symbol)
@@ -1376,8 +1403,8 @@ suggest to customize that face, if it's customizable."
                         (get symbol 'saved-variable-comment))
                     (boundp symbol)
                     (push (list symbol 'custom-variable) found))))
-    (if (not found )
-       (error "No saved user options")
+    (if (not found)
+       (user-error "No saved user options")
       (custom-buffer-create (custom-sort-items found t nil)
                            "*Customize Saved*"))))
 
@@ -1385,7 +1412,7 @@ suggest to customize that face, if it's customizable."
 
 ;;;###autoload
 (defun customize-apropos (pattern &optional type)
-  "Customize all loaded options, faces and groups matching PATTERN.
+  "Customize loaded options, faces and groups matching PATTERN.
 PATTERN can be a word, a list of words (separated by spaces),
 or a regexp (using some regexp special characters).  If it is a word,
 search for matches for that word as a substring.  If it is a list of words,
@@ -1393,62 +1420,50 @@ search for matches for any two (or more) of those words.
 
 If TYPE is `options', include only options.
 If TYPE is `faces', include only faces.
-If TYPE is `groups', include only groups.
-If TYPE is t (interactively, with prefix arg), include variables
-that are not customizable options, as well as faces and groups
-\(but we recommend using `apropos-variable' instead)."
-  (interactive (list (apropos-read-pattern "symbol") current-prefix-arg))
+If TYPE is `groups', include only groups."
+  (interactive (list (apropos-read-pattern "symbol") nil))
   (require 'apropos)
+  (unless (memq type '(nil options faces groups))
+    (error "Invalid setting type %s" (symbol-name type)))
   (apropos-parse-pattern pattern)
   (let (found)
     (mapatoms
      `(lambda (symbol)
        (when (string-match apropos-regexp (symbol-name symbol))
-         ,(if (not (memq type '(faces options)))
+         ,(if (memq type '(nil groups))
               '(if (get symbol 'custom-group)
                    (push (list symbol 'custom-group) found)))
-         ,(if (not (memq type '(options groups)))
+         ,(if (memq type '(nil faces))
               '(if (custom-facep symbol)
                    (push (list symbol 'custom-face) found)))
-         ,(if (not (memq type '(groups faces)))
+         ,(if (memq type '(nil options))
               `(if (and (boundp symbol)
                         (eq (indirect-variable symbol) symbol)
                         (or (get symbol 'saved-value)
-                            (custom-variable-p symbol)
-                            ,(if (not (memq type '(nil options)))
-                                 '(get symbol 'variable-documentation))))
+                            (custom-variable-p symbol)))
                    (push (list symbol 'custom-variable) found))))))
-    (if (not found)
-       (error "No %s matching %s"
-              (if (eq type t)
-                  "items"
-                (format "customizable %s"
-                        (if (memq type '(options faces groups))
-                            (symbol-name type)
-                          "items")))
-              pattern)
-      (custom-buffer-create
-       (custom-sort-items found t custom-buffer-order-groups)
-       "*Customize Apropos*"))))
+    (unless found
+      (error "No customizable %s matching %s" (symbol-name type) pattern))
+    (custom-buffer-create
+     (custom-sort-items found t custom-buffer-order-groups)
+     "*Customize Apropos*")))
 
 ;;;###autoload
-(defun customize-apropos-options (regexp &optional arg)
-  "Customize all loaded customizable options matching REGEXP.
-With prefix ARG, include variables that are not customizable options
-\(but it is better to use `apropos-variable' if you want to find those)."
-  (interactive "sCustomize options (regexp): \nP")
-  (customize-apropos regexp (or arg 'options)))
+(defun customize-apropos-options (regexp &optional ignored)
+  "Customize all loaded customizable options matching REGEXP."
+  (interactive (list (apropos-read-pattern "options")))
+  (customize-apropos regexp 'options))
 
 ;;;###autoload
 (defun customize-apropos-faces (regexp)
   "Customize all loaded faces matching REGEXP."
-  (interactive "sCustomize faces (regexp): \n")
+  (interactive (list (apropos-read-pattern "faces")))
   (customize-apropos regexp 'faces))
 
 ;;;###autoload
 (defun customize-apropos-groups (regexp)
   "Customize all loaded groups matching REGEXP."
-  (interactive "sCustomize groups (regexp): \n")
+  (interactive (list (apropos-read-pattern "groups")))
   (customize-apropos regexp 'groups))
 
 ;;; Buffer.
@@ -1506,7 +1521,7 @@ Optional NAME is the name of the buffer.
 OPTIONS should be an alist of the form ((SYMBOL WIDGET)...), where
 SYMBOL is a customization option, and WIDGET is a widget for editing
 that option."
-  (pop-to-buffer (custom-get-fresh-buffer (or name "*Customization*")))
+  (pop-to-buffer-same-window (custom-get-fresh-buffer (or name "*Customization*")))
   (custom-buffer-create-internal options description))
 
 ;;;###autoload
@@ -1518,17 +1533,15 @@ OPTIONS should be an alist of the form ((SYMBOL WIDGET)...), where
 SYMBOL is a customization option, and WIDGET is a widget for editing
 that option."
   (unless name (setq name "*Customization*"))
-  (let ((pop-up-windows t)
-       (same-window-buffer-names nil)
-       (same-window-regexps nil))
-    (pop-to-buffer (custom-get-fresh-buffer name))
-    (custom-buffer-create-internal options description)))
+  (switch-to-buffer-other-window (custom-get-fresh-buffer name))
+  (custom-buffer-create-internal options description))
 
-(defcustom custom-reset-button-menu nil
+(defcustom custom-reset-button-menu t
   "If non-nil, only show a single reset button in customize buffers.
 This button will have a menu with all three reset operations."
   :type 'boolean
-  :group 'custom-buffer)
+  :group 'custom-buffer
+  :version "24.3")
 
 (defcustom custom-buffer-verbose-help t
   "If non-nil, include explanatory text in the customization buffer."
@@ -1578,13 +1591,12 @@ Otherwise use brackets."
   (let ((init-file (or custom-file user-init-file)))
     ;; Insert verbose help at the top of the custom buffer.
     (when custom-buffer-verbose-help
-      (widget-insert (if init-file
-                        "To apply changes, use the Save or Set buttons."
-                      "Custom settings cannot be saved; maybe you started Emacs with `-q'.")
-                    "\nFor details, see ")
+      (unless init-file
+       (widget-insert "Custom settings cannot be saved; maybe you started Emacs with `-q'.\n"))
+      (widget-insert "For help using this buffer, see ")
       (widget-create 'custom-manual
-                    :tag "Saving Customizations"
-                    "(emacs)Saving Customizations")
+                    :tag "Easy Customization"
+                    "(emacs)Easy Customization")
       (widget-insert " in the ")
       (widget-create 'custom-manual
                     :tag "Emacs manual"
@@ -1596,7 +1608,9 @@ Otherwise use brackets."
     ;; Insert the search field.
     (when custom-search-field
       (widget-insert "\n")
-      (let* ((echo "Search for custom items")
+      (let* ((echo "Search for custom items.
+You can enter one or more words separated by spaces,
+or a regular expression.")
             (search-widget
              (widget-create
               'editable-field
@@ -1609,7 +1623,7 @@ Otherwise use brackets."
         :tag " Search "
         :help-echo echo :action
         (lambda (widget &optional _event)
-          (customize-apropos (widget-value (widget-get widget :parent)))))
+          (customize-apropos (split-string (widget-value (widget-get widget :parent))))))
        (widget-insert "\n")))
 
     ;; The custom command buttons are also in the toolbar, so for a
@@ -1621,29 +1635,30 @@ Otherwise use brackets."
     ;; So now the buttons are always inserted in the buffer.  (Bug#1326)
     (if custom-buffer-verbose-help
        (widget-insert "
- Operate on all settings in this buffer:\n"))
+Operate on all settings in this buffer:\n"))
     (let ((button (lambda (tag action active help _icon _label)
                    (widget-insert " ")
                    (if (eval active)
                        (widget-create 'push-button :tag tag
                                       :help-echo help :action action))))
          (commands custom-commands))
-      (apply button (pop commands)) ; Set for current session
-      (apply button (pop commands)) ; Save for future sessions
       (if custom-reset-button-menu
          (progn
-           (widget-insert " ")
            (widget-create 'push-button
-                          :tag "Reset buffer"
+                          :tag " Revert... "
                           :help-echo "Show a menu with reset operations."
                           :mouse-down-action 'ignore
-                          :action 'custom-reset))
+                          :action 'custom-reset)
+           (apply button (pop commands))  ; Apply
+           (apply button (pop commands))) ; Apply and Save
+       (apply button (pop commands))   ; Apply
+       (apply button (pop commands))   ; Apply and Save
        (widget-insert "\n")
-       (apply button (pop commands)) ; Undo edits
-       (apply button (pop commands)) ; Reset to saved
-       (apply button (pop commands)) ; Erase customization
+       (apply button (pop commands))   ; Undo
+       (apply button (pop commands))   ; Reset
+       (apply button (pop commands))   ; Erase
        (widget-insert "  ")
-       (pop commands) ; Help (omitted)
+       (pop commands)                  ; Help (omitted)
        (apply button (pop commands)))) ; Exit
     (widget-insert "\n\n"))
 
@@ -1697,7 +1712,7 @@ Otherwise use brackets."
   (unless group
     (setq group 'emacs))
   (let ((name "*Customize Browser*"))
-    (pop-to-buffer (custom-get-fresh-buffer name)))
+    (pop-to-buffer-same-window (custom-get-fresh-buffer name)))
   (Custom-mode)
   (widget-insert (format "\
 %s buttons; type RET or click mouse-1
@@ -1806,6 +1821,7 @@ item in another window.\n\n"))
 ;; We want simple widgets to be displayed by default, but complex
 ;; widgets to be hidden.
 
+;; This widget type is obsolete as of Emacs 24.1.
 (widget-put (get 'item 'widget-type) :custom-show t)
 (widget-put (get 'editable-field 'widget-type)
            :custom-show (lambda (_widget value)
@@ -1837,64 +1853,52 @@ item in another window.\n\n"))
   :group 'custom-buffer)
 
 (defface custom-invalid '((((class color))
-                          (:foreground "yellow1" :background "red1"))
-                         (t
-                          (:weight bold :slant italic :underline t)))
+                          :foreground "yellow1" :background "red1")
+                         (t :weight bold :slant italic :underline t))
   "Face used when the customize item is invalid."
   :group 'custom-magic-faces)
-(define-obsolete-face-alias 'custom-invalid-face 'custom-invalid "22.1")
 
 (defface custom-rogue '((((class color))
-                        (:foreground "pink" :background "black"))
-                       (t
-                        (:underline t)))
+                        :foreground "pink" :background "black")
+                       (t :underline t))
   "Face used when the customize item is not defined for customization."
   :group 'custom-magic-faces)
-(define-obsolete-face-alias 'custom-rogue-face 'custom-rogue "22.1")
 
 (defface custom-modified '((((min-colors 88) (class color))
-                           (:foreground "white" :background "blue1"))
+                           :foreground "white" :background "blue1")
                           (((class color))
-                           (:foreground "white" :background "blue"))
-                          (t
-                           (:slant italic :bold)))
+                           :foreground "white" :background "blue")
+                          (t :slant italic))
   "Face used when the customize item has been modified."
   :group 'custom-magic-faces)
-(define-obsolete-face-alias 'custom-modified-face 'custom-modified "22.1")
 
 (defface custom-set '((((min-colors 88) (class color))
-                      (:foreground "blue1" :background "white"))
+                      :foreground "blue1" :background "white")
                      (((class color))
-                      (:foreground "blue" :background "white"))
-                     (t
-                      (:slant italic)))
+                      :foreground "blue" :background "white")
+                     (t :slant italic))
   "Face used when the customize item has been set."
   :group 'custom-magic-faces)
-(define-obsolete-face-alias 'custom-set-face 'custom-set "22.1")
 
 (defface custom-changed '((((min-colors 88) (class color))
-                          (:foreground "white" :background "blue1"))
+                          :foreground "white" :background "blue1")
                          (((class color))
-                          (:foreground "white" :background "blue"))
-                         (t
-                          (:slant italic)))
+                          :foreground "white" :background "blue")
+                         (t :slant italic))
   "Face used when the customize item has been changed."
   :group 'custom-magic-faces)
-(define-obsolete-face-alias 'custom-changed-face 'custom-changed "22.1")
 
 (defface custom-themed '((((min-colors 88) (class color))
-                          (:foreground "white" :background "blue1"))
-                         (((class color))
-                          (:foreground "white" :background "blue"))
-                         (t
-                          (:slant italic)))
+                         :foreground "white" :background "blue1")
+                        (((class color))
+                         :foreground "white" :background "blue")
+                        (t :slant italic))
   "Face used when the customize item has been set by a theme."
   :group 'custom-magic-faces)
 
-(defface custom-saved '((t (:underline t)))
+(defface custom-saved '((t :underline t))
   "Face used when the customize item has been saved."
   :group 'custom-magic-faces)
-(define-obsolete-face-alias 'custom-saved-face 'custom-saved "22.1")
 
 (defconst custom-magic-alist
   '((nil "#" underline "\
@@ -2085,25 +2089,22 @@ and `face'."
 ;;; The `custom' Widget.
 
 (defface custom-button
-  '((((type x w32 ns) (class color))   ; Like default modeline
-     (:box (:line-width 2 :style released-button)
-          :background "lightgrey" :foreground "black"))
-    (t
-     nil))
+  '((((type x w32 ns) (class color))   ; Like default mode line
+     :box (:line-width 2 :style released-button)
+     :background "lightgrey" :foreground "black"))
   "Face for custom buffer buttons if `custom-raised-buttons' is non-nil."
   :version "21.1"
   :group 'custom-faces)
-(define-obsolete-face-alias 'custom-button-face 'custom-button "22.1")
 
 (defface custom-button-mouse
   '((((type x w32 ns) (class color))
-     (:box (:line-width 2 :style released-button)
-          :background "grey90" :foreground "black"))
+     :box (:line-width 2 :style released-button)
+     :background "grey90" :foreground "black")
     (t
      ;; This is for text terminals that support mouse, like GPM mouse
      ;; or the MS-DOS terminal: inverse-video makes the button stand
      ;; out on mouse-over.
-     (:inverse-video t)))
+     :inverse-video t))
   "Mouse face for custom buffer buttons if `custom-raised-buttons' is non-nil."
   :version "22.1"
   :group 'custom-faces)
@@ -2122,15 +2123,12 @@ and `face'."
 
 (defface custom-button-pressed
   '((((type x w32 ns) (class color))
-     (:box (:line-width 2 :style pressed-button)
-          :background "lightgrey" :foreground "black"))
-    (t
-     (:inverse-video t)))
+     :box (:line-width 2 :style pressed-button)
+     :background "lightgrey" :foreground "black")
+    (t :inverse-video t))
   "Face for pressed custom buttons if `custom-raised-buttons' is non-nil."
   :version "21.1"
   :group 'custom-faces)
-(define-obsolete-face-alias 'custom-button-pressed-face
-  'custom-button-pressed "22.1")
 
 (defface custom-button-pressed-unraised
   '((default :inherit custom-button-unraised)
@@ -2148,22 +2146,15 @@ and `face'."
 (defface custom-documentation '((t nil))
   "Face used for documentation strings in customization buffers."
   :group 'custom-faces)
-(define-obsolete-face-alias 'custom-documentation-face
-  'custom-documentation "22.1")
-
-(defface custom-state '((((class color)
-                         (background dark))
-                        (:foreground "lime green"))
-                       (((class color)
-                         (background light))
-                        (:foreground "dark green"))
-                       (t nil))
+
+(defface custom-state '((((class color) (background dark))
+                        :foreground "lime green")
+                       (((class color) (background light))
+                        :foreground "dark green"))
   "Face used for State descriptions in the customize buffer."
   :group 'custom-faces)
-(define-obsolete-face-alias 'custom-state-face 'custom-state "22.1")
 
-(defface custom-link
-  '((t :inherit link))
+(defface custom-link '((t :inherit link))
   "Face for links in customization buffers."
   :version "22.1"
   :group 'custom-faces)
@@ -2234,6 +2225,7 @@ and `face'."
             (setq widget nil)))))
   (widget-setup))
 
+(make-obsolete 'custom-show "this widget type is no longer supported." "24.1")
 (defun custom-show (widget value)
   "Non-nil if WIDGET should be shown with VALUE by default."
   (let ((show (widget-get widget :custom-show)))
@@ -2359,20 +2351,18 @@ If INITIAL-STRING is non-nil, use that rather than \"Parent groups:\"."
   "Face used for comments on variables or faces."
   :version "21.1"
   :group 'custom-faces)
-(define-obsolete-face-alias 'custom-comment-face 'custom-comment "22.1")
 
 ;; like font-lock-comment-face
 (defface custom-comment-tag
-  '((((class color) (background dark)) (:foreground "gray80"))
-    (((class color) (background light)) (:foreground "blue4"))
+  '((((class color) (background dark)) :foreground "gray80")
+    (((class color) (background light)) :foreground "blue4")
     (((class grayscale) (background light))
-     (:foreground "DimGray" :weight bold :slant italic))
+     :foreground "DimGray" :weight bold :slant italic)
     (((class grayscale) (background dark))
-     (:foreground "LightGray" :weight bold :slant italic))
-    (t (:weight bold)))
+     :foreground "LightGray" :weight bold :slant italic)
+    (t :weight bold))
   "Face used for the comment tag on variables or faces."
   :group 'custom-faces)
-(define-obsolete-face-alias 'custom-comment-tag-face 'custom-comment-tag "22.1")
 
 (define-widget 'custom-comment 'string
   "User comment."
@@ -2411,26 +2401,19 @@ If INITIAL-STRING is non-nil, use that rather than \"Parent groups:\"."
 ;;; The `custom-variable' Widget.
 
 (defface custom-variable-tag
-  `((((class color)
-      (background dark))
-     (:foreground "light blue" :weight bold))
-    (((min-colors 88) (class color)
-      (background light))
-     (:foreground "blue1" :weight bold))
-    (((class color)
-      (background light))
-     (:foreground "blue" :weight bold))
-    (t (:weight bold)))
+  `((((class color) (background dark))
+     :foreground "light blue" :weight bold)
+    (((min-colors 88) (class color) (background light))
+     :foreground "blue1" :weight bold)
+    (((class color) (background light))
+     :foreground "blue" :weight bold)
+    (t :weight bold))
   "Face used for unpushable variable tags."
   :group 'custom-faces)
-(define-obsolete-face-alias 'custom-variable-tag-face
-  'custom-variable-tag "22.1")
 
-(defface custom-variable-button '((t (:underline t :weight bold)))
+(defface custom-variable-button '((t :underline t :weight bold))
   "Face used for pushable variable tags."
   :group 'custom-faces)
-(define-obsolete-face-alias 'custom-variable-button-face
-  'custom-variable-button "22.1")
 
 (defcustom custom-variable-default-form 'edit
   "Default form of displaying variable values."
@@ -2443,15 +2426,15 @@ If INITIAL-STRING is non-nil, use that rather than \"Parent groups:\"."
   "Return documentation of VARIABLE for use in Custom buffer.
 Normally just return the docstring.  But if VARIABLE automatically
 becomes buffer local when set, append a message to that effect."
-  (if (and (local-variable-if-set-p variable)
-          (or (not (local-variable-p variable))
-              (with-temp-buffer
-                (local-variable-if-set-p variable))))
-      (concat (documentation-property variable 'variable-documentation)
+  (format "%s%s" (documentation-property variable 'variable-documentation)
+         (if (and (local-variable-if-set-p variable)
+                  (or (not (local-variable-p variable))
+                      (with-temp-buffer
+                        (local-variable-if-set-p variable))))
              "\n
 This variable automatically becomes buffer-local when set outside Custom.
-However, setting it through Custom sets the default value.")
-    (documentation-property variable 'variable-documentation)))
+However, setting it through Custom sets the default value."
+           "")))
 
 (define-widget 'custom-variable 'custom
   "A widget for displaying a Custom variable.
@@ -2569,7 +2552,6 @@ try matching its doc string against `custom-guess-doc-alist'."
                  :parent widget)
                 buttons))
          ((memq form '(lisp mismatch))
-          ;; In lisp mode edit the saved value when possible.
           (push (widget-create-child-and-convert
                  widget 'custom-visibility
                  :help-echo "Hide the value of this option."
@@ -2581,11 +2563,10 @@ try matching its doc string against `custom-guess-doc-alist'."
                  t)
                 buttons)
           (insert " ")
-          (let* ((value (cond ((get symbol 'saved-value)
-                               (car (get symbol 'saved-value)))
-                              ((get symbol 'standard-value)
-                               (car (get symbol 'standard-value)))
-                              ((default-boundp symbol)
+          ;; This used to try presenting the saved value or the
+          ;; standard value, but it seems more intuitive to present
+          ;; the current value (Bug#7600).
+          (let* ((value (cond ((default-boundp symbol)
                                (custom-quote (funcall get symbol)))
                               (t
                                (custom-quote (widget-get conv :value))))))
@@ -2794,12 +2775,10 @@ If STATE is nil, the value is computed by `custom-variable-state'."
      (lambda (widget)
        (and (default-boundp (widget-value widget))
            (memq (widget-get widget :custom-state) '(modified changed)))))
-    ("Reset to Saved" custom-variable-reset-saved
+    ("Revert This Session's Customization" custom-variable-reset-saved
      (lambda (widget)
-       (and (or (get (widget-value widget) 'saved-value)
-               (get (widget-value widget) 'saved-variable-comment))
-           (memq (widget-get widget :custom-state)
-                 '(modified set changed rogue)))))
+       (memq (widget-get widget :custom-state)
+            '(modified set changed rogue))))
     ,@(when (or custom-file init-file-user)
        '(("Erase Customization" custom-variable-reset-standard
           (lambda (widget)
@@ -2866,7 +2845,7 @@ Optional EVENT is the location for the menu."
         (comment (widget-value comment-widget))
         val)
     (cond ((eq state 'hidden)
-          (error "Cannot set hidden variable"))
+          (user-error "Cannot set hidden variable"))
          ((setq val (widget-apply child :validate))
           (goto-char (widget-get val :from))
           (error "%s" (widget-get val :error)))
@@ -2908,7 +2887,7 @@ Optional EVENT is the location for the menu."
         (comment (widget-value comment-widget))
         val)
     (cond ((eq state 'hidden)
-          (error "Cannot set hidden variable"))
+          (user-error "Cannot set hidden variable"))
          ((setq val (widget-apply child :validate))
           (goto-char (widget-get val :from))
           (error "Saving %s: %s" symbol (widget-get val :error)))
@@ -2950,23 +2929,25 @@ Optional EVENT is the location for the menu."
   (custom-variable-state-set-and-redraw widget))
 
 (defun custom-variable-reset-saved (widget)
-  "Restore the saved value for the variable being edited by WIDGET.
-This also updates the buffer to show that value.
-The value that was current before this operation
-becomes the backup value, so you can get it again."
+  "Restore the value of the variable being edited by WIDGET.
+If there is a saved value, restore it; otherwise reset to the
+uncustomized (themed or standard) value.
+
+Update the widget to show that value.  The value that was current
+before this operation becomes the backup value."
   (let* ((symbol (widget-value widget))
-        (set (or (get symbol 'custom-set) 'set-default))
-        (value (get symbol 'saved-value))
+        (saved-value (get symbol 'saved-value))
         (comment (get symbol 'saved-variable-comment)))
-    (cond ((or value comment)
-          (put symbol 'variable-comment comment)
-          (custom-variable-backup-value widget)
-          (custom-push-theme 'theme-value symbol 'user 'set (car-safe value))
-          (condition-case nil
-              (funcall set symbol (eval (car value)))
-            (error nil)))
-         (t
-          (error "No saved value for %s" symbol)))
+    (custom-variable-backup-value widget)
+    (if (not (or saved-value comment))
+       ;; If there is no saved value, remove the setting.
+       (custom-push-theme 'theme-value symbol 'user 'reset)
+      ;; Otherwise, apply the saved value.
+      (put symbol 'variable-comment comment)
+      (custom-push-theme 'theme-value symbol 'user 'set (car-safe saved-value))
+      (ignore-errors
+       (funcall (or (get symbol 'custom-set) 'set-default)
+                symbol (eval (car saved-value)))))
     (put symbol 'customized-value nil)
     (put symbol 'customized-variable-comment nil)
     (widget-put widget :custom-state 'unknown)
@@ -2980,7 +2961,7 @@ redraw the widget immediately."
   (let* ((symbol (widget-value widget)))
     (if (get symbol 'standard-value)
        (custom-variable-backup-value widget)
-      (error "No standard setting known for %S" symbol))
+      (user-error "No standard setting known for %S" symbol))
     (put symbol 'variable-comment nil)
     (put symbol 'customized-value nil)
     (put symbol 'customized-variable-comment nil)
@@ -3042,8 +3023,8 @@ to switch between two values."
          (condition-case nil
              (funcall set symbol (car value))
             (error nil)))
-      (error "No backup value for %s" symbol))
-    (put symbol 'customized-value (list (car value)))
+      (user-error "No backup value for %s" symbol))
+    (put symbol 'customized-value (list (custom-quote (car value))))
     (put symbol 'variable-comment comment)
     (put symbol 'customized-variable-comment comment)
     (custom-variable-state-set widget)
@@ -3195,7 +3176,7 @@ Also change :reverse-video to :inverse-video."
     (if (not inactive)
        ;; Widget is alive, we don't have to do anything special
        (widget-default-delete widget)
-      ;; WIDGET is already deleted because we did so to inactivate it;
+      ;; WIDGET is already deleted because we did so to deactivate it;
       ;; now just get rid of the label we put in its place.
       (delete-region (car (cdr inactive))
                     (+ (car (cdr inactive)) (cdr (cdr inactive))))
@@ -3221,6 +3202,7 @@ Also change :reverse-video to :inverse-video."
   :args '((const :tag "all" t)
          (const :tag "defaults" default)
          (checklist
+          :tag "specific display"
           :offset 0
           :extra-offset 9
           :args ((group :sibling-args (:help-echo "\
@@ -3298,10 +3280,9 @@ Only match frames that support the specified face attributes.")
 ;;; The `custom-face' Widget.
 
 (defface custom-face-tag
-  `((t :inherit custom-variable-tag))
+  '((t :inherit custom-variable-tag))
   "Face used for face tags."
   :group 'custom-faces)
-(define-obsolete-face-alias 'custom-face-tag-face 'custom-face-tag "22.1")
 
 (defcustom custom-face-default-form 'selected
   "Default form of displaying face definition."
@@ -3589,10 +3570,9 @@ the present value is saved to its :shown-value property instead."
     ("Undo Edits" custom-redraw
      (lambda (widget)
        (memq (widget-get widget :custom-state) '(modified changed))))
-    ("Reset to Saved" custom-face-reset-saved
+    ("Revert This Session's Customization" custom-face-reset-saved
      (lambda (widget)
-       (or (get (widget-value widget) 'saved-face)
-          (get (widget-value widget) 'saved-face-comment))))
+       (memq (widget-get widget :custom-state) '(modified set changed))))
     ,@(when (or custom-file init-file-user)
        '(("Erase Customization" custom-face-reset-standard
           (lambda (widget)
@@ -3647,18 +3627,17 @@ This is one of `set', `saved', `changed', `themed', or `rogue'."
              'changed))
           ((or (get face 'saved-face)
                (get face 'saved-face-comment))
-           (if (equal (get face 'saved-face-comment) comment)
-               (cond
-                ((eq 'user (caar (get face 'theme-face)))
-                 'saved)
-                ((eq 'changed (caar (get face 'theme-face)))
-                 'changed)
-                (t 'themed))
-             'changed))
+           (cond ((not (equal (get face 'saved-face-comment) comment))
+                  'changed)
+                 ((eq 'user (caar (get face 'theme-face)))
+                  'saved)
+                 ((eq 'changed (caar (get face 'theme-face)))
+                  'changed)
+                 (t 'themed)))
           ((get face 'face-defface-spec)
-           (if (equal comment nil)
-               'standard
-             'changed))
+           (cond (comment 'changed)
+                 ((get face 'theme-face) 'themed)
+                 (t 'standard)))
           (t 'rogue))))
     ;; If the user called set-face-attribute to change the default for
     ;; new frames, this face is "set outside of Customize".
@@ -3748,24 +3727,26 @@ Optional EVENT is the location for the menu."
   "22.1")
 
 (defun custom-face-reset-saved (widget)
-  "Restore WIDGET to the face's default attributes."
-  (let* ((symbol (widget-value widget))
+  "Restore WIDGET to the face's default attributes.
+If there is a saved face, restore it; otherwise reset to the
+uncustomized (themed or standard) face."
+  (let* ((face (widget-value widget))
         (child (car (widget-get widget :children)))
-        (value (get symbol 'saved-face))
-        (comment (get symbol 'saved-face-comment))
+        (saved-face (get face 'saved-face))
+        (comment (get face 'saved-face-comment))
         (comment-widget (widget-get widget :comment-widget)))
-    (unless (or value comment)
-      (error "No saved value for this face"))
-    (put symbol 'customized-face nil)
-    (put symbol 'customized-face-comment nil)
-    (custom-push-theme 'theme-face symbol 'user 'set value)
-    (face-spec-set symbol value t)
-    (put symbol 'face-comment comment)
-    (widget-value-set child value)
+    (put face 'customized-face nil)
+    (put face 'customized-face-comment nil)
+    (custom-push-theme 'theme-face face 'user
+                      (if saved-face 'set 'reset)
+                      saved-face)
+    (face-spec-set face saved-face t)
+    (put face 'face-comment comment)
+    (widget-value-set child saved-face)
     ;; This call manages the comment visibility
     (widget-value-set comment-widget (or comment ""))
     (custom-face-state-set widget)
-    (custom-redraw-magic widget)))
+    (custom-redraw widget)))
 
 (defun custom-face-standard-value (widget)
   (get (widget-value widget) 'face-defface-spec))
@@ -3779,7 +3760,7 @@ redraw the widget immediately."
         (value (get symbol 'face-defface-spec))
         (comment-widget (widget-get widget :comment-widget)))
     (unless value
-      (error "No standard setting for this face"))
+      (user-error "No standard setting for this face"))
     (put symbol 'customized-face nil)
     (put symbol 'customized-face-comment nil)
     (custom-push-theme 'theme-face symbol 'user 'reset)
@@ -3909,8 +3890,6 @@ restoring it to the state of a face that has never been customized."
 ;;; The `custom-group' Widget.
 
 (defcustom custom-group-tag-faces nil
-  ;; In XEmacs, this ought to play games with font size.
-  ;; Fixme: make it do so in Emacs.
   "Face used for group tags.
 The first member is used for level 1 groups, the second for level 2,
 and so forth.  The remaining group tags are shown with `custom-group-tag'."
@@ -3918,34 +3897,28 @@ and so forth.  The remaining group tags are shown with `custom-group-tag'."
   :group 'custom-faces)
 
 (defface custom-group-tag-1
-  `((((class color)
-      (background dark))
-     (:foreground "pink" :weight bold :height 1.2 :inherit variable-pitch))
-    (((min-colors 88) (class color)
-      (background light))
-     (:foreground "red1" :weight bold :height 1.2 :inherit variable-pitch))
-    (((class color)
-      (background light))
-     (:foreground "red" :weight bold :height 1.2 :inherit variable-pitch))
-    (t (:weight bold)))
-  "Face used for group tags."
+  '((default :weight bold :height 1.2 :inherit variable-pitch)
+    (((class color) (background dark)) :foreground "pink")
+    (((min-colors 88) (class color) (background light)) :foreground "red1")
+    (((class color) (background light)) :foreground "red"))
+  "Face for group tags."
   :group 'custom-faces)
-(define-obsolete-face-alias 'custom-group-tag-face-1 'custom-group-tag-1 "22.1")
 
 (defface custom-group-tag
-  `((((class color)
-      (background dark))
-     (:foreground "light blue" :weight bold :height 1.2 :inherit variable-pitch))
-    (((min-colors 88) (class color)
-      (background light))
-     (:foreground "blue1" :weight bold :height 1.2 :inherit variable-pitch))
-    (((class color)
-      (background light))
-     (:foreground "blue" :weight bold :height 1.2 :inherit variable-pitch))
-    (t (:weight bold)))
-  "Face used for low level group tags."
+  '((default :weight bold :height 1.2 :inherit variable-pitch)
+    (((class color) (background dark)) :foreground "light blue")
+    (((min-colors 88) (class color) (background light)) :foreground "blue1")
+    (((class color) (background light)) :foreground "blue")
+    (t :weight bold))
+  "Face for low level group tags."
+  :group 'custom-faces)
+
+(defface custom-group-subtitle
+  '((t :weight bold))
+  "Face for the \"Subgroups:\" subtitle in Custom buffers."
   :group 'custom-faces)
-(define-obsolete-face-alias 'custom-group-tag-face 'custom-group-tag "22.1")
+
+(defvar custom-group-doc-align-col 20)
 
 (define-widget 'custom-group 'custom
   "Customize group."
@@ -4012,11 +3985,9 @@ If GROUPS-ONLY non-nil, return only those members that are groups."
           (custom-browse-insert-prefix prefix)
           (push (widget-create-child-and-convert
                  widget 'custom-browse-visibility
-                 ;; :tag-glyph "plus"
                  :tag "+")
                 buttons)
           (insert "-- ")
-          ;; (widget-glyph-insert nil "-- " "horizontal")
           (push (widget-create-child-and-convert
                  widget 'custom-browse-group-tag)
                 buttons)
@@ -4026,8 +3997,6 @@ If GROUPS-ONLY non-nil, return only those members that are groups."
                (zerop (length members)))
           (custom-browse-insert-prefix prefix)
           (insert "[ ]-- ")
-          ;; (widget-glyph-insert nil "[ ]" "empty")
-          ;; (widget-glyph-insert nil "-- " "horizontal")
           (push (widget-create-child-and-convert
                  widget 'custom-browse-group-tag)
                 buttons)
@@ -4105,7 +4074,8 @@ If GROUPS-ONLY non-nil, return only those members that are groups."
                    :action 'custom-toggle-parent
                    (not (eq state 'hidden)))
                   buttons))
-          (insert " : ")
+          (if (>= (current-column) custom-group-doc-align-col)
+              (insert "  "))
           ;; Create magic button.
           (let ((magic (widget-create-child-and-convert
                         widget 'custom-magic nil)))
@@ -4115,7 +4085,8 @@ If GROUPS-ONLY non-nil, return only those members that are groups."
           (widget-put widget :buttons buttons)
           ;; Insert documentation.
           (if (and (eq custom-buffer-style 'links) (> level 1))
-              (widget-put widget :documentation-indent 0))
+              (widget-put widget :documentation-indent
+                          custom-group-doc-align-col))
           (widget-add-documentation-string-button
            widget :visibility-widget 'custom-visibility))
 
@@ -4193,25 +4164,34 @@ If GROUPS-ONLY non-nil, return only those members that are groups."
                  (count 0)
                  (reporter (make-progress-reporter
                             "Creating group entries..." 0 len))
+                 (have-subtitle (and (not (eq symbol 'emacs))
+                                     (eq custom-buffer-order-groups 'last)))
+                 prev-type
                  children)
-            (setq children
-                  (mapcar
-                   (lambda (entry)
-                     (widget-insert "\n")
-                     (progress-reporter-update reporter (setq count (1+ count)))
-                     (let ((sym (nth 0 entry))
-                           (type (nth 1 entry)))
-                       (prog1
-                           (widget-create-child-and-convert
-                            widget type
-                            :group widget
-                            :tag (custom-unlispify-tag-name sym)
-                            :custom-prefixes custom-prefix-list
-                            :custom-level (1+ level)
-                            :value sym)
-                         (unless (eq (preceding-char) ?\n)
-                           (widget-insert "\n")))))
-                   members))
+
+            (dolist (entry members)
+              (unless (eq prev-type 'custom-group)
+                (widget-insert "\n"))
+              (progress-reporter-update reporter (setq count (1+ count)))
+              (let ((sym (nth 0 entry))
+                    (type (nth 1 entry)))
+                (when (and have-subtitle (eq type 'custom-group))
+                  (setq have-subtitle nil)
+                  (widget-insert
+                   (propertize "Subgroups:\n" 'face 'custom-group-subtitle)))
+                (setq prev-type type)
+                (push (widget-create-child-and-convert
+                       widget type
+                       :group widget
+                       :tag (custom-unlispify-tag-name sym)
+                       :custom-prefixes custom-prefix-list
+                       :custom-level (1+ level)
+                       :value sym)
+                      children)
+                (unless (eq (preceding-char) ?\n)
+                  (widget-insert "\n"))))
+
+            (setq children (nreverse children))
             (mapc 'custom-magic-reset children)
             (widget-put widget :children children)
             (custom-group-state-update widget)
@@ -4236,7 +4216,7 @@ If GROUPS-ONLY non-nil, return only those members that are groups."
     ("Undo Edits" custom-group-reset-current
      (lambda (widget)
        (memq (widget-get widget :custom-state) '(modified))))
-    ("Reset to Saved" custom-group-reset-saved
+    ("Revert This Session's Customizations" custom-group-reset-saved
      (lambda (widget)
        (memq (widget-get widget :custom-state) '(modified set))))
     ,@(when (or custom-file init-file-user)
@@ -4378,23 +4358,16 @@ Click on \"More\" \(or position point there and press RETURN)
 if only the first line of the docstring is shown."))
   :group 'customize)
 
-(defun custom-file ()
+(defun custom-file (&optional no-error)
   "Return the file name for saving customizations."
-  (file-chase-links
-   (or custom-file
-       (let ((user-init-file user-init-file)
-            (default-init-file
-              (if (eq system-type 'ms-dos) "~/_emacs" "~/.emacs")))
-        (when (null user-init-file)
-          (if (or (file-exists-p default-init-file)
-                  (and (eq system-type 'windows-nt)
-                       (file-exists-p "~/_emacs")))
-              ;; Started with -q, i.e. the file containing
-              ;; Custom settings hasn't been read.  Saving
-              ;; settings there would overwrite other settings.
-              (error "Saving settings from \"emacs -q\" would overwrite existing customizations"))
-          (setq user-init-file default-init-file))
-        user-init-file))))
+  (if (null user-init-file)
+      ;; Started with -q, i.e. the file containing Custom settings
+      ;; hasn't been read.  Saving settings there won't make much
+      ;; sense.
+      (if no-error
+         nil
+       (user-error "Saving settings from \"emacs -q\" would overwrite existing customizations"))
+    (file-chase-links (or custom-file user-init-file))))
 
 ;; If recentf-mode is non-nil, this is defined.
 (declare-function recentf-expand-file-name "recentf" (name))
@@ -4804,6 +4777,7 @@ If several parents are listed, go to the first of them."
     (set (make-local-variable 'widget-link-suffix) ""))
   (setq show-trailing-whitespace nil))
 
+(define-obsolete-variable-alias 'custom-mode-hook 'Custom-mode-hook "23.1")
 (define-derived-mode Custom-mode nil "Custom"
   "Major mode for editing customization buffers.
 
@@ -4852,20 +4826,8 @@ if that value is non-nil."
   (Custom-mode))
 (make-obsolete 'custom-mode 'Custom-mode "23.1")
 (put 'custom-mode 'mode-class 'special)
-(define-obsolete-variable-alias 'custom-mode-hook 'Custom-mode-hook "23.1")
 
-(dolist (regexp
-        '("^No user option defaults have been changed since Emacs "
-          "^Invalid face:? "
-          "^No \\(?:customized\\|rogue\\|saved\\) user options"
-          "^No customizable items matching "
-          "^There are unset changes"
-          "^Cannot set hidden variable"
-          "^No \\(?:saved\\|backup\\) value for "
-          "^No standard setting known for "
-          "^No standard setting for this face"
-          "^Saving settings from \"emacs -q\" would overwrite existing customizations"))
-  (add-to-list 'debug-ignored-errors regexp))
+(add-to-list 'debug-ignored-errors "^Invalid face:? ")
 
 ;;; The End.