]> code.delx.au - gnu-emacs/blobdiff - lisp/faces.el
(face-spec-set-match-display): Revert the change from
[gnu-emacs] / lisp / faces.el
index 914f2c177af1311adcaed2bdd357c8f2fc9ae80f..a8c9eee55173e742091f01830bcba60a6e31a479 100644 (file)
@@ -25,7 +25,9 @@
 ;;; Code:
 
 (eval-when-compile
-  (require 'cl))
+  (require 'cl)
+  ;; Warning suppression -- can't require x-win in batch:
+  (autoload 'xw-defined-colors "x-win"))
 
 (require 'cus-face)
 
@@ -50,12 +52,14 @@ example, if `:slant' appears before `:height', font selection first
 tries to find a font with a suitable slant, even if this results in
 a font height that isn't optimal."
   :tag "Font selection order."
+  :type '(list symbol symbol symbol symbol)
   :group 'font-selection
   :set #'(lambda (symbol value)
           (set-default symbol value)
           (internal-set-font-selection-order value)))
 
-;; This is defined originally in {w32,x}faces.c.
+
+;; This is defined originally in xfaces.c.
 (defcustom face-font-family-alternatives
   '(("courier" "fixed")
     ("helv" "helvetica" "arial" "fixed"))
@@ -64,12 +68,29 @@ Each element has the the form (FAMILY ALTERNATIVE1 ALTERNATIVE2 ...).
 If fonts of family FAMILY can't be loaded, try ALTERNATIVE1, then
 ALTERNATIVE2 etc."
   :tag "Alternative font families to try."
+  :type '(repeat (repeat string))
   :group 'font-selection
   :set #'(lambda (symbol value)
           (set-default symbol value)
           (internal-set-alternative-font-family-alist value)))
 
 
+;; This is defined originally in xfaces.c.
+(defcustom face-font-registry-alternatives
+  '(("muletibetan-2" "muletibetan-0"))
+  "*Alist of alternative font registry names.
+Each element has the the form (REGISTRY ALTERNATIVE1 ALTERNATIVE2 ...).
+If fonts of registry REGISTRY can't be loaded, try ALTERNATIVE1, then
+ALTERNATIVE2 etc."
+  :tag "Alternative font registries to try."
+  :type '(repeat (repeat string))
+  :version "21.1"
+  :group 'font-selection
+  :set #'(lambda (symbol value)
+          (set-default symbol value)
+          (internal-set-alternative-font-registry-alist value)))
+
+
 \f
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; Creation, copying.
@@ -263,16 +284,16 @@ If FRAME is omitted or nil, use the selected frame."
     (:stipple
      (".attributeStipple" . "Face.AttributeStipple")
      (".attributeBackgroundPixmap" . "Face.AttributeBackgroundPixmap"))
-    (:font (".attributeFont" . "Face.AttributeFont"))
     (:bold (".attributeBold" . "Face.AttributeBold"))
     (:italic (".attributeItalic" . "Face.AttributeItalic"))
-    (:font (".attributeFont" . "Face.AttributeFont")))
+    (:font (".attributeFont" . "Face.AttributeFont"))
+    (:inherit (".attributeInherit" . "Face.AttributeInherit")))
   "*List of X resources and classes for face attributes.
 Each element has the form (ATTRIBUTE ENTRY1 ENTRY2...) where ATTRIBUTE is
 the name of a face attribute, and each ENTRY is a cons of the form
 (RESOURCE . CLASS) with RESOURCE being the resource and CLASS being the
 X resource class for the attribute."
-  :type 'sexp
+  :type '(repeat (cons symbol (repeat (cons string string))))
   :group 'faces)
 
 
@@ -296,7 +317,7 @@ specifies an invalid attribute."
 
 (defun set-face-attributes-from-resources (face frame)
   "Set attributes of FACE from X resources for FRAME."
-  (when (memq (framep frame) '(x w32))
+  (when (memq (framep frame) '(x w32 mac))
     (dolist (definition face-x-resources)
       (let ((attribute (car definition)))
        (dolist (entry (cdr definition))
@@ -394,8 +415,6 @@ Use `face-attribute' for finer control."
     (memq italic '(italic oblique))))
     
 
-
-
 \f
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; Face documentation.
@@ -450,8 +469,10 @@ It must be one of the symbols `ultra-condensed', `extra-condensed',
 
 `:height'
 
-VALUE must be an integer specifying the height of the font to use in
-1/10 pt.
+VALUE must be either an integer specifying the height of the font to use
+in 1/10 pt, a floating point number specifying the amount by which to
+scale any underlying face, or a function, which is called with the old
+height (from the underlying face), and should return the new height.
 
 `:weight'
 
@@ -535,20 +556,20 @@ will be used.
 
 For compatibility with Emacs 20, keywords `:bold' and `:italic' can
 be used to specify that a bold or italic font should be used.  VALUE
-must be t or nil in that case.  A value of `unspecified' is not allowed."
-  (setq args (purecopy args))
-  (cond ((null frame)
-        ;; Change face on all frames.
-        (dolist (frame (frame-list))
-          (apply #'set-face-attribute face frame args))
-        ;; Record that as a default for new frames.
-        (apply #'set-face-attribute face t args))
-       (t
-        (while args
-          (internal-set-lisp-face-attribute face (car args)
-                                            (purecopy (cadr args))
-                                            frame)
-          (setq args (cdr (cdr args)))))))
+must be t or nil in that case.  A value of `unspecified' is not allowed.
+
+`:inherit'
+
+VALUE is the name of a face from which to inherit attributes, or a list
+of face names.  Attributes from inherited faces are merged into the face
+like an underlying face would be, with higher priority than underlying faces."
+  (let ((where (if (null frame) 0 frame)))
+    (setq args (purecopy args))
+    (while args
+      (internal-set-lisp-face-attribute face (car args)
+                                       (purecopy (cadr args))
+                                       where)
+      (setq args (cdr (cdr args))))))
 
 
 (defun make-face-bold (face &optional frame noerror)
@@ -730,7 +751,7 @@ Value is a symbol naming a known face."
        (def (thing-at-point 'symbol))
        face)
     (cond ((assoc def face-list)
-          (setq prompt (concat prompt "(default " def "): ")))
+          (setq prompt (concat prompt " (default " def "): ")))
          (t (setq def nil)
             (setq prompt (concat prompt ": "))))
     (while (equal "" (setq face (completing-read
@@ -771,13 +792,21 @@ an integer value."
            ((:height)
             'integerp)
            (:stipple
-            (and (memq window-system '(x w32))
+            (and (memq window-system '(x w32 mac))
                  (mapcar #'list
-                         (apply #'nconc (mapcar #'directory-files
-                                                x-bitmap-file-path)))))
+                         (apply #'nconc
+                                (mapcar (lambda (dir)
+                                          (and (file-readable-p dir)
+                                               (file-directory-p dir)
+                                               (directory-files dir)))
+                                        x-bitmap-file-path)))))
+           (:inherit
+            (cons '("none" . nil)
+                  (mapcar #'(lambda (c) (cons (symbol-name c) c))
+                          (face-list))))
            (t
             (error "Internal error"))))
-    (if (listp valid)
+    (if (and (listp valid) (not (memq attribute '(:inherit))))
        (nconc (list (cons "unspecified" 'unspecified)) valid)
       valid)))
               
@@ -796,7 +825,8 @@ an integer value."
     (:inverse-video . "inverse-video display")
     (:foreground . "foreground color")
     (:background . "background color")
-    (:stipple . "background stipple"))
+    (:stipple . "background stipple")
+    (:inherit . "inheritance"))
   "An alist of descriptive names for face attributes.
 Each element has the form (ATTRIBUTE-NAME . DESCRIPTION) where
 ATTRIBUTE-NAME is a face attribute name (a keyword symbol), and
@@ -810,21 +840,22 @@ DESCRIPTION is a descriptive name for ATTRIBUTE-NAME.")
 
 (defun face-read-string (face default name &optional completion-alist)
   "Interactively read a face attribute string value.
-FACE is the face whose attribute is read.  DEFAULT is the default
-value to return if no new value is entered.  NAME is a descriptive
-name of the attribute for prompting.  COMPLETION-ALIST is an alist
-of valid values, if non-nil.
+FACE is the face whose attribute is read.  If non-nil, DEFAULT is the
+default string to return if no new value is entered.  NAME is a
+descriptive name of the attribute for prompting.  COMPLETION-ALIST is an
+alist of valid values, if non-nil.
 
-Entering nothing accepts the default value DEFAULT.
+Entering nothing accepts the default string DEFAULT.
 Value is the new attribute value."
+  ;; Capitalize NAME (we don't use `capitalize' because that capitalizes
+  ;; each word in a string separately).
+  (setq name (concat (upcase (substring name 0 1)) (substring name 1)))
   (let* ((completion-ignore-case t)
         (value (completing-read
                 (if default
-                    (format "Set face %s %s (default %s): "
-                            face name (downcase (if (symbolp default)
-                                                    (symbol-name default)
-                                                  default)))
-                  (format "Set face %s %s: " face name))
+                    (format "%s for face `%s' (default %s): "
+                            name face default)
+                  (format "%s for face `%s': " name face))
                 completion-alist)))
     (if (equal value "") default value)))
 
@@ -836,17 +867,15 @@ value to return if no new value is entered.  NAME is a descriptive
 name of the attribute for prompting.  Value is the new attribute value."
   (let ((new-value
         (face-read-string face
-                          (if (memq default
-                                    '(unspecified
-                                      "unspecified-fg"
-                                      "unspecified-bg"))
-                              default
-                            (int-to-string default))
+                          (format "%s" default)
                           name
                           (list (cons "unspecified" 'unspecified)))))
-    (if (memq new-value '(unspecified "unspecified-fg" "unspecified-bg"))
-       new-value
-      (string-to-int new-value))))
+    (cond ((equal new-value "unspecified")
+          'unspecified)
+         ((member new-value '("unspecified-fg" "unspecified-bg"))
+          new-value)
+         (t
+          (string-to-int new-value)))))
 
 
 (defun read-face-attribute (face attribute &optional frame)
@@ -867,20 +896,27 @@ of a global face.  Value is the new attribute value."
                   (vectorp old-value)))
       (setq old-value (prin1-to-string old-value)))
     (cond ((listp valid)
-          (setq new-value
-                (face-read-string face old-value attribute-name valid))
-          ;; Terminal frames can support colors that don't appear
-          ;; explicitly in VALID, using color approximation code
-          ;; in tty-colors.el.
-          (if (and (memq attribute '(:foreground :background))
-                   (not (memq window-system '(x w32 mac)))
-                   (not (memq new-value
-                              '(unspecified
-                                "unspecified-fg"
-                                "unspecified-bg"))))
-              (setq new-value (car (tty-color-desc new-value frame))))
-          (unless (eq new-value 'unspecified)
-            (setq new-value (cdr (assoc new-value valid)))))
+          (let ((default
+                  (or (car (rassoc old-value valid))
+                      (format "%s" old-value))))
+            (setq new-value
+                  (face-read-string face default attribute-name valid))
+            (if (equal new-value default)
+                ;; Nothing changed, so don't bother with all the stuff
+                ;; below.  In particular, this avoids a non-tty color
+                ;; from being canonicalized for a tty when the user
+                ;; just uses the default.
+                (setq new-value old-value)
+              ;; Terminal frames can support colors that don't appear
+              ;; explicitly in VALID, using color approximation code
+              ;; in tty-colors.el.
+              (if (and (memq attribute '(:foreground :background))
+                       (not (memq window-system '(x w32 mac)))
+                       (not (member new-value
+                                    '("unspecified"
+                                      "unspecified-fg" "unspecified-bg"))))
+                  (setq new-value (car (tty-color-desc new-value frame))))
+              (setq new-value (cdr (assoc new-value valid))))))
          ((eq valid 'integerp)
           (setq new-value (face-read-integer face old-value attribute-name)))
          (t (error "Internal error")))
@@ -899,7 +935,7 @@ of a global face.  Value is the new attribute value."
   "Read the name of a font for FACE on FRAME.
 If optional argument FRAME Is nil or omitted, use the selected frame."
   (let ((completion-ignore-case t))
-    (completing-read (format "Set font attributes of face %s from font: " face)
+    (completing-read (format "Set font attributes of face `%s' from font: " face)
                     (mapcar 'list (x-list-fonts "*" nil frame)))))
 
 
@@ -919,7 +955,7 @@ Value is a property list of attribute names and new values."
 If optional argument FRAME is nil or omitted, modify the face used
 for newly created frame, i.e. the global face."
   (interactive)
-  (let ((face (read-face-name "Modify face ")))
+  (let ((face (read-face-name "Modify face")))
     (apply #'set-face-attribute face frame
           (read-all-face-attributes face frame))))
 
@@ -931,13 +967,13 @@ FRAME nil or unspecified means read attribute value of global face.
 Value is a list (FACE NEW-VALUE) where FACE is the face read
 (a symbol), and NEW-VALUE is value read."
   (cond ((eq attribute :font)
-        (let* ((prompt (format "Set font-related attributes of face "))
+        (let* ((prompt "Set font-related attributes of face")
                (face (read-face-name prompt))
                (font (read-face-font face frame)))
           (list face font)))
        (t
         (let* ((attribute-name (face-descriptive-attribute-name attribute))
-               (prompt (format "Set %s of face " attribute-name))
+               (prompt (format "Set %s of face" attribute-name))
                (face (read-face-name prompt))
                (new-value (read-face-attribute face attribute frame)))
           (list face new-value)))))
@@ -1043,7 +1079,8 @@ If FRAME is omitted or nil, use the selected frame."
                  (:box . "Box")
                  (:inverse-video . "Inverse")
                  (:stipple . "Stipple")
-                 (:font . "Font or fontset")))
+                 (:font . "Font or fontset")
+                 (:inherit . "Inherit")))
        (max-width (apply #'max (mapcar #'(lambda (x) (length (cdr x)))
                                        attrs))))
     (with-output-to-temp-buffer "*Help*"
@@ -1109,6 +1146,12 @@ If FRAME is nil, the current FRAME is used."
            options (cdr conjunct)
            match (cond ((eq req 'type)
                         (or (memq window-system options)
+                            ;; FIXME: This should be revisited to use
+                            ;; display-graphic-p, provided that the
+                            ;; color selection depends on the number
+                            ;; of supported colors, and all defface's
+                            ;; are changed to look at number of colors
+                            ;; instead of (type graphic) etc.
                             (and (null window-system)
                                  (memq 'tty options))
                             (and (memq 'motif options)
@@ -1129,53 +1172,59 @@ If FRAME is nil, the current FRAME is used."
 
 
 (defun face-spec-choose (spec &optional frame)
-  "Choose the proper attributes for FRAME, out of SPEC."
+  "Choose the proper attributes for FRAME, out of SPEC.
+If SPEC is nil, return nil."
   (unless frame
     (setq frame (selected-frame)))
   (let ((tail spec)
        result)
     (while tail
-      (let* ((entry (car tail))
-            (display (nth 0 entry))
-            (attrs (nth 1 entry)))
-       (setq tail (cdr tail))
+      (let* ((entry (pop tail))
+            (display (car entry))
+            (attrs (cdr entry)))
        (when (face-spec-set-match-display display frame)
-         (setq result attrs tail nil))))
+         (setq result (if (listp (car attrs))
+                          ;; Old-style entry, the attribute list is the
+                          ;; first element.
+                          (car attrs)
+                        attrs)
+               tail nil))))
     result))
 
 
 (defun face-spec-reset-face (face &optional frame)
   "Reset all attributes of FACE on FRAME to unspecified."
-  (let ((attrs face-attribute-name-alist)
-       params)
+  (let ((attrs face-attribute-name-alist))
     (while attrs
       (let ((attr-and-name (car attrs)))
-       (setq params (cons (car attr-and-name) (cons 'unspecified params))))
-      (setq attrs (cdr attrs)))
-    (apply #'set-face-attribute face frame params)))
+       (set-face-attribute face frame (car attr-and-name) 'unspecified))
+      (setq attrs (cdr attrs)))))
 
 
 (defun face-spec-set (face spec &optional frame)
   "Set FACE's attributes according to the first matching entry in SPEC.
 FRAME is the frame whose frame-local face is set.  FRAME nil means
-do it on all frames.  See `defface' for information about SPEC."
-  (let ((attrs (face-spec-choose spec frame))
-       params)
+do it on all frames.  See `defface' for information about SPEC.
+If SPEC is nil, do nothing."
+  (let ((attrs (face-spec-choose spec frame)))
+    (when attrs
+      (face-spec-reset-face face frame))
     (while attrs
       (let ((attribute (car attrs))
            (value (car (cdr attrs))))
        ;; Support some old-style attribute names and values.
        (case attribute
          (:bold (setq attribute :weight value (if value 'bold 'normal)))
-         (:italic (setq attribute :slant value (if value 'italic 'normal))))
-       (setq params (cons attribute (cons value params))))
-      (setq attrs (cdr (cdr attrs))))
-    (face-spec-reset-face face frame)
-    (apply #'set-face-attribute face frame params)))
+         (:italic (setq attribute :slant value (if value 'italic 'normal)))
+         (t (unless (assq attribute face-x-resources)
+              (setq attribute nil))))
+       (when attribute
+         (set-face-attribute face frame attribute value)))
+      (setq attrs (cdr (cdr attrs))))))
 
 
 (defun face-attr-match-p (face attrs &optional frame)
-  "Value is non-nil if attributes of FACE match values in plist ATTRS.
+  "Return t if attributes of FACE match values in plist ATTRS.
 Optional parameter FRAME is the frame whose definition of FACE
 is used.  If nil or omitted, use the selected frame."
   (unless frame
@@ -1184,18 +1233,29 @@ is used.  If nil or omitted, use the selected frame."
        (match t))
     (while (and match (not (null list)))
       (let* ((attr (car (car list)))
-            (specified-value (plist-get attrs attr))
+            (specified-value
+             (if (plist-member attrs attr)
+                 (plist-get attrs attr)
+               'unspecified))
             (value-now (face-attribute face attr frame)))
-       (when specified-value
-         (setq match (equal specified-value value-now)))
+       (setq match (equal specified-value value-now))
        (setq list (cdr list))))
     match))
 
-
 (defun face-spec-match-p (face spec &optional frame)
   "Return t if FACE, on FRAME, matches what SPEC says it should look like."
   (face-attr-match-p face (face-spec-choose spec frame) frame))
 
+(defsubst face-default-spec (face)
+  "Return the default face-spec for FACE, ignoring any user customization.
+If there is no default for FACE, return nil."
+  (get face 'face-defface-spec))
+
+(defsubst face-user-default-spec (face)
+  "Return the user's customized face-spec for FACE, or the default if none.
+If there is neither a user setting or a default for FACE, return nil."
+  (or (get face 'saved-face)
+      (face-default-spec face)))
 
 \f
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -1208,7 +1268,7 @@ is used.  If nil or omitted, use the selected frame."
 The argument FRAME specifies which frame to try.
 The value may be different for frames on different display types.
 If FRAME doesn't support colors, the value is nil."
-  (if (memq (framep (or frame (selected-frame))) '(x w32))
+  (if (memq (framep (or frame (selected-frame))) '(x w32 mac))
       (xw-defined-colors frame)
     (mapcar 'car (tty-color-alist frame))))
 (defalias 'x-defined-colors 'defined-colors)
@@ -1218,9 +1278,9 @@ If FRAME doesn't support colors, the value is nil."
 If FRAME is omitted or nil, use the selected frame.
 If COLOR is the symbol `unspecified' or one of the strings
 \"unspecified-fg\" or \"unspecified-bg\", the value is nil."
-  (if (memq color '(unspecified "unspecified-bg" "unspecified-fg"))
+  (if (member color '(unspecified "unspecified-bg" "unspecified-fg"))
       nil
-    (if (memq (framep (or frame (selected-frame))) '(x w32))
+    (if (member (framep (or frame (selected-frame))) '(x w32 mac))
        (xw-color-defined-p color frame)
       (numberp (tty-color-translate color frame)))))
 (defalias 'x-color-defined-p 'color-defined-p)
@@ -1228,15 +1288,14 @@ If COLOR is the symbol `unspecified' or one of the strings
 (defun color-values (color &optional frame)
   "Return a description of the color named COLOR on frame FRAME.
 The value is a list of integer RGB values--\(RED GREEN BLUE\).
-These values appear to range from 0 to 65280 or 65535, depending
-on the system; white is \(65280 65280 65280\) or \(65535 65535 65535\).
+These values appear to range from 0 65535; white is \(65535 65535 65535\).
 If FRAME is omitted or nil, use the selected frame.
 If FRAME cannot display COLOR, the value is nil.
 If COLOR is the symbol `unspecified' or one of the strings
 \"unspecified-fg\" or \"unspecified-bg\", the value is nil."
-  (if (memq color '(unspecified "unspecified-fg" "unspecified-bg"))
+  (if (member color '(unspecified "unspecified-fg" "unspecified-bg"))
       nil
-    (if (memq (framep (or frame (selected-frame))) '(x w32))
+    (if (memq (framep (or frame (selected-frame))) '(x w32 mac))
        (xw-color-values color frame)
       (tty-color-values color frame))))
 (defalias 'x-color-values 'color-values)
@@ -1246,7 +1305,7 @@ If COLOR is the symbol `unspecified' or one of the strings
 The optional argument DISPLAY specifies which display to ask about.
 DISPLAY should be either a frame or a display name (a string).
 If omitted or nil, that stands for the selected frame's display."
-  (if (memq (framep-on-display display) '(x w32))
+  (if (memq (framep-on-display display) '(x w32 mac))
       (xw-display-color-p display)
     (tty-display-color-p display)))
 (defalias 'x-display-color-p 'display-color-p)
@@ -1269,11 +1328,12 @@ If omitted or nil, that stands for the selected frame's display."
   "*The brightness of the background.
 Set this to the symbol `dark' if your background color is dark, `light' if
 your background is light, or nil (default) if you want Emacs to
-examine the brightness for you."
+examine the brightness for you.  Don't set this variable with `setq';
+this won't have the expected effect."
   :group 'faces
   :set #'(lambda (var value)
-          (set var value)
-          (mapcar 'frame-set-background-mode (frame-list)))
+          (set-default var value)
+          (mapc 'frame-set-background-mode (frame-list)))
   :initialize 'custom-initialize-changed
   :type '(choice (choice-item dark)
                 (choice-item light)
@@ -1281,49 +1341,54 @@ examine the brightness for you."
 
 
 (defun frame-set-background-mode (frame)
-  "Set up the `background-mode' and `display-type' frame parameters for FRAME."
+  "Set up display-dependent faces on FRAME.
+Display-dependent faces are those which have different definitions
+according to the `background-mode' and `display-type' frame parameters."
   (let* ((bg-resource
          (and window-system
               (x-get-resource ".backgroundMode" "BackgroundMode")))
-        (params (frame-parameters frame))
-        (bg-mode (cond (frame-background-mode)
-                       ((null window-system)
-                        ;; No way to determine this automatically (?).
-                        'dark)
-                       (bg-resource
-                        (intern (downcase bg-resource)))
-                       ((< (apply '+ (x-color-values
-                                      (cdr (assq 'background-color
-                                                 params))
-                                      frame))
-                           ;; Just looking at the screen, colors whose
-                           ;; values add up to .6 of the white total
-                           ;; still look dark to me.
-                           (* (apply '+ (x-color-values "white" frame)) .6))
-                        'dark)
-                       (t 'light)))
-        (display-type (cond ((null window-system)
-                             (if (tty-display-color-p frame) 'color 'mono))
-                            ((x-display-color-p frame)
-                             'color)
-                            ((x-display-grayscale-p frame)
-                             'grayscale)
-                            (t 'mono))))
-    (modify-frame-parameters frame
-                            (list (cons 'background-mode bg-mode)
-                                  (cons 'display-type display-type))))
-  
-  ;; For all named faces, choose face specs matching the new frame
-  ;; parameters.
-  (let ((face-list (face-list)))
-    (while face-list
-      (let* ((face (car face-list))
-            (spec (get face 'face-defface-spec)))
-       (when spec
-         (face-spec-set face spec frame))
-      (setq face-list (cdr face-list))))))
-
-
+        (bg-color (frame-parameter frame 'background-color))
+        (bg-mode
+         (cond (frame-background-mode)
+               (bg-resource
+                (intern (downcase bg-resource)))
+               ((and (null window-system) (null bg-color))
+                ;; No way to determine this automatically (?).
+                'dark)
+               ;; Unspecified frame background color can only happen
+               ;; on tty's.
+               ((member bg-color '(unspecified "unspecified-bg"))
+                'dark)
+               ((equal bg-color "unspecified-fg") ; inverted colors
+                'light)
+               ((>= (apply '+ (x-color-values bg-color frame))
+                   ;; Just looking at the screen, colors whose
+                   ;; values add up to .6 of the white total
+                   ;; still look dark to me.
+                   (* (apply '+ (x-color-values "white" frame)) .6))
+                'light)
+               (t 'dark)))
+        (display-type
+         (cond ((null window-system)
+                (if (tty-display-color-p frame) 'color 'mono))
+               ((x-display-color-p frame)
+                'color)
+               ((x-display-grayscale-p frame)
+                'grayscale)
+               (t 'mono)))
+        (old-bg-mode
+         (frame-parameter frame 'background-mode))
+        (old-display-type
+         (frame-parameter frame 'display-type)))
+
+    (unless (and (eq bg-mode old-bg-mode) (eq display-type old-display-type))
+      (modify-frame-parameters frame
+                              (list (cons 'background-mode bg-mode)
+                                    (cons 'display-type display-type)))
+      ;; For all named faces, choose face specs matching the new frame
+      ;; parameters.
+      (dolist (face (face-list))
+       (face-spec-set face (face-user-default-spec face) frame)))))
 
 \f
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -1408,13 +1473,10 @@ Value is the new frame created."
   "Set frame-local faces of FRAME from face specs and resources.
 Initialize colors of certain faces from frame parameters."
   (dolist (face (face-list))
-    (let ((spec (or (get face 'saved-face)
-                   (get face 'face-defface-spec))))
-      (when spec
-       (face-spec-set face spec frame))
-      (internal-merge-in-global-face face frame)
-      (when (memq window-system '(x w32))
-       (make-face-x-resource-internal face frame))))
+    (face-spec-set face (face-user-default-spec face) frame)
+    (internal-merge-in-global-face face frame)
+    (when (memq window-system '(x w32 mac))
+      (make-face-x-resource-internal face frame)))
 
   ;; Initialize attributes from frame parameters.
   (let ((params '((foreground-color default :foreground)
@@ -1433,6 +1495,25 @@ Initialize colors of certain faces from frame parameters."
          (set-face-attribute face frame attr value)))
       (setq params (cdr params)))))
 
+(defun tty-handle-reverse-video (frame parameters)
+  "Handle the reverse-video frame parameter for terminal frames."
+  (when (cdr (or (assq 'reverse parameters)
+                (assq 'reverse default-frame-alist)))
+    (if (null window-system)
+       (setq inverse-video t))
+    (let* ((params (frame-parameters frame))
+          (bg (cdr (assq 'foreground-color params)))
+          (fg (cdr (assq 'background-color params))))
+      (modify-frame-parameters frame
+                              (list (cons 'foreground-color fg)
+                                    (cons 'background-color bg)))
+      (if (equal bg (cdr (assq 'mouse-color params)))
+         (modify-frame-parameters frame
+                                  (list (cons 'mouse-color fg))))
+      (if (equal bg (cdr (assq 'cursor-color params)))
+         (modify-frame-parameters frame
+                                  (list (cons 'cursor-color fg)))))))
+
 
 (defun tty-create-frame-with-faces (&optional parameters)
   "Create a frame from optional frame parameters PARAMETERS.
@@ -1444,6 +1525,7 @@ created."
        success)
     (unwind-protect
        (progn
+         (tty-handle-reverse-video frame (frame-parameters frame))
          (frame-set-background-mode frame)
          (face-set-after-frame-default frame)
          (setq success t))
@@ -1469,15 +1551,13 @@ created."
 
 ;; Update a frame's faces when we change its default font.
 
-(defun frame-update-faces (frame)
-  nil)
+(defalias 'frame-update-faces 'ignore)
 (make-obsolete 'frame-update-faces "No longer necessary" "21.1")
 
 ;; Update the colors of FACE, after FRAME's own colors have been
 ;; changed.
 
-(defun frame-update-face-colors (frame)
-  (frame-set-background-mode frame))
+(defalias 'frame-update-face-colors 'frame-set-background-mode)
 (make-obsolete 'frame-update-face-colors 'frame-set-background-mode "21.1")
 
 \f
@@ -1497,10 +1577,9 @@ created."
 
 
 (defface mode-line
-  '((((type x) (class color))
-     (:box (:line-width 2 :style released-button) :background "grey75"))
-    (((type w32) (class color))
-     (:box (:line-width 2 :style released-button) :background "grey75"))
+  '((((type x w32 mac) (class color))
+     (:box (:line-width 2 :style released-button)
+          :background "grey75" :foreground "black"))
     (t
      (:inverse-video t)))
   "Basic mode line face."
@@ -1512,10 +1591,37 @@ created."
 (put 'modeline 'face-alias 'mode-line)
 
 (defface header-line
-  '((((type x) (class color))
-     (:box (:line-width 2 :style released-button) :background "grey75"))
-    (((type w32) (class color))
-     (:box (:line-width 2 :style released-button) :background "grey75"))
+  '((((type tty))
+     ;; This used to be `:inverse-video t', but that doesn't look very
+     ;; good when combined with inverse-video mode-lines and multiple
+     ;; windows.  Underlining looks better, and is more consistent with
+     ;; the window-system face variants, which deemphasize the
+     ;; header-line in relation to the mode-line face.  If a terminal
+     ;; can't underline, then the header-line will end up without any
+     ;; highlighting; this may be too confusing in general, although it
+     ;; happens to look good with the only current use of header-lines,
+     ;; the info browser. XXX
+     (:underline t))
+    (((class color grayscale) (background light))
+     (:inherit mode-line
+      :background "grey90" :foreground "grey20"
+      :box (:line-width 1 :style released-button)))
+    (((class color grayscale) (background dark))
+     (:inherit mode-line
+      :background "grey20" :foreground "grey90"
+      :box (:line-width 1 :style released-button)))
+    (((class mono) (background light))
+     (:inherit mode-line
+      :background "white" :foreground "black"
+      :inverse-video nil
+      :box nil
+      :underline t))
+    (((class mono) (background dark))
+     (:inherit mode-line
+      :background "black" :foreground "white"
+      :inverse-video nil
+      :box nil
+      :underline t))
     (t
      (:inverse-video t)))
   "Basic header-line face."
@@ -1524,12 +1630,12 @@ created."
 
 
 (defface tool-bar
-  '((((type x) (class color))
-     (:box (:line-width 1 :style released-button) :background "grey75"))
+  '((((type x w32 mac) (class color))
+     (:box (:line-width 1 :style released-button)
+          :background "grey75" :foreground "black"))
     (((type x) (class mono))
-     (:box (:line-width 1 :style released-button) :background "grey"))
-    (((type w32) (class color))
-     (:box (:line-width 1 :style released-button) :background "grey75"))
+     (:box (:line-width 1 :style released-button)
+          :background "grey" :foreground "black"))
     (t
      ()))
   "Basic tool-bar face."
@@ -1543,19 +1649,22 @@ created."
     (((type tty) (class mono))
      (:inverse-video t))
     (((class color) (background dark))
-     (:background "blue"))
+     (:background "blue3"))
     (((class color) (background light))
-     (:background "lightblue"))
+     (:background "light goldenrod yellow"))
     (t (:background "gray")))
   "Basic face for highlighting the region."
+  :version "21.1"
   :group 'basic-faces)
 
 
 (defface fringe
-  '((((class color))
-     (:background "grey95"))
-    (t
-     (:background "gray")))
+  '((((class color) (background light))
+       (:background "grey95"))
+      (((class color) (background dark))
+       (:background "grey10"))
+      (t
+       (:background "gray")))
   "Basic face for the fringes to the left and right of windows under X."
   :version "21.1"
   :group 'frames
@@ -1633,11 +1742,11 @@ created."
 
 (defface secondary-selection
   '((((type tty) (class color))
-     (:background "cyan"))
+     (:background "cyan" :foreground "black"))
     (((class color) (background light))
      (:background "yellow"))
     (((class color) (background dark))
-     (:background "yellow"))
+     (:background "SkyBlue4"))
     (t (:inverse-video t)))
   "Basic face for displaying the secondary selection."
   :group 'basic-faces)