]> code.delx.au - gnu-emacs/blobdiff - lisp/cus-edit.el
(tar-header-block-tokenize): Decode codes of file
[gnu-emacs] / lisp / cus-edit.el
index 156b78b793f76f73e982eb2ff76e7a1f25b665b2..b6c60a4129c1f6804d288419ca301d5fe1b91413 100644 (file)
@@ -1,10 +1,10 @@
-;;; cus-edit.el --- Tools for customization Emacs.
+;;; cus-edit.el --- Tools for customizating Emacs and Lisp packages.
 ;;
 ;; Copyright (C) 1996, 1997 Free Software Foundation, Inc.
 ;;
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Keywords: help, faces
 ;;
 ;; Copyright (C) 1996, 1997 Free Software Foundation, Inc.
 ;;
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Keywords: help, faces
-;; Version: 1.9942
+;; Version: 1.9954
 ;; X-URL: http://www.dina.kvl.dk/~abraham/custom/
 
 ;; This file is part of GNU Emacs.
 ;; X-URL: http://www.dina.kvl.dk/~abraham/custom/
 
 ;; This file is part of GNU Emacs.
   :group 'external
   :group 'development)
 
   :group 'external
   :group 'development)
 
+(defgroup convenience nil
+  "Convenience features for faster editing."
+  :group 'emacs)
+
 (defgroup programming nil
   "Support for programming in other languages."
   :group 'emacs)
 (defgroup programming nil
   "Support for programming in other languages."
   :group 'emacs)
 
 (defgroup customize '((widgets custom-group))
   "Customization of the Customization support."
 
 (defgroup customize '((widgets custom-group))
   "Customization of the Customization support."
-  :link '(custom-manual "(custom)Top")
+  :link '(custom-manual "(elisp)Customization")
   :link '(url-link :tag "Development Page" 
                   "http://www.dina.kvl.dk/~abraham/custom/")
   :prefix "custom-"
   :link '(url-link :tag "Development Page" 
                   "http://www.dina.kvl.dk/~abraham/custom/")
   :prefix "custom-"
@@ -408,7 +412,7 @@ Return a list suitable for use in `interactive'."
                obarray (lambda (symbol)
                          (and (boundp symbol)
                               (or (get symbol 'custom-type)
                obarray (lambda (symbol)
                          (and (boundp symbol)
                               (or (get symbol 'custom-type)
-                                  (user-variable-p symbol))))))
+                                  (user-variable-p symbol)))) t))
      (list (if (equal val "")
               (if (symbolp v) v nil)
             (intern val)))))
      (list (if (equal val "")
               (if (symbolp v) v nil)
             (intern val)))))
@@ -440,6 +444,11 @@ WIDGET is the widget to apply the filter entries of MENU on."
   :group 'custom-menu
   :type 'boolean)
 
   :group 'custom-menu
   :type 'boolean)
 
+(defcustom custom-unlispify-remove-prefixes nil
+  "Non-nil means remove group prefixes from option names in buffer."
+  :group 'custom-menu
+  :type 'boolean)
+
 (defun custom-unlispify-menu-entry (symbol &optional no-suffix)
   "Convert symbol into a menu entry."
   (cond ((not custom-unlispify-menu-entries)
 (defun custom-unlispify-menu-entry (symbol &optional no-suffix)
   "Convert symbol into a menu entry."
   (cond ((not custom-unlispify-menu-entries)
@@ -458,15 +467,16 @@ WIDGET is the widget to apply the filter entries of MENU on."
                      (re-search-forward "-p\\'" nil t))
             (replace-match "" t t)
             (goto-char (point-min)))
                      (re-search-forward "-p\\'" nil t))
             (replace-match "" t t)
             (goto-char (point-min)))
-          (let ((prefixes custom-prefix-list)
-                prefix)
-            (while prefixes
-              (setq prefix (car prefixes))
-              (if (search-forward prefix (+ (point) (length prefix)) t)
-                  (progn 
-                    (setq prefixes nil)
-                    (delete-region (point-min) (point)))
-                (setq prefixes (cdr prefixes)))))
+          (if custom-unlispify-remove-prefixes
+              (let ((prefixes custom-prefix-list)
+                    prefix)
+                (while prefixes
+                  (setq prefix (car prefixes))
+                  (if (search-forward prefix (+ (point) (length prefix)) t)
+                      (progn 
+                        (setq prefixes nil)
+                        (delete-region (point-min) (point)))
+                    (setq prefixes (cdr prefixes))))))
           (subst-char-in-region (point-min) (point-max) ?- ?\  t)
           (capitalize-region (point-min) (point-max))
           (unless no-suffix 
           (subst-char-in-region (point-min) (point-max) ?- ?\  t)
           (capitalize-region (point-min) (point-max))
           (unless no-suffix 
@@ -601,6 +611,8 @@ If `last', order groups after non-groups."
                 (const :tag "none" nil))
   :group 'custom-menu)
 
                 (const :tag "none" nil))
   :group 'custom-menu)
 
+;;;###autoload (add-hook 'same-window-regexps "\\`\\*Customiz.*\\*\\'")
+
 (defun custom-sort-items (items sort-alphabetically order-groups)
   "Return a sorted copy of ITEMS.
 ITEMS should be a `custom-group' property.
 (defun custom-sort-items (items sort-alphabetically order-groups)
   "Return a sorted copy of ITEMS.
 ITEMS should be a `custom-group' property.
@@ -647,7 +659,8 @@ groups after non-groups, if nil do not order groups at all."
   (interactive)
   (let ((children custom-options))
     (mapcar (lambda (child)
   (interactive)
   (let ((children custom-options))
     (mapcar (lambda (child)
-             (when (memq (widget-get child :custom-state) '(modified set))
+             (when (memq (widget-get child :custom-state)
+                         '(modified set changed rogue))
                (widget-apply child :custom-save)))
            children))
   (custom-save-all))
                (widget-apply child :custom-save)))
            children))
   (custom-save-all))
@@ -674,27 +687,33 @@ when the action is chosen.")
   "Reset all modified group members to their current value."
   (interactive)
   (let ((children custom-options))
   "Reset all modified group members to their current value."
   (interactive)
   (let ((children custom-options))
-    (mapcar (lambda (child)
-             (when (eq (widget-get child :custom-state) 'modified)
-               (widget-apply child :custom-reset-current)))
+    (mapcar (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))
            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 (child)
-             (when (eq (widget-get child :custom-state) 'modified)
-               (widget-apply child :custom-reset-saved)))
+    (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))))
            children)))
 
 (defun Custom-reset-standard (&rest ignore)
   "Reset all modified, set, or saved group members to their standard settings."
   (interactive)
   (let ((children custom-options))
            children)))
 
 (defun Custom-reset-standard (&rest ignore)
   "Reset all modified, set, or saved group members to their standard settings."
   (interactive)
   (let ((children custom-options))
-    (mapcar (lambda (child)
-             (when (eq (widget-get child :custom-state) 'modified)
-               (widget-apply child :custom-reset-standard)))
+    (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))))
            children)))
 
 ;;; The Customize Commands
            children)))
 
 ;;; The Customize Commands
@@ -767,6 +786,26 @@ If VARIABLE has a `custom-type' property, it must be a widget and the
   (funcall (or (get var 'custom-set) 'set-default) var val)
   (put var 'customized-value (list (custom-quote val))))
 
   (funcall (or (get var 'custom-set) 'set-default) var val)
   (put var 'customized-value (list (custom-quote val))))
 
+;;;###autoload
+(defun customize-save-variable (var val)
+  "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.
+
+The `customized-value' property of the VARIABLE will be set to a list
+with a quoted VALUE as its sole list member.
+
+If VARIABLE has a `variable-interactive' property, that is used as if
+it were the arg to `interactive' (which see) to interactively read the value.
+
+If VARIABLE has a `custom-type' property, it must be a widget and the
+`:prompt-value' property of that widget will be used for reading the value. " 
+  (interactive (custom-prompt-variable "Set and ave variable: "
+                                      "Set and save value for %s as: "))
+  (funcall (or (get var 'custom-set) 'set-default) var val)
+  (put var 'saved-value (list (custom-quote val)))
+  (custom-save-all))
+
 ;;;###autoload
 (defun customize ()
   "Select a customization buffer which you can use to set user options.
 ;;;###autoload
 (defun customize ()
   "Select a customization buffer which you can use to set user options.
@@ -783,36 +822,51 @@ are shown; the contents of those subgroups are initially hidden."
                       (completing-read "Customize group: (default emacs) "
                                        obarray 
                                        (lambda (symbol)
                       (completing-read "Customize group: (default emacs) "
                                        obarray 
                                        (lambda (symbol)
-                                         (get symbol 'custom-group))
+                                         (or (get symbol 'custom-loads)
+                                             (get symbol 'custom-group)))
                                        t))))
                                        t))))
-
   (when (stringp group)
     (if (string-equal "" group)
        (setq group 'emacs)
       (setq group (intern group))))
   (when (stringp group)
     (if (string-equal "" group)
        (setq group 'emacs)
       (setq group (intern group))))
+  (or (get group 'custom-group)
+      (custom-load-symbol group))
   (let ((name (format "*Customize Group: %s*"
                      (custom-unlispify-tag-name group))))
     (if (get-buffer name)
   (let ((name (format "*Customize Group: %s*"
                      (custom-unlispify-tag-name group))))
     (if (get-buffer name)
-       (switch-to-buffer name)
+       (pop-to-buffer name)
       (custom-buffer-create (list (list group 'custom-group))
       (custom-buffer-create (list (list group 'custom-group))
-                           name))))
+                           name
+                           (concat " for group "
+                                   (custom-unlispify-tag-name group))))))
 
 ;;;###autoload
 
 ;;;###autoload
-(defun customize-group-other-window (symbol)
-  "Customize SYMBOL, which must be a customization group."
-  (interactive (list (completing-read "Customize group: (default emacs) "
-                                     obarray 
-                                     (lambda (symbol)
-                                       (get symbol 'custom-group))
-                                     t)))
-
-  (when (stringp symbol)
-    (if (string-equal "" symbol)
-       (setq symbol 'emacs)
-      (setq symbol (intern symbol))))
-  (custom-buffer-create-other-window
-   (list (list symbol 'custom-group))
-   (format "*Customize Group: %s*" (custom-unlispify-tag-name symbol))))
+(defun customize-group-other-window (group)
+  "Customize GROUP, which must be a customization group."
+  (interactive (list (let ((completion-ignore-case t))
+                      (completing-read "Customize group: (default emacs) "
+                                       obarray 
+                                       (lambda (symbol)
+                                         (or (get symbol 'custom-loads)
+                                             (get symbol 'custom-group)))
+                                       t))))
+  (when (stringp group)
+    (if (string-equal "" group)
+       (setq group 'emacs)
+      (setq group (intern group))))
+  (or (get group 'custom-group)
+      (custom-load-symbol group))
+  (let ((name (format "*Customize Group: %s*"
+                     (custom-unlispify-tag-name group))))
+    (if (get-buffer name)
+       (let ((window (selected-window)))
+         (pop-to-buffer name)
+         (select-window window))
+      (custom-buffer-create-other-window
+       (list (list group 'custom-group))
+       name
+       (concat " for group "
+              (custom-unlispify-tag-name group))))))
 
 ;;;###autoload
 (defalias 'customize-variable 'customize-option)
 
 ;;;###autoload
 (defalias 'customize-variable 'customize-option)
@@ -821,10 +875,114 @@ are shown; the contents of those subgroups are initially hidden."
 (defun customize-option (symbol)
   "Customize SYMBOL, which must be a user option variable."
   (interactive (custom-variable-prompt))
 (defun customize-option (symbol)
   "Customize SYMBOL, which must be a user option variable."
   (interactive (custom-variable-prompt))
+  ;; If we don't have SYMBOL's real definition loaded,
+  ;; try to load it.
+  (unless (get symbol 'custom-type)
+    (let ((loaddefs-file (locate-library "loaddefs.el" t))
+         file)
+      ;; See if it is autoloaded from some library.
+      (when loaddefs-file
+       (with-temp-buffer
+         (insert-file-contents loaddefs-file)
+         (when (re-search-forward (concat "^(defvar " (symbol-name symbol))
+                                  nil t)
+           (search-backward "\n;;; Generated autoloads from ")
+           (goto-char (match-end 0))
+           (setq file (buffer-substring (point)
+                                        (progn (end-of-line) (point)))))))
+      ;; If it is, load that library.
+      (when file
+       (when (string-match "\\.el\\'" file)
+         (setq file (substring file 0 (match-beginning 0))))
+       (load file))))
+  (unless (get symbol 'custom-type)
+    (error "Variable %s cannot be customized" symbol))
   (custom-buffer-create (list (list symbol 'custom-variable))
                        (format "*Customize Option: %s*"
                                (custom-unlispify-tag-name symbol))))
 
   (custom-buffer-create (list (list symbol 'custom-variable))
                        (format "*Customize Option: %s*"
                                (custom-unlispify-tag-name symbol))))
 
+(defvar customize-changed-options-previous-release "20.2"
+  "Version for `customize-changed-options' to refer back to by default.")
+
+;;;###autoload
+(defun customize-changed-options (since-version)
+  "Customize all user option variables changed in Emacs itself.
+This includes new user option variables and faces, and new
+customization groups, as well as older options and faces whose default
+values have changed since the previous major Emacs release.
+
+With argument SINCE-VERSION (a string), customize all user option
+variables that were added (or their meanings were changed) since that
+version."
+
+  (interactive "sCustomize options changed, since version (default all versions): ")
+  (if (equal since-version "")
+      (setq since-version nil))
+  (unless since-version
+    (setq since-version customize-changed-options-previous-release))
+  (let ((found nil)
+       (versions nil))
+    (mapatoms (lambda (symbol)
+               (and (or (boundp symbol)
+                        ;; For variables not yet loaded.
+                        (get symbol 'standard-value)
+                        ;; For groups the previous test fails, this one
+                        ;; could be used to determine if symbol is a
+                        ;; group. Is there a better way for this?
+                        (get symbol 'group-documentation))
+                    (let ((version (get symbol 'custom-version)))
+                      (and version
+                           (or (null since-version)
+                               (customize-version-lessp since-version version))
+                           (if (member version versions) 
+                               t
+                             ;;; Collect all versions that we use.
+                             (push version versions))))
+                    (setq found
+                          ;; We have to set the right thing here,
+                          ;; depending if we have a group or a
+                          ;; variable. 
+                          (if (get  symbol 'group-documentation)
+                              (cons (list symbol 'custom-group) found)
+                            (cons (list symbol 'custom-variable) found))))))
+    (if (not found)
+       (error "No user option defaults have been changed since Emacs %s"
+              since-version)
+      (let ((flist nil))
+       (while versions
+         (push (copy-sequence 
+                (cdr (assoc (car versions)  custom-versions-load-alist)))
+               flist)
+         (setq versions (cdr versions)))
+       (put 'custom-versions-load-alist 'custom-loads 
+            ;; Get all the files that correspond to element from the
+            ;; VERSIONS list. This could use some simplification.
+            (apply 'nconc flist)))
+      ;; Because we set all the files needed to be loaded as a
+      ;; `custom-loads' property to `custom-versions-load-alist' this
+      ;; call will actually load them.
+      (custom-load-symbol 'custom-versions-load-alist)
+      ;; Clean up
+      (put 'custom-versions-load-alist 'custom-loads nil)
+      (custom-buffer-create (custom-sort-items found t 'first)
+                           "*Customize Changed Options*"))))
+
+(defun customize-version-lessp (version1 version2)
+  ;; 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)))
+    (or (< major1 major2)
+       (and (= major1 major2)
+            (< minor1 minor2)))))
+  
 ;;;###autoload
 (defalias 'customize-variable-other-window 'customize-option-other-window)
 
 ;;;###autoload
 (defalias 'customize-variable-other-window 'customize-option-other-window)
 
@@ -976,7 +1134,7 @@ links: groups have links to subgroups."
   :group 'custom-buffer)
 
 ;;;###autoload
   :group 'custom-buffer)
 
 ;;;###autoload
-(defun custom-buffer-create (options &optional name)
+(defun custom-buffer-create (options &optional name description)
   "Create a buffer containing OPTIONS.
 Optional NAME is the name of the buffer.
 OPTIONS should be an alist of the form ((SYMBOL WIDGET)...), where
   "Create a buffer containing OPTIONS.
 Optional NAME is the name of the buffer.
 OPTIONS should be an alist of the form ((SYMBOL WIDGET)...), where
@@ -984,11 +1142,11 @@ SYMBOL is a customization option, and WIDGET is a widget for editing
 that option."
   (unless name (setq name "*Customization*"))
   (kill-buffer (get-buffer-create name))
 that option."
   (unless name (setq name "*Customization*"))
   (kill-buffer (get-buffer-create name))
-  (switch-to-buffer (get-buffer-create name))
-  (custom-buffer-create-internal options))
+  (pop-to-buffer (get-buffer-create name))
+  (custom-buffer-create-internal options description))
 
 ;;;###autoload
 
 ;;;###autoload
-(defun custom-buffer-create-other-window (options &optional name)
+(defun custom-buffer-create-other-window (options &optional name description)
   "Create a buffer containing OPTIONS.
 Optional NAME is the name of the buffer.
 OPTIONS should be an alist of the form ((SYMBOL WIDGET)...), where
   "Create a buffer containing OPTIONS.
 Optional NAME is the name of the buffer.
 OPTIONS should be an alist of the form ((SYMBOL WIDGET)...), where
@@ -996,9 +1154,14 @@ SYMBOL is a customization option, and WIDGET is a widget for editing
 that option."
   (unless name (setq name "*Customization*"))
   (kill-buffer (get-buffer-create name))
 that option."
   (unless name (setq name "*Customization*"))
   (kill-buffer (get-buffer-create name))
-  (let ((window (selected-window)))
-    (switch-to-buffer-other-window (get-buffer-create name))
-    (custom-buffer-create-internal options)
+  (let ((window (selected-window))
+       (pop-up-windows t)
+       (special-display-buffer-names nil)
+       (special-display-regexps nil)
+       (same-window-buffer-names nil)
+       (same-window-regexps nil))
+    (pop-to-buffer (get-buffer-create name))
+    (custom-buffer-create-internal options description)
     (select-window window)))
 
 (defcustom custom-reset-button-menu nil
     (select-window window)))
 
 (defcustom custom-reset-button-menu nil
@@ -1007,12 +1170,18 @@ This button will have a menu with all three reset operations."
   :type 'boolean
   :group 'custom-buffer)
 
   :type 'boolean
   :group 'custom-buffer)
 
-(defun custom-buffer-create-internal (options)
+(defun custom-buffer-create-internal (options &optional description)
   (message "Creating customization buffer...")
   (custom-mode)
   (message "Creating customization buffer...")
   (custom-mode)
-  (widget-insert "This is a customization buffer.
+  (widget-insert "This is a customization buffer")
+  (if description
+      (widget-insert description))
+  (widget-insert ".
 Square brackets show active fields; type RET or click mouse-1
 Square brackets show active fields; type RET or click mouse-1
-on an active field to invoke its action.  Invoke ")
+on an active field to invoke its action.  Editing an option value
+changes the text in the buffer; invoke the State button and
+choose the Set operation to set the option value.
+Invoke ")
   (widget-create 'info-link 
                 :tag "Help"
                 :help-echo "Read the online help."
   (widget-create 'info-link 
                 :tag "Help"
                 :help-echo "Read the online help."
@@ -1082,7 +1251,7 @@ Reset all values in this buffer to their standard settings."
                (length (length options)))
            (mapcar (lambda (entry)
                        (prog2
                (length (length options)))
            (mapcar (lambda (entry)
                        (prog2
-                           (message "Creating customization items %2d%%..."
+                           (message "Creating customization items ...%2d%%"
                                     (/ (* 100.0 count) length))
                            (widget-create (nth 1 entry)
                                         :tag (custom-unlispify-tag-name
                                     (/ (* 100.0 count) length))
                            (widget-create (nth 1 entry)
                                         :tag (custom-unlispify-tag-name
@@ -1095,6 +1264,7 @@ Reset all values in this buffer to their standard settings."
                      options))))
   (unless (eq (preceding-char) ?\n)
     (widget-insert "\n"))
                      options))))
   (unless (eq (preceding-char) ?\n)
     (widget-insert "\n"))
+  (message "Creating customization items ...%2d%%done" 100)
   (unless (eq custom-buffer-style 'tree)
     (mapcar 'custom-magic-reset custom-options))
   (message "Creating customization setup...")
   (unless (eq custom-buffer-style 'tree)
     (mapcar 'custom-magic-reset custom-options))
   (message "Creating customization setup...")
@@ -1105,25 +1275,19 @@ Reset all values in this buffer to their standard settings."
 ;;; The Tree Browser.
 
 ;;;###autoload
 ;;; The Tree Browser.
 
 ;;;###autoload
-(defun customize-browse (group)
+(defun customize-browse (&optional group)
   "Create a tree browser for the customize hierarchy."
   "Create a tree browser for the customize hierarchy."
-  (interactive (list (let ((completion-ignore-case t))
-                      (completing-read "Customize group: (default emacs) "
-                                       obarray 
-                                       (lambda (symbol)
-                                         (get symbol 'custom-group))
-                                       t))))
-
-  (when (stringp group)
-    (if (string-equal "" group)
-       (setq group 'emacs)
-      (setq group (intern group))))
+  (interactive)
+  (unless group
+    (setq group 'emacs))
   (let ((name "*Customize Browser*"))
     (kill-buffer (get-buffer-create name))
   (let ((name "*Customize Browser*"))
     (kill-buffer (get-buffer-create name))
-    (switch-to-buffer (get-buffer-create name)))
+    (pop-to-buffer (get-buffer-create name)))
   (custom-mode)
   (widget-insert "\
   (custom-mode)
   (widget-insert "\
-Invoke [+] or [?] below to expand items, and [-] to collapse items.\n")
+Square brackets show active fields; type RET or click mouse-1
+on an active field to invoke its action.
+Invoke [+] below to expand a group, and [-] to collapse an expanded group.\n")
   (if custom-browse-only-groups
       (widget-insert "\
 Invoke the [Group] button below to edit that item in another window.\n\n")
   (if custom-browse-only-groups
       (widget-insert "\
 Invoke the [Group] button below to edit that item in another window.\n\n")
@@ -1153,7 +1317,7 @@ item in another window.\n\n"))
   (goto-char (point-min)))
 
 (define-widget 'custom-browse-visibility 'item
   (goto-char (point-min)))
 
 (define-widget 'custom-browse-visibility 'item
-  "Control visibility of of items in the customize tree browser."
+  "Control visibility of items in the customize tree browser."
   :format "%[[%t]%]"
   :action 'custom-browse-visibility-action)
 
   :format "%[[%t]%]"
   :action 'custom-browse-visibility-action)
 
@@ -1355,8 +1519,8 @@ The list should be sorted most significant first.")
   "If non-nil, show textual description of the state.
 If `long', show a full-line description, not just one word."
   :type '(choice (const :tag "no" nil)
   "If non-nil, show textual description of the state.
 If `long', show a full-line description, not just one word."
   :type '(choice (const :tag "no" nil)
-                (const short)
-                (const long))
+                (const long)
+                (other :tag "short" short))
   :group 'custom-buffer)
 
 (defcustom custom-magic-show-hidden '(option face)
   :group 'custom-buffer)
 
 (defcustom custom-magic-show-hidden '(option face)
@@ -1399,7 +1563,7 @@ and `face'."
         (text (or (and (eq category 'group)
                        (nth 4 entry))
                   (nth 3 entry)))
         (text (or (and (eq category 'group)
                        (nth 4 entry))
                   (nth 3 entry)))
-        (lisp (eq (widget-get parent :custom-form) 'lisp))
+        (form (widget-get parent :custom-form))
         children)
     (while (string-match "\\`\\(.*\\)%c\\(.*\\)\\'" text)
       (setq text (concat (match-string 1 text) 
         children)
     (while (string-match "\\`\\(.*\\)%c\\(.*\\)\\'" text)
       (setq text (concat (match-string 1 text) 
@@ -1428,8 +1592,10 @@ and `face'."
        (if (eq custom-magic-show 'long)
            (insert text)
          (insert (symbol-name state)))
        (if (eq custom-magic-show 'long)
            (insert text)
          (insert (symbol-name state)))
-       (when lisp 
-         (insert " (lisp)"))
+       (cond ((eq form 'lisp)
+              (insert " (lisp)"))
+             ((eq form 'mismatch)
+              (insert " (mismatch)")))
        (put-text-property start (point) 'face 'custom-state-face))
       (insert "\n"))
     (when (and (eq category 'group)
        (put-text-property start (point) 'face 'custom-state-face))
       (insert "\n"))
     (when (and (eq category 'group)
@@ -1450,7 +1616,7 @@ and `face'."
             :button-suffix ""
             :help-echo "Change the state."
             :format (if hidden "%t" "%[%t%]")
             :button-suffix ""
             :help-echo "Change the state."
             :format (if hidden "%t" "%[%t%]")
-            :tag (if lisp 
+            :tag (if (memq form '(lisp mismatch))
                      (concat "(" magic ")")
                    (concat "[" magic "]")))
            children)
                      (concat "(" magic ")")
                    (concat "[" magic "]")))
            children)
@@ -1495,7 +1661,6 @@ and `face'."
   :value-delete 'widget-children-value-delete
   :value-get 'widget-value-value-get
   :validate 'widget-children-validate
   :value-delete 'widget-children-value-delete
   :value-get 'widget-value-value-get
   :validate 'widget-children-validate
-  :button-face 'custom-button-face
   :match (lambda (widget value) (symbolp value)))
 
 (defun custom-convert-widget (widget)
   :match (lambda (widget value) (symbolp value)))
 
 (defun custom-convert-widget (widget)
@@ -1575,6 +1740,8 @@ and `face'."
                   (require load)
                 (error nil)))
              ;; Don't reload a file already loaded.
                   (require load)
                 (error nil)))
              ;; Don't reload a file already loaded.
+             ((and (boundp 'preloaded-file-list)
+                   (member load preloaded-file-list)))
              ((assoc load load-history))
              ((assoc (locate-library load) load-history))
              (t
              ((assoc load load-history))
              ((assoc (locate-library load) load-history))
              (t
@@ -1700,6 +1867,13 @@ If INITIAL-STRING is non-nil, use that rather than \"Parent groups:\"."
   "Face used for pushable variable tags."
   :group 'custom-faces)
 
   "Face used for pushable variable tags."
   :group 'custom-faces)
 
+(defcustom custom-variable-default-form 'edit
+  "Default form of displaying variable values."
+  :type '(choice (const edit)
+                (const lisp))
+  :group 'custom-buffer
+  :version "20.3")
+
 (define-widget 'custom-variable 'custom
   "Customize variable."
   :format "%v"
 (define-widget 'custom-variable 'custom
   "Customize variable."
   :format "%v"
@@ -1708,7 +1882,7 @@ If INITIAL-STRING is non-nil, use that rather than \"Parent groups:\"."
   :custom-category 'option
   :custom-state nil
   :custom-menu 'custom-variable-menu-create
   :custom-category 'option
   :custom-state nil
   :custom-menu 'custom-variable-menu-create
-  :custom-form 'edit
+  :custom-form nil ; defaults to value of `custom-variable-default-form'
   :value-create 'custom-variable-value-create
   :action 'custom-variable-action
   :custom-set 'custom-variable-set
   :value-create 'custom-variable-value-create
   :action 'custom-variable-action
   :custom-set 'custom-variable-set
@@ -1736,6 +1910,8 @@ Otherwise, look up symbol in `custom-guess-type-alist'."
 (defun custom-variable-value-create (widget)
   "Here is where you edit the variables value."
   (custom-load-widget widget)
 (defun custom-variable-value-create (widget)
   "Here is where you edit the variables value."
   (custom-load-widget widget)
+  (unless (widget-get widget :custom-form)
+    (widget-put widget :custom-form custom-variable-default-form))
   (let* ((buttons (widget-get widget :buttons))
         (children (widget-get widget :children))
         (form (widget-get widget :custom-form))
   (let* ((buttons (widget-get widget :buttons))
         (children (widget-get widget :children))
         (form (widget-get widget :custom-form))
@@ -1760,7 +1936,7 @@ Otherwise, look up symbol in `custom-guess-type-alist'."
     (when (eq state 'unknown)
       (unless (widget-apply conv :match value)
        ;; (widget-apply (widget-convert type) :match value)
     (when (eq state 'unknown)
       (unless (widget-apply conv :match value)
        ;; (widget-apply (widget-convert type) :match value)
-       (setq form 'lisp)))
+       (setq form 'mismatch)))
     ;; Now we can create the child widget.
     (cond ((eq custom-buffer-style 'tree)
           (insert prefix (if last " `--- " " |--- "))
     ;; Now we can create the child widget.
     (cond ((eq custom-buffer-style 'tree)
           (insert prefix (if last " `--- " " |--- "))
@@ -1784,7 +1960,7 @@ Otherwise, look up symbol in `custom-guess-type-alist'."
                  :action 'custom-toggle-parent
                  nil)
                 buttons))
                  :action 'custom-toggle-parent
                  nil)
                 buttons))
-         ((eq form 'lisp)
+         ((memq form '(lisp mismatch))
           ;; In lisp mode edit the saved value when possible.
           (let* ((value (cond ((get symbol 'saved-value)
                                (car (get symbol 'saved-value)))
           ;; In lisp mode edit the saved value when possible.
           (let* ((value (cond ((get symbol 'saved-value)
                                (car (get symbol 'saved-value)))
@@ -1815,7 +1991,7 @@ Otherwise, look up symbol in `custom-guess-type-alist'."
           (let* ((format (widget-get type :format))
                  tag-format value-format)
             (unless (string-match ":" format)
           (let* ((format (widget-get type :format))
                  tag-format value-format)
             (unless (string-match ":" format)
-              (error "Bad format."))
+              (error "Bad format"))
             (setq tag-format (substring format 0 (match-end 0)))
             (setq value-format (substring format (match-end 0)))
             (push (widget-create-child-and-convert
             (setq tag-format (substring format 0 (match-end 0)))
             (setq value-format (substring format (match-end 0)))
             (push (widget-create-child-and-convert
@@ -1927,10 +2103,10 @@ Otherwise, look up symbol in `custom-guess-type-alist'."
     ("---" ignore ignore)
     ("Don't show as Lisp expression" custom-variable-edit 
      (lambda (widget)
     ("---" ignore ignore)
     ("Don't show as Lisp expression" custom-variable-edit 
      (lambda (widget)
-       (not (eq (widget-get widget :custom-form) 'edit))))
-    ("Show as Lisp expression" custom-variable-edit-lisp
+       (eq (widget-get widget :custom-form) 'lisp)))
+    ("Show initial Lisp expression" custom-variable-edit-lisp
      (lambda (widget)
      (lambda (widget)
-       (not (eq (widget-get widget :custom-form) 'lisp)))))
+       (eq (widget-get widget :custom-form) 'edit))))
   "Alist of actions for the `custom-variable' widget.
 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
   "Alist of actions for the `custom-variable' widget.
 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
@@ -1977,11 +2153,11 @@ Optional EVENT is the location for the menu."
         (set (or (get symbol 'custom-set) 'set-default))
          val)
     (cond ((eq state 'hidden)
         (set (or (get symbol 'custom-set) 'set-default))
          val)
     (cond ((eq state 'hidden)
-          (error "Cannot set hidden variable."))
+          (error "Cannot set hidden variable"))
          ((setq val (widget-apply child :validate))
           (goto-char (widget-get val :from))
           (error "%s" (widget-get val :error)))
          ((setq val (widget-apply child :validate))
           (goto-char (widget-get val :from))
           (error "%s" (widget-get val :error)))
-         ((eq form 'lisp)
+         ((memq form '(lisp mismatch))
           (funcall set symbol (eval (setq val (widget-value child))))
           (put symbol 'customized-value (list val)))
          (t
           (funcall set symbol (eval (setq val (widget-value child))))
           (put symbol 'customized-value (list val)))
          (t
@@ -1991,7 +2167,7 @@ Optional EVENT is the location for the menu."
     (custom-redraw-magic widget)))
 
 (defun custom-variable-save (widget)
     (custom-redraw-magic widget)))
 
 (defun custom-variable-save (widget)
-  "Set the default value for the variable being edited by WIDGET."
+  "Set and save the value for the variable being edited by WIDGET."
   (let* ((form (widget-get widget :custom-form))
         (state (widget-get widget :custom-state))
         (child (car (widget-get widget :children)))
   (let* ((form (widget-get widget :custom-form))
         (state (widget-get widget :custom-state))
         (child (car (widget-get widget :children)))
@@ -1999,11 +2175,11 @@ Optional EVENT is the location for the menu."
         (set (or (get symbol 'custom-set) 'set-default))
         val)
     (cond ((eq state 'hidden)
         (set (or (get symbol 'custom-set) 'set-default))
         val)
     (cond ((eq state 'hidden)
-          (error "Cannot set hidden variable."))
+          (error "Cannot set hidden variable"))
          ((setq val (widget-apply child :validate))
           (goto-char (widget-get val :from))
           (error "%s" (widget-get val :error)))
          ((setq val (widget-apply child :validate))
           (goto-char (widget-get val :from))
           (error "%s" (widget-get val :error)))
-         ((eq form 'lisp)
+         ((memq form '(lisp mismatch))
           (put symbol 'saved-value (list (widget-value child)))
           (funcall set symbol (eval (widget-value child))))
          (t
           (put symbol 'saved-value (list (widget-value child)))
           (funcall set symbol (eval (widget-value child))))
          (t
@@ -2084,10 +2260,10 @@ The X11 Window System.")
                                           :sibling-args (:help-echo "\
 OS/2 Presentation Manager.")
                                           pm)
                                           :sibling-args (:help-echo "\
 OS/2 Presentation Manager.")
                                           pm)
-                                   (const :format "Win32 "
+                                   (const :format "W32 "
                                           :sibling-args (:help-echo "\
                                           :sibling-args (:help-echo "\
-Windows NT/95/97.")
-                                          win32)
+Windows NT/9X.")
+                                          w32)
                                    (const :format "DOS "
                                           :sibling-args (:help-echo "\
 Plain MS-DOS.")
                                    (const :format "DOS "
                                           :sibling-args (:help-echo "\
 Plain MS-DOS.")
@@ -2136,6 +2312,14 @@ Match frames with dark backgrounds.")
   "Face used for face tags."
   :group 'custom-faces)
 
   "Face used for face tags."
   :group 'custom-faces)
 
+(defcustom custom-face-default-form 'selected
+  "Default form of displaying face definition."
+  :type '(choice (const all)
+                (const selected)
+                (const lisp))
+  :group 'custom-buffer
+  :version "20.3")
+
 (define-widget 'custom-face 'custom
   "Customize face."
   :sample-face 'custom-face-tag-face
 (define-widget 'custom-face 'custom
   "Customize face."
   :sample-face 'custom-face-tag-face
@@ -2145,7 +2329,7 @@ Match frames with dark backgrounds.")
   :value-create 'custom-face-value-create
   :action 'custom-face-action
   :custom-category 'face
   :value-create 'custom-face-value-create
   :action 'custom-face-action
   :custom-category 'face
-  :custom-form 'selected
+  :custom-form nil ; defaults to value of `custom-face-default-form'
   :custom-set 'custom-face-set
   :custom-save 'custom-face-save
   :custom-reset-current 'custom-redraw
   :custom-set 'custom-face-set
   :custom-save 'custom-face-save
   :custom-reset-current 'custom-redraw
@@ -2249,6 +2433,8 @@ Match frames with dark backgrounds.")
           (unless (eq state 'hidden)
             (message "Creating face editor...")
             (custom-load-widget widget)
           (unless (eq state 'hidden)
             (message "Creating face editor...")
             (custom-load-widget widget)
+            (unless (widget-get widget :custom-form)
+                (widget-put widget :custom-form custom-face-default-form))
             (let* ((symbol (widget-value widget))
                    (spec (or (get symbol 'saved-face)
                              (get symbol 'face-defface-spec)
             (let* ((symbol (widget-value widget))
                    (spec (or (get symbol 'saved-face)
                              (get symbol 'face-defface-spec)
@@ -2257,7 +2443,12 @@ Match frames with dark backgrounds.")
                                             symbol (selected-frame))))))
                    (form (widget-get widget :custom-form))
                    (indent (widget-get widget :indent))
                                             symbol (selected-frame))))))
                    (form (widget-get widget :custom-form))
                    (indent (widget-get widget :indent))
-                   (edit (widget-create-child-and-convert
+                   edit)
+              ;; If the user has changed this face in some other way,
+              ;; edit it as the user has specified it.
+              (if (not (face-spec-match-p symbol spec (selected-frame)))
+                  (setq spec (list (list t (face-attr-construct symbol (selected-frame))))))
+              (setq edit (widget-create-child-and-convert
                           widget
                           (cond ((and (eq form 'selected)
                                       (widget-apply custom-face-selected 
                           widget
                           (cond ((and (eq form 'selected)
                                       (widget-apply custom-face-selected 
@@ -2271,14 +2462,14 @@ Match frames with dark backgrounds.")
                                 (t 
                                  (when indent (insert-char ?\  indent))
                                  'sexp))
                                 (t 
                                  (when indent (insert-char ?\  indent))
                                  'sexp))
-                          :value spec)))
+                          :value spec))
               (custom-face-state-set widget)
               (widget-put widget :children (list edit)))
             (message "Creating face editor...done"))))))
 
 (defvar custom-face-menu 
               (custom-face-state-set widget)
               (widget-put widget :children (list edit)))
             (message "Creating face editor...done"))))))
 
 (defvar custom-face-menu 
-  '(("Set" custom-face-set)
-    ("Save" custom-face-save)
+  '(("Set for Current Session" custom-face-set)
+    ("Save for Future Sessions" custom-face-save-command)
     ("Reset to Saved" custom-face-reset-saved
      (lambda (widget)
        (get (widget-value widget) 'saved-face)))
     ("Reset to Saved" custom-face-reset-saved
      (lambda (widget)
        (get (widget-value widget) 'saved-face)))
@@ -2357,14 +2548,20 @@ Optional EVENT is the location for the menu."
     (custom-face-state-set widget)
     (custom-redraw-magic widget)))
 
     (custom-face-state-set widget)
     (custom-redraw-magic widget)))
 
+(defun custom-face-save-command (widget)
+  "Save in `.emacs' the face attributes in WIDGET."
+  (custom-face-save widget)
+  (custom-save-all))
+
 (defun custom-face-save (widget)
 (defun custom-face-save (widget)
-  "Make the face attributes in WIDGET default."
+  "Prepare for saving WIDGET's face attributes, but don't write `.emacs'."
   (let* ((symbol (widget-value widget))
         (child (car (widget-get widget :children)))
         (value (widget-value child)))
     (face-spec-set symbol value)
     (put symbol 'saved-face value)
     (put symbol 'customized-face nil)
   (let* ((symbol (widget-value widget))
         (child (car (widget-get widget :children)))
         (value (widget-value child)))
     (face-spec-set symbol value)
     (put symbol 'saved-face value)
     (put symbol 'customized-face nil)
+    (custom-save-all)
     (custom-face-state-set widget)
     (custom-redraw-magic widget)))
 
     (custom-face-state-set widget)
     (custom-redraw-magic widget)))
 
@@ -2452,6 +2649,13 @@ Optional EVENT is the location for the menu."
 
 (define-widget 'hook 'list
   "A emacs lisp hook"
 
 (define-widget 'hook 'list
   "A emacs lisp hook"
+  :value-to-internal (lambda (widget value)
+                      (if (and value (symbolp value))
+                          (list value)
+                        value))
+  :match (lambda (widget value)
+          (or (symbolp value)
+              (widget-group-match widget value)))
   :convert-widget 'custom-hook-convert-widget
   :tag "Hook")
 
   :convert-widget 'custom-hook-convert-widget
   :tag "Hook")
 
@@ -2542,24 +2746,37 @@ and so forth.  The remaining group tags are shown with
        (insert "--------")))
   (widget-default-create widget))
 
        (insert "--------")))
   (widget-default-create widget))
 
+(defun custom-group-members (symbol groups-only)
+  "Return SYMBOL's custom group members.
+If GROUPS-ONLY non-nil, return only those members that are groups."
+  (if (not groups-only)
+      (get symbol 'custom-group)
+    (let (members)
+      (dolist (entry (get symbol 'custom-group))
+       (when (eq (nth 1 entry) 'custom-group)
+         (push entry members)))
+      (nreverse members))))
+
 (defun custom-group-value-create (widget)
   "Insert a customize group for WIDGET in the current buffer."
 (defun custom-group-value-create (widget)
   "Insert a customize group for WIDGET in the current buffer."
-  (let ((state (widget-get widget :custom-state))
-       (level (widget-get widget :custom-level))
-       (indent (widget-get widget :indent))
-       (prefix (widget-get widget :custom-prefix))
-       (buttons (widget-get widget :buttons))
-       (tag (widget-get widget :tag))
-       (symbol (widget-value widget)))
+  (let* ((state (widget-get widget :custom-state))
+        (level (widget-get widget :custom-level))
+        ;; (indent (widget-get widget :indent))
+        (prefix (widget-get widget :custom-prefix))
+        (buttons (widget-get widget :buttons))
+        (tag (widget-get widget :tag))
+        (symbol (widget-value widget))
+        (members (custom-group-members symbol
+                                       (and (eq custom-buffer-style 'tree)
+                                            custom-browse-only-groups))))
     (cond ((and (eq custom-buffer-style 'tree)
                (eq state 'hidden)
     (cond ((and (eq custom-buffer-style 'tree)
                (eq state 'hidden)
-               (or (get symbol 'custom-group)
-                   (custom-unloaded-widget-p widget)))
+               (or members (custom-unloaded-widget-p widget)))
           (custom-browse-insert-prefix prefix)
           (push (widget-create-child-and-convert
                  widget 'custom-browse-visibility 
                  ;; :tag-glyph "plus"
           (custom-browse-insert-prefix prefix)
           (push (widget-create-child-and-convert
                  widget 'custom-browse-visibility 
                  ;; :tag-glyph "plus"
-                 :tag (if (custom-unloaded-widget-p widget) "?" "+"))
+                 :tag "+")
                 buttons)
           (insert "-- ")
           ;; (widget-glyph-insert nil "-- " "horizontal")
                 buttons)
           (insert "-- ")
           ;; (widget-glyph-insert nil "-- " "horizontal")
@@ -2569,7 +2786,7 @@ and so forth.  The remaining group tags are shown with
           (insert " " tag "\n")
           (widget-put widget :buttons buttons))
          ((and (eq custom-buffer-style 'tree)
           (insert " " tag "\n")
           (widget-put widget :buttons buttons))
          ((and (eq custom-buffer-style 'tree)
-               (zerop (length (get symbol 'custom-group))))
+               (zerop (length members)))
           (custom-browse-insert-prefix prefix)
           (insert "[ ]-- ")
           ;; (widget-glyph-insert nil "[ ]" "empty")
           (custom-browse-insert-prefix prefix)
           (insert "[ ]-- ")
           ;; (widget-glyph-insert nil "[ ]" "empty")
@@ -2582,7 +2799,7 @@ and so forth.  The remaining group tags are shown with
          ((eq custom-buffer-style 'tree)
           (custom-browse-insert-prefix prefix)
           (custom-load-widget widget)
          ((eq custom-buffer-style 'tree)
           (custom-browse-insert-prefix prefix)
           (custom-load-widget widget)
-          (if (zerop (length (get symbol 'custom-group)))
+          (if (zerop (length members))
               (progn 
                 (custom-browse-insert-prefix prefix)
                 (insert "[ ]-- ")
               (progn 
                 (custom-browse-insert-prefix prefix)
                 (insert "[ ]-- ")
@@ -2606,7 +2823,7 @@ and so forth.  The remaining group tags are shown with
             (insert " " tag "\n")
             (widget-put widget :buttons buttons)
             (message "Creating group...")
             (insert " " tag "\n")
             (widget-put widget :buttons buttons)
             (message "Creating group...")
-            (let* ((members (custom-sort-items (get symbol 'custom-group)
+            (let* ((members (custom-sort-items members
                              custom-browse-sort-alphabetically
                              custom-browse-order-groups))
                    (prefixes (widget-get widget :custom-prefixes))
                              custom-browse-sort-alphabetically
                              custom-browse-order-groups))
                    (prefixes (widget-get widget :custom-prefixes))
@@ -2619,18 +2836,16 @@ and so forth.  The remaining group tags are shown with
               (while members
                 (setq entry (car members)
                       members (cdr members))
               (while members
                 (setq entry (car members)
                       members (cdr members))
-                (when (or (not custom-browse-only-groups)
-                          (eq (nth 1 entry) 'custom-group))
-                  (push (widget-create-child-and-convert
-                         widget (nth 1 entry)
-                         :group widget
-                         :tag (custom-unlispify-tag-name (nth 0 entry))
-                         :custom-prefixes custom-prefix-list
-                         :custom-level (1+ level)
-                         :custom-last (null members)
-                         :value (nth 0 entry)
-                         :custom-prefix prefix)
-                        children)))
+                (push (widget-create-child-and-convert
+                       widget (nth 1 entry)
+                       :group widget
+                       :tag (custom-unlispify-tag-name (nth 0 entry))
+                       :custom-prefixes custom-prefix-list
+                       :custom-level (1+ level)
+                       :custom-last (null members)
+                       :value (nth 0 entry)
+                       :custom-prefix prefix)
+                      children))
               (widget-put widget :children (reverse children)))
             (message "Creating group...done")))
          ;; Nested style.
               (widget-put widget :children (reverse children)))
             (message "Creating group...done")))
          ;; Nested style.
@@ -2652,7 +2867,7 @@ and so forth.  The remaining group tags are shown with
                      symbol)
                     buttons)
             (push (widget-create-child-and-convert 
                      symbol)
                     buttons)
             (push (widget-create-child-and-convert 
-                   widget 'group-visibility
+                   widget 'custom-group-visibility
                    :help-echo "Show members of this group."
                    :action 'custom-toggle-parent
                    (not (eq state 'hidden)))
                    :help-echo "Show members of this group."
                    :action 'custom-toggle-parent
                    (not (eq state 'hidden)))
@@ -2725,7 +2940,7 @@ and so forth.  The remaining group tags are shown with
           ;; Members.
           (message "Creating group...")
           (custom-load-widget widget)
           ;; Members.
           (message "Creating group...")
           (custom-load-widget widget)
-          (let* ((members (custom-sort-items (get symbol 'custom-group)
+          (let* ((members (custom-sort-items members
                                              custom-buffer-sort-alphabetically
                                              custom-buffer-order-groups))
                  (prefixes (widget-get widget :custom-prefixes))
                                              custom-buffer-sort-alphabetically
                                              custom-buffer-order-groups))
                  (prefixes (widget-get widget :custom-prefixes))
@@ -2764,10 +2979,10 @@ Creating group members... %2d%%"
           (insert "/\n")))))
 
 (defvar custom-group-menu 
           (insert "/\n")))))
 
 (defvar custom-group-menu 
-  '(("Set" custom-group-set
+  '(("Set for Current Session" custom-group-set
      (lambda (widget)
        (eq (widget-get widget :custom-state) 'modified)))
      (lambda (widget)
        (eq (widget-get widget :custom-state) 'modified)))
-    ("Save" custom-group-save
+    ("Save for Future Sessions" custom-group-save
      (lambda (widget)
        (memq (widget-get widget :custom-state) '(modified set))))
     ("Reset to Current" custom-group-reset-current
      (lambda (widget)
        (memq (widget-get widget :custom-state) '(modified set))))
     ("Reset to Current" custom-group-reset-current
@@ -2863,19 +3078,27 @@ Optional EVENT is the location for the menu."
 
 ;;; The `custom-save-all' Function.
 ;;;###autoload
 
 ;;; The `custom-save-all' Function.
 ;;;###autoload
-(defcustom custom-file (if (featurep 'xemacs)
-                          "~/.xemacs-custom"
-                        "~/.emacs")
+(defcustom custom-file nil
   "File used for storing customization information.
   "File used for storing customization information.
-If you change this from the default \"~/.emacs\" you need to
-explicitly load that file for the settings to take effect."
-  :type 'file
+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."
+  :type '(choice (const :tag "Your Emacs init file" nil) file)
   :group 'customize)
 
   :group 'customize)
 
+(defun custom-file ()
+  "Return the file name for saving customizations."
+  (setq custom-file
+       (or custom-file
+           user-init-file
+           (read-file-name "File for customizations: "
+                           "~/" nil nil ".emacs"))))
+
 (defun custom-save-delete (symbol)
 (defun custom-save-delete (symbol)
-  "Delete the call to SYMBOL form `custom-file'.
+  "Delete the call to SYMBOL from `custom-file'.
 Leave point at the location of the call, or after the last expression."
 Leave point at the location of the call, or after the last expression."
-  (set-buffer (find-file-noselect custom-file))
+  (let ((default-major-mode))
+    (set-buffer (find-file-noselect (custom-file))))
   (goto-char (point-min))
   (catch 'found
     (while t
   (goto-char (point-min))
   (catch 'found
     (while t
@@ -2978,54 +3201,18 @@ Leave point at the location of the call, or after the last expression."
 ;;;###autoload
 (defun custom-save-all ()
   "Save all customizations in `custom-file'."
 ;;;###autoload
 (defun custom-save-all ()
   "Save all customizations in `custom-file'."
-  (custom-save-variables)
-  (custom-save-faces)
-  (save-excursion
-    (set-buffer (find-file-noselect custom-file))
-    (save-buffer)))
+  (let ((inhibit-read-only t))
+    (custom-save-variables)
+    (custom-save-faces)
+    (save-excursion
+      (let ((default-major-mode nil))
+       (set-buffer (find-file-noselect (custom-file))))
+      (save-buffer))))
 
 ;;; The Customize Menu.
 
 ;;; Menu support
 
 
 ;;; The Customize Menu.
 
 ;;; Menu support
 
-(unless (string-match "XEmacs" emacs-version)
-  (defconst custom-help-menu
-    '("Customize"
-      ["Update menu" Custom-menu-update t]
-      ["Browse" (customize-browse 'emacs) t]
-      ["Group..." customize-group t]
-      ["Option..." customize-option t]
-      ["Face..." customize-face t]
-      ["Saved..." customize-saved t]
-      ["Set..." customize-customized t]
-      "--"
-      ["Apropos..." customize-apropos t]
-      ["Group apropos..." customize-apropos-groups t]
-      ["Option apropos..." customize-apropos-options t]
-      ["Face apropos..." customize-apropos-faces t])
-    ;; This menu should be identical to the one defined in `menu-bar.el'. 
-    "Customize menu")
-
-  (defun custom-menu-reset ()
-    "Reset customize menu."
-    (remove-hook 'custom-define-hook 'custom-menu-reset)
-    (define-key global-map [menu-bar help-menu customize-menu]
-      (cons (car custom-help-menu)
-           (easy-menu-create-keymaps (car custom-help-menu)
-                                     (cdr custom-help-menu)))))
-
-  (defun Custom-menu-update (event)
-    "Update customize menu."
-    (interactive "e")
-    (add-hook 'custom-define-hook 'custom-menu-reset)
-    (let* ((emacs (widget-apply '(custom-group) :custom-menu 'emacs))
-          (menu `(,(car custom-help-menu)
-                  ,emacs
-                  ,@(cdr (cdr custom-help-menu)))))
-      (let ((map (easy-menu-create-keymaps (car menu) (cdr menu))))
-       (define-key global-map [menu-bar help-menu customize-menu]
-         (cons (car menu) map))))))
-
 (defcustom custom-menu-nesting 2
   "Maximum nesting in custom menus."
   :type 'integer
 (defcustom custom-menu-nesting 2
   "Maximum nesting in custom menus."
   :type 'integer
@@ -3126,6 +3313,8 @@ The format is suitable for use with `easy-menu-define'."
   (define-key custom-mode-map "\177" 'scroll-down)
   (define-key custom-mode-map "q" 'bury-buffer)
   (define-key custom-mode-map "u" 'Custom-goto-parent)
   (define-key custom-mode-map "\177" 'scroll-down)
   (define-key custom-mode-map "q" 'bury-buffer)
   (define-key custom-mode-map "u" 'Custom-goto-parent)
+  (define-key custom-mode-map "n" 'widget-forward)
+  (define-key custom-mode-map "p" 'widget-backward)
   (define-key custom-mode-map [mouse-1] 'Custom-move-and-invoke))
 
 (defun Custom-move-and-invoke (event)
   (define-key custom-mode-map [mouse-1] 'Custom-move-and-invoke))
 
 (defun Custom-move-and-invoke (event)
@@ -3148,7 +3337,7 @@ The format is suitable for use with `easy-menu-define'."
     ["Reset to Current" Custom-reset-current t]
     ["Reset to Saved" Custom-reset-saved t]
     ["Reset to Standard Settings" Custom-reset-standard t]
     ["Reset to Current" Custom-reset-current t]
     ["Reset to Saved" Custom-reset-saved t]
     ["Reset to Standard Settings" Custom-reset-standard t]
-    ["Info" (Info-goto-node "(custom)The Customization Buffer") t]))
+    ["Info" (Info-goto-node "(emacs)Easy Customization") t]))
 
 (defun Custom-goto-parent ()
   "Go to the parent group listed at the top of this buffer.
 
 (defun Custom-goto-parent ()
   "Go to the parent group listed at the top of this buffer.
@@ -3177,6 +3366,9 @@ The following commands are available:
 
 Move to next button or editable field.     \\[widget-forward]
 Move to previous button or editable field. \\[widget-backward]
 
 Move to next button or editable field.     \\[widget-forward]
 Move to previous button or editable field. \\[widget-backward]
+\\<widget-field-keymap>\
+Complete content of editable text field.   \\[widget-complete]
+\\<custom-mode-map>\
 Invoke button under the mouse pointer.     \\[Custom-move-and-invoke]
 Invoke button under point.                \\[widget-button-press]
 Set all modifications.                    \\[Custom-set]
 Invoke button under the mouse pointer.     \\[Custom-move-and-invoke]
 Invoke button under point.                \\[widget-button-press]
 Set all modifications.                    \\[Custom-set]
@@ -3195,6 +3387,8 @@ if that value is non-nil."
   (make-local-variable 'custom-options)
   (make-local-variable 'widget-documentation-face)
   (setq widget-documentation-face 'custom-documentation-face)
   (make-local-variable 'custom-options)
   (make-local-variable 'widget-documentation-face)
   (setq widget-documentation-face 'custom-documentation-face)
+  (make-local-variable 'widget-button-face)
+  (setq widget-button-face 'custom-button-face)
   (make-local-hook 'widget-edit-functions)
   (add-hook 'widget-edit-functions 'custom-state-buffer-message nil t)
   (run-hooks 'custom-mode-hook))
   (make-local-hook 'widget-edit-functions)
   (add-hook 'widget-edit-functions 'custom-state-buffer-message nil t)
   (run-hooks 'custom-mode-hook))