(make-coding-system): Create -with-esc variant coding system.
[bpt/emacs.git] / lisp / cus-edit.el
index cbd736b..b6c60a4 100644 (file)
@@ -4,7 +4,7 @@
 ;;
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Keywords: help, faces
-;; Version: 1.9944
+;; Version: 1.9954
 ;; X-URL: http://www.dina.kvl.dk/~abraham/custom/
 
 ;; This file is part of GNU Emacs.
   :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 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-"
@@ -408,7 +412,7 @@ Return a list suitable for use in `interactive'."
                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)))))
@@ -607,6 +611,8 @@ If `last', order groups after non-groups."
                 (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.
@@ -653,7 +659,8 @@ groups after non-groups, if nil do not order groups at all."
   (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))
@@ -680,27 +687,33 @@ when the action is chosen.")
   "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))
-    (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))
-    (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
@@ -773,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))))
 
+;;;###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.
@@ -789,38 +822,51 @@ are shown; the contents of those subgroups are initially hidden."
                       (completing-read "Customize group: (default emacs) "
                                        obarray 
                                        (lambda (symbol)
-                                         (get symbol 'custom-group))
+                                         (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)
-       (switch-to-buffer name)
+       (pop-to-buffer name)
       (custom-buffer-create (list (list group 'custom-group))
                            name
                            (concat " for group "
                                    (custom-unlispify-tag-name group))))))
 
 ;;;###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)
@@ -829,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))
+  ;; 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))))
 
+(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)
 
@@ -992,7 +1142,7 @@ 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))
-  (switch-to-buffer (get-buffer-create name))
+  (pop-to-buffer (get-buffer-create name))
   (custom-buffer-create-internal options description))
 
 ;;;###autoload
@@ -1004,8 +1154,13 @@ 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))
-  (let ((window (selected-window)))
-    (switch-to-buffer-other-window (get-buffer-create name))
+  (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)))
 
@@ -1096,7 +1251,7 @@ Reset all values in this buffer to their standard settings."
                (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
@@ -1109,6 +1264,7 @@ Reset all values in this buffer to their standard settings."
                      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...")
@@ -1119,48 +1275,49 @@ Reset all values in this buffer to their standard settings."
 ;;; The Tree Browser.
 
 ;;;###autoload
-(defun customize-browse ()
+(defun customize-browse (&optional group)
   "Create a tree browser for the customize hierarchy."
   (interactive)
-  (let ((group 'emacs))
-    (let ((name "*Customize Browser*"))
-      (kill-buffer (get-buffer-create name))
-      (switch-to-buffer (get-buffer-create name)))
-    (custom-mode)
-    (widget-insert "\
+  (unless group
+    (setq group 'emacs))
+  (let ((name "*Customize Browser*"))
+    (kill-buffer (get-buffer-create name))
+    (pop-to-buffer (get-buffer-create name)))
+  (custom-mode)
+  (widget-insert "\
 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 "\
+  (if custom-browse-only-groups
+      (widget-insert "\
 Invoke the [Group] button below to edit that item in another window.\n\n")
-      (widget-insert "Invoke the ") 
-      (widget-create 'item 
-                    :format "%t"
-                    :tag "[Group]"
-                    :tag-glyph "folder")
-      (widget-insert ", ")
-      (widget-create 'item 
-                    :format "%t"
-                    :tag "[Face]"
-                    :tag-glyph "face")
-      (widget-insert ", and ")
-      (widget-create 'item 
-                    :format "%t"
-                    :tag "[Option]"
-                    :tag-glyph "option")
-      (widget-insert " buttons below to edit that
+    (widget-insert "Invoke the ") 
+    (widget-create 'item 
+                  :format "%t"
+                  :tag "[Group]"
+                  :tag-glyph "folder")
+    (widget-insert ", ")
+    (widget-create 'item 
+                  :format "%t"
+                  :tag "[Face]"
+                  :tag-glyph "face")
+    (widget-insert ", and ")
+    (widget-create 'item 
+                  :format "%t"
+                  :tag "[Option]"
+                  :tag-glyph "option")
+    (widget-insert " buttons below to edit that
 item in another window.\n\n"))
-    (let ((custom-buffer-style 'tree))
-      (widget-create 'custom-group 
-                    :custom-last t
-                    :custom-state 'unknown
-                    :tag (custom-unlispify-tag-name group)
-                    :value group))
-    (goto-char (point-min))))
+  (let ((custom-buffer-style 'tree))
+    (widget-create 'custom-group 
+                  :custom-last t
+                  :custom-state 'unknown
+                  :tag (custom-unlispify-tag-name group)
+                  :value group))
+  (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)
 
@@ -1362,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)
-                (const short)
-                (const long))
+                (const long)
+                (other :tag "short" short))
   :group 'custom-buffer)
 
 (defcustom custom-magic-show-hidden '(option face)
@@ -1406,7 +1563,7 @@ and `face'."
         (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) 
@@ -1435,8 +1592,10 @@ and `face'."
        (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)
@@ -1457,7 +1616,7 @@ and `face'."
             :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)
@@ -1581,7 +1740,8 @@ and `face'."
                   (require load)
                 (error nil)))
              ;; Don't reload a file already loaded.
-             ((member load preloaded-file-list))
+             ((and (boundp 'preloaded-file-list)
+                   (member load preloaded-file-list)))
              ((assoc load load-history))
              ((assoc (locate-library load) load-history))
              (t
@@ -1707,6 +1867,13 @@ If INITIAL-STRING is non-nil, use that rather than \"Parent groups:\"."
   "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"
@@ -1715,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-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
@@ -1743,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)
+  (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))
@@ -1767,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)
-       (setq form 'lisp)))
+       (setq form 'mismatch)))
     ;; Now we can create the child widget.
     (cond ((eq custom-buffer-style 'tree)
           (insert prefix (if last " `--- " " |--- "))
@@ -1791,7 +1960,7 @@ Otherwise, look up symbol in `custom-guess-type-alist'."
                  :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)))
@@ -1822,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)
-              (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
@@ -1934,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)
-       (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)
-       (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
@@ -1984,11 +2153,11 @@ Optional EVENT is the location for the menu."
         (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)))
-         ((eq form 'lisp)
+         ((memq form '(lisp mismatch))
           (funcall set symbol (eval (setq val (widget-value child))))
           (put symbol 'customized-value (list val)))
          (t
@@ -1998,7 +2167,7 @@ Optional EVENT is the location for the menu."
     (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)))
@@ -2006,11 +2175,11 @@ Optional EVENT is the location for the menu."
         (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)))
-         ((eq form 'lisp)
+         ((memq form '(lisp mismatch))
           (put symbol 'saved-value (list (widget-value child)))
           (funcall set symbol (eval (widget-value child))))
          (t
@@ -2091,10 +2260,10 @@ The X11 Window System.")
                                           :sibling-args (:help-echo "\
 OS/2 Presentation Manager.")
                                           pm)
-                                   (const :format "Win32 "
+                                   (const :format "W32 "
                                           :sibling-args (:help-echo "\
-Windows NT/95/97.")
-                                          win32)
+Windows NT/9X.")
+                                          w32)
                                    (const :format "DOS "
                                           :sibling-args (:help-echo "\
 Plain MS-DOS.")
@@ -2143,6 +2312,14 @@ Match frames with dark backgrounds.")
   "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
@@ -2152,7 +2329,7 @@ Match frames with dark backgrounds.")
   :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
@@ -2256,6 +2433,8 @@ Match frames with dark backgrounds.")
           (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)
@@ -2264,7 +2443,12 @@ Match frames with dark backgrounds.")
                                             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 
@@ -2278,14 +2462,14 @@ Match frames with dark backgrounds.")
                                 (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 
   '(("Set for Current Session" custom-face-set)
-    ("Save for Future Sessions" custom-face-save)
+    ("Save for Future Sessions" custom-face-save-command)
     ("Reset to Saved" custom-face-reset-saved
      (lambda (widget)
        (get (widget-value widget) 'saved-face)))
@@ -2364,14 +2548,20 @@ Optional EVENT is the location for the menu."
     (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)
-  "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)
+    (custom-save-all)
     (custom-face-state-set widget)
     (custom-redraw-magic widget)))
 
@@ -2459,6 +2649,13 @@ Optional EVENT is the location for the menu."
 
 (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")
 
@@ -2549,19 +2746,32 @@ and so forth.  The remaining group tags are shown with
        (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."
-  (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)
-               (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 
@@ -2576,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)
-               (zerop (length (get symbol 'custom-group))))
+               (zerop (length members)))
           (custom-browse-insert-prefix prefix)
           (insert "[ ]-- ")
           ;; (widget-glyph-insert nil "[ ]" "empty")
@@ -2589,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)
-          (if (zerop (length (get symbol 'custom-group)))
+          (if (zerop (length members))
               (progn 
                 (custom-browse-insert-prefix prefix)
                 (insert "[ ]-- ")
@@ -2613,7 +2823,7 @@ and so forth.  The remaining group tags are shown with
             (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))
@@ -2626,18 +2836,16 @@ and so forth.  The remaining group tags are shown with
               (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.
@@ -2659,7 +2867,7 @@ and so forth.  The remaining group tags are shown with
                      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)))
@@ -2732,7 +2940,7 @@ and so forth.  The remaining group tags are shown with
           ;; 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))
@@ -2870,19 +3078,27 @@ Optional EVENT is the location for the menu."
 
 ;;; 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.
-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)
 
+(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)
-  "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."
-  (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
@@ -2985,11 +3201,13 @@ Leave point at the location of the call, or after the last expression."
 ;;;###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.
 
@@ -3119,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]
-    ["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.
@@ -3148,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]
+\\<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]