*** empty log message ***
[bpt/emacs.git] / lisp / cus-edit.el
index da0ee18..862cbf7 100644 (file)
@@ -1,6 +1,6 @@
 ;;; cus-edit.el --- Tools for customizing Emacs and Lisp packages.
 ;;
-;; Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1997, 1999, 2000, 2001 Free Software Foundation, Inc.
 ;;
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Keywords: help, faces
@@ -1297,14 +1297,13 @@ Un-customize all values in this buffer.  They get their standard settings."
                 :tag "Finish"
                 :help-echo
                 (lambda (&rest ignore)
-                  (concat (cond
-                           ((eq custom-buffer-done-function
-                                'custom-bury-buffer)
-                            "Bury")
-                           ((eq custom-buffer-done-function 'kill-buffer)
-                            "Kill")
-                           (t "Finish with"))              
-                          " the buffer."))
+                  (cond
+                   ((eq custom-buffer-done-function
+                        'custom-bury-buffer)
+                    "Bury this buffer")
+                   ((eq custom-buffer-done-function 'kill-buffer)
+                    "Kill this buffer")
+                   (t "Finish with this buffer")))
                 :action #'Custom-buffer-done)
   (widget-insert "\n\n")
   (message "Creating customization items...")
@@ -1322,18 +1321,18 @@ Un-customize all values in this buffer.  They get their standard settings."
          (let ((count 0)
                (length (length options)))
            (mapcar (lambda (entry)
-                       (prog2
-                           (message "Creating customization items ...%2d%%"
-                                    (/ (* 100.0 count) length))
-                           (widget-create (nth 1 entry)
+                     (prog2
+                         (message "Creating customization items ...%2d%%"
+                                  (/ (* 100.0 count) length))
+                         (widget-create (nth 1 entry)
                                         :tag (custom-unlispify-tag-name
                                               (nth 0 entry))
                                         :value (nth 0 entry))
-                         (setq count (1+ count))
-                         (unless (eq (preceding-char) ?\n)
-                           (widget-insert "\n"))
-                         (widget-insert "\n")))
-                     options))))
+                       (setq count (1+ count))
+                       (unless (eq (preceding-char) ?\n)
+                         (widget-insert "\n"))
+                       (widget-insert "\n")))
+                   options))))
   (unless (eq (preceding-char) ?\n)
     (widget-insert "\n"))
   (message "Creating customization items ...%2d%%done" 100)
@@ -2379,7 +2378,7 @@ Optional EVENT is the location for the menu."
           (error "Cannot set hidden variable"))
          ((setq val (widget-apply child :validate))
           (goto-char (widget-get val :from))
-          (error "%s" (widget-get val :error)))
+          (error "Saving %s: %s" symbol (widget-get val :error)))
          ((memq form '(lisp mismatch))
           (when (equal comment "")
             (setq comment nil)
@@ -2594,6 +2593,57 @@ Match frames with dark backgrounds.")
 (defconst custom-face-selected (widget-convert 'custom-face-selected)
   "Converted version of the `custom-face-selected' widget.")
 
+(defun custom-filter-face-spec (spec filter-index default-filter)
+  "Return a canonicalized version of SPEC using.
+FILTER-INDEX is the index in the entry for each attribute in
+`custom-face-attributes' at which the appropriate filter function can be
+found, and DEFAULT-FILTER is the filter to apply for attributes that
+don't specify one."
+  (mapcar (lambda (entry)
+           ;; Filter a single face-spec entry
+           (let ((tests (car entry))
+                 (unfiltered-attrs
+                  ;; Handle both old- and new-style attribute syntax
+                  (if (listp (car (cdr entry)))
+                      (car (cdr entry))
+                    (cdr entry)))
+                 (filtered-attrs nil))
+             ;; Filter each face attribute
+             (while unfiltered-attrs
+               (let* ((attr (pop unfiltered-attrs))
+                      (pre-filtered-value (pop unfiltered-attrs))
+                      (filter
+                       (or (nth filter-index (assq attr custom-face-attributes))
+                           default-filter))
+                      (filtered-value
+                       (if filter
+                           (funcall filter pre-filtered-value)
+                         pre-filtered-value)))
+                 (push filtered-value filtered-attrs)
+                 (push attr filtered-attrs)))
+             ;;
+             (list tests filtered-attrs)))
+         spec))
+
+(defun custom-pre-filter-face-spec (spec)
+  "Return SPEC changed as necessary for editing by the face customization widget.
+SPEC must be a full face spec."
+  (custom-filter-face-spec
+   spec 2
+   (lambda (value)
+     (cond ((eq value 'unspecified) nil)
+          ((eq value nil) 'off)
+          (t value)))))
+
+(defun custom-post-filter-face-spec (spec)
+  "Return the customized SPEC in a form suitable for setting the face."
+  (custom-filter-face-spec
+   spec 3
+   (lambda (value)
+     (cond ((eq value nil) 'unspecified)
+          ((eq value 'off) nil)
+          (t value)))))
+
 (defun custom-face-value-create (widget)
   "Create a list of the display specifications for WIDGET."
   (let ((buttons (widget-get widget :buttons))
@@ -2616,10 +2666,12 @@ Match frames with dark backgrounds.")
          (t
           ;; Create tag.
           (insert tag)
+          (widget-specify-sample widget begin (point))
           (if (eq custom-buffer-style 'face)
               (insert " ")
-            (widget-specify-sample widget begin (point))
-            (insert ": "))
+            (if (string-match "face\\'" tag)
+                (insert ":")
+              (insert " face: ")))
           ;; Sample.
           (push (widget-create-child-and-convert widget 'item
                                                  :format "(%{%t%})"
@@ -2680,6 +2732,7 @@ Match frames with dark backgrounds.")
               ;; 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 spec (custom-pre-filter-face-spec spec))
               (setq edit (widget-create-child-and-convert
                           widget
                           (cond ((and (eq form 'selected)
@@ -2793,7 +2846,7 @@ Optional EVENT is the location for the menu."
   "Make the face attributes in WIDGET take effect."
   (let* ((symbol (widget-value widget))
         (child (car (widget-get widget :children)))
-        (value (widget-value child))
+        (value (custom-post-filter-face-spec (widget-value child)))
         (comment-widget (widget-get widget :comment-widget))
         (comment (widget-value comment-widget)))
     (when (equal comment "")
@@ -2801,7 +2854,11 @@ Optional EVENT is the location for the menu."
       ;; Make the comment invisible by hand if it's empty
       (custom-comment-hide comment-widget))
     (put symbol 'customized-face value)
-    (face-spec-set symbol value)
+    (if (face-spec-choose value)
+       (face-spec-set symbol value)
+      ;; face-set-spec ignores empty attribute lists, so just give it
+      ;; something harmless instead.
+      (face-spec-set symbol '((t :foreground unspecified))))
     (put symbol 'customized-face-comment comment)
     (put symbol 'face-comment comment)
     (custom-face-state-set widget)
@@ -2816,14 +2873,18 @@ Optional EVENT is the location for the menu."
   "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))
+        (value (custom-post-filter-face-spec (widget-value child)))
         (comment-widget (widget-get widget :comment-widget))
         (comment (widget-value comment-widget)))
     (when (equal comment "")
       (setq comment nil)
       ;; Make the comment invisible by hand if it's empty
       (custom-comment-hide comment-widget))
-    (face-spec-set symbol value)
+    (if (face-spec-choose value)
+       (face-spec-set symbol value)
+      ;; face-set-spec ignores empty attribute lists, so just give it
+      ;; something harmless instead.
+      (face-spec-set symbol '((t :foreground unspecified))))
     (put symbol 'saved-face value)
     (put symbol 'customized-face nil)
     (put symbol 'face-comment comment)
@@ -2883,7 +2944,7 @@ restoring it to the state of a face that has never been customized."
   :convert-widget 'widget-value-convert-widget
   :button-prefix 'widget-push-button-prefix
   :button-suffix 'widget-push-button-suffix
-  :format "%t: %[select face%] %v"
+  :format "%{%t%}: %[select face%] %v"
   :tag "Face"
   :value 'default
   :value-create 'widget-face-value-create
@@ -3388,9 +3449,19 @@ to the new custom file.  This will preserve your existing customizations."
   "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"))))
+           (let ((user-init-file user-init-file)
+                 (default-init-file
+                   (if (eq system-type 'ms-dos) "~/_emacs" "~/.emacs")))
+             (when (null user-init-file)
+               (if (or (file-exists-p default-init-file)
+                       (and (eq system-type 'windows-nt)
+                            (file-exists-p "~/_emacs")))
+                   ;; Started with -q, i.e. the file containing
+                   ;; Custom settings hasn't been read.  Saving
+                   ;; settings there would overwrite other settings.
+                   (error "Saving settings from \"emacs -q\" would overwrite existing customizations"))
+               (setq user-init-file default-init-file))
+             user-init-file))))
 
 (defun custom-save-delete (symbol)
   "Visit `custom-file' and delete all calls to SYMBOL from it.
@@ -3419,7 +3490,17 @@ or (if there were none) at the end of the buffer."
              (setq first (point)))))))
     (if first
        (goto-char first)
-      (goto-char (point-max)))))
+      ;; Move in front of local variables, otherwise long Custom
+      ;; entries would make them ineffective.
+      (let ((pos (point-max))
+           (case-fold-search t))
+       (save-excursion
+         (goto-char (point-max))
+         (search-backward "\n\^L" (max (- (point-max) 3000) (point-min))
+                          'move)
+         (when (search-forward "Local Variables:" nil t)
+           (setq pos (line-beginning-position))))
+       (goto-char pos)))))
 
 (defun custom-save-variables ()
   "Save all customized variables in `custom-file'."
@@ -3438,7 +3519,7 @@ or (if there were none) at the end of the buffer."
        (princ "\n"))
       (princ "(custom-set-variables
   ;; custom-set-variables was added by Custom -- don't edit or cut/paste it!
-  ;; Your init file must only contain one such instance.\n")
+  ;; Your init file should contain only one such instance.\n")
       (mapcar
        (lambda (symbol)
         (let ((value (get symbol 'saved-value))
@@ -3502,7 +3583,7 @@ or (if there were none) at the end of the buffer."
        (princ "\n"))
       (princ "(custom-set-faces
   ;; custom-set-faces was added by Custom -- don't edit or cut/paste it!
-  ;; Your init file must only contain one such instance.\n")
+  ;; Your init file should contain only one such instance.\n")
       (mapcar
        (lambda (symbol)
         (let ((value (get symbol 'saved-face))
@@ -3651,7 +3732,7 @@ The format is suitable for use with `easy-menu-define'."
     (setq name "Customize"))
   `(,name
     :filter (lambda (&rest junk)
-             (cdr (custom-menu-create ',symbol)))))
+             (custom-menu-create ',symbol))))
 
 ;;; The Custom Mode.
 
@@ -3659,6 +3740,8 @@ The format is suitable for use with `easy-menu-define'."
   "Keymap for `custom-mode'.")
 
 (unless custom-mode-map
+  ;; This keymap should be dense, but a dense keymap would prevent inheriting
+  ;; "\r" bindings from the parent map.
   (setq custom-mode-map (make-sparse-keymap))
   (set-keymap-parent custom-mode-map widget-keymap)
   (suppress-keymap custom-mode-map)
@@ -3753,7 +3836,6 @@ if that value is non-nil."
     (set (make-local-variable 'widget-push-button-suffix) "")
     (set (make-local-variable 'widget-link-prefix) "")
     (set (make-local-variable 'widget-link-suffix) ""))
-  (make-local-hook 'widget-edit-functions)
   (add-hook 'widget-edit-functions 'custom-state-buffer-message nil t)
   (run-hooks 'custom-mode-hook))