diff lisp/x11/x-font-menu.el @ 86:364816949b59 r20-0b93

Import from CVS: tag r20-0b93
author cvs
date Mon, 13 Aug 2007 09:09:02 +0200
parents 6a378aca36af
children 821dec489c24
line wrap: on
line diff
--- a/lisp/x11/x-font-menu.el	Mon Aug 13 09:08:31 2007 +0200
+++ b/lisp/x11/x-font-menu.el	Mon Aug 13 09:09:02 2007 +0200
@@ -2,9 +2,11 @@
 
 ;; Copyright (C) 1994 Free Software Foundation, Inc.
 ;; Copyright (C) 1995 Tinker Systems and INS Engineering Corp.
+;; Copyright (C) 1997 Sun Microsystems
 
 ;; Author: Jamie Zawinski <jwz@lucid.com>
 ;; Restructured by: Jonathan Stigelman <Stig@hackvan.com>
+;; Mule-ized by: Martin Buchholz
 
 ;; This file is part of XEmacs.
 
@@ -62,9 +64,9 @@
 ;;; `reset-device-font-menus' to rebuild the menus from all currently
 ;;; available fonts.
 ;;;
-;;; There is knowledge here about the regexp match numbers in `x-font-regexp',
-;;; `x-font-regexp-foundry-and-family', and
-;;; `x-font-regexp-registry-and-encoding' defined in x-faces.el.
+;;; There is knowledge here about the regexp match numbers in
+;;; `x-font-regexp' and `x-font-regexp-foundry-and-family' defined in
+;;; x-faces.el.
 ;;;
 ;;; There are at least three kinds of fonts under X11r5:
 ;;;
@@ -97,7 +99,7 @@
 ;;;	(font-properties (face-font 'default))
 ;;; - The values of the following variables after making a selection:
 ;;;	font-menu-preferred-resolution
-;;;	font-menu-preferred-registry
+;;;	font-menu-registry-encoding
 ;;;
 ;;; There is a common misconception that "*-courier-medium-r-*-11-*", also
 ;;; known as "-adobe-courier-medium-r-normal--11-80-100-100-m-60-iso8859-1",
@@ -105,6 +107,21 @@
 ;;; which is an 8-point font (the number after -11- is the size in tenths
 ;;; of points).  So if you expect to be seeing an "11" entry in the "Size"
 ;;; menu and are not, this may be why.
+;;;
+;;; In the real world (aka Solaris), one has to deal with fonts that
+;;; appear to be medium-i but are really light-r, and fonts that
+;;; resolve to different resolutions depending on the charset:
+;;;
+;;; (font-instance-truename
+;;;  (make-font-instance "-*-mincho-medium-i-normal-*-*-*-*-*-*-*-jisx0201*-*"))
+;;; ==>
+;;; "-morisawa-ryumin light kl-light-r-normal--10-100-72-72-m-50-jisx0201.1976-0"
+;;;
+;;; (list-fonts "-dt-interface user-medium-r-normal-s*-*-*-*-*-*-*-*-*")
+;;; ==>
+;;; ("-dt-interface user-medium-r-normal-s sans-12-120-72-72-m-70-iso8859-1"
+;;;  "-dt-interface user-medium-r-normal-s-14-120-75-75-m-120-jisx0208.1983-0"
+;;;  "-dt-interface user-medium-r-normal-s-14-120-75-75-m-60-jisx0201.1976-0")
 
 ;;; Code:
 
@@ -126,10 +143,13 @@
 ;; ( (device . [parsed-list-fonts family-menu size-menu weight-menu]) ...)
 (defvar device-fonts-cache nil)
 
-(defconst font-menu-preferred-registry nil) 
-(defconst font-menu-preferred-resolution nil)
+(defvar font-menu-registry-encoding nil
+  "Registry and encoding to use with font menu fonts.")
 
-(defconst fonts-menu-junk-families
+(defvar font-menu-preferred-resolution "*-*"
+  "Preferred horizontal and vertical font menu resolution (e.g. \"75-75\").")
+
+(defvar fonts-menu-junk-families
   (purecopy
    (mapconcat
     #'identity
@@ -143,6 +163,11 @@
     "\\|"))
   "A regexp matching font families which are uninteresting (e.g. cursor fonts).")
 
+(eval-when-compile
+  (defsubst device-fonts-cache ()
+    (or (cdr (assq (selected-device) device-fonts-cache))
+	(reset-device-font-menus (selected-device)))))
+
 (defun hack-font-truename (fn)
   "Filter the output of `font-instance-truename' to deal with Japanese fontsets."
   (if (string-match "," (font-instance-truename fn))
@@ -161,8 +186,8 @@
 (fset 'install-font-menus 'reset-device-font-menus)
 (make-obsolete 'install-font-menus 'reset-device-font-menus)
 
-(defvar x-font-regexp-ja nil
-  "This is used to filter out fonts that don't work in the locale.
+(defvar x-font-regexp-ascii nil
+  "This is used to filter out font families that can't display ASCII text.
 It must be set at run-time.")
 
 (defun vassoc (key valist)
@@ -191,30 +216,20 @@
 	  (not (or device (setq device (selected-device))))
 	  (not (eq (device-type device) 'x)))
       nil
-    (if (and (getenv "LANG")
-	     (string-match "^\\(ja\\|japanese\\)$"
-			   (getenv "LANG")))
-	;; #### - this is questionable behavior left over from the I18N4 code.
-	(setq x-font-regexp-ja "jisx[^-]*-[^-]*$"
-	      font-menu-preferred-registry '("*" . "*")
-	      font-menu-preferred-resolution '("*" . "*")))
-    (let ((all-fonts nil)
-	  (case-fold-search t)
-	  name family size weight entry monospaced-p
-	  dev-cache
-	  (cache nil)
-	  (families nil)
-	  (sizes nil)
-	  (weights nil))
-      (cond ((stringp debug)		; kludge
-	     (setq all-fonts (split-string debug "\n")))
-	    (t
-	     (setq all-fonts
-		   (or debug
-		       (list-fonts "*-*-*-*-*-*-*-*-*-*-*-*-*-*" device)))))
-      (while (setq name (pop all-fonts))
-	(when (and (or (not x-font-regexp-ja)
-		       (string-match x-font-regexp-ja name))
+    (unless x-font-regexp-ascii
+      (setq x-font-regexp-ascii (if (fboundp 'charset-registry)
+				    (charset-registry 'ascii)
+				  "iso8859-1")))
+    (setq font-menu-registry-encoding
+	  (if (featurep 'mule) "*-*" "iso8859-1"))
+    (let ((case-fold-search t)
+	  family size weight entry monospaced-p
+	  dev-cache cache families sizes weights)
+      (dolist (name (cond ((null debug)	; debugging kludge
+			   (list-fonts "*-*-*-*-*-*-*-*-*-*-*-*-*-*" device))
+			  ((stringp debug) (split-string debug "\n"))
+			  (t debug)))
+	(when (and (string-match x-font-regexp-ascii name)
 		   (string-match x-font-regexp name))
 	  (setq weight (capitalize (match-string 1 name))
 		size   (string-to-int (match-string 6 name)))
@@ -229,18 +244,12 @@
 			    (car (setq cache
 				       (cons (vector family nil nil t)
 					     cache)))))
-	    (or (member family families)
-		(setq families (cons family families)))
-	    (or (member weight weights)
-		(setq weights (cons weight weights)))
-	    (or (member weight (aref entry 1))
-		(aset entry 1 (cons weight (aref entry 1))))
-	    (or (member size sizes)
-		(setq sizes (cons size sizes)))
-	    (or (member size (aref entry 2))
-		(aset entry 2 (cons size (aref entry 2))))
-	    (aset entry 3 (and (aref entry 3) monospaced-p))
-	    )))
+	    (or (member family families) (push family families))
+	    (or (member weight weights)  (push weight weights))
+	    (or (member size   sizes)    (push size   sizes))
+	    (or (member weight (aref entry 1)) (push weight (aref entry 1)))
+	    (or (member size   (aref entry 2)) (push size   (aref entry 2)))
+	    (aset entry 3 (and (aref entry 3) monospaced-p)))))
       ;;
       ;; Hack scalable fonts.
       ;; Some fonts come only in scalable versions (the only size is 0)
@@ -267,181 +276,178 @@
 	    (setq sizes (delq 0 sizes))))
 
       (setq families (sort families 'string-lessp)
-	    weights (sort weights 'string-lessp)
-	    sizes (sort sizes '<))
+	    weights  (sort weights 'string-lessp)
+	    sizes    (sort sizes '<))
 
-      (let ((rest cache))
-	(while rest
-	  (aset (car rest) 1 (sort (aref (car rest) 1) 'string-lessp))
-	  (aset (car rest) 2 (sort (aref (car rest) 2) '<))
-	  (setq rest (cdr rest))))
+      (dolist (entry cache)
+	  (aset entry 1 (sort (aref entry 1) 'string-lessp))
+	  (aset entry 2 (sort (aref entry 2) '<)))
 
       (message "Getting list of fonts from server... done.")
 
       (setq dev-cache (assq device device-fonts-cache))
       (or dev-cache
 	  (setq dev-cache (car (push (list device) device-fonts-cache))))
-      (setcdr dev-cache
-	      (vector
-	       cache
-	       (mapcar #'(lambda (x)
-			   (vector x
-				   (list 'font-menu-set-font x nil nil)
-				   ':style 'radio ':active nil ':selected nil))
-		       families)
-	       (mapcar #'(lambda (x)
-			   (vector (if (/= 0 (% x 10))
-				       ;; works with no LISP_FLOAT_TYPE
-				       (concat (int-to-string (/ x 10)) "."
-					       (int-to-string (% x 10)))
-				     (int-to-string (/ x 10)))
-				   (list 'font-menu-set-font nil nil x)
-				   ':style 'radio ':active nil ':selected nil))
-		       sizes)
-	       (mapcar #'(lambda (x)
-			   (vector x
-				   (list 'font-menu-set-font nil x nil)
-				   ':style 'radio ':active nil ':selected nil))
-		       weights)))
+      (setcdr
+       dev-cache
+       (vector
+	cache
+	(mapcar (lambda (x)
+		  (vector x
+			  (list 'font-menu-set-font x nil nil)
+			  ':style 'radio ':active nil ':selected nil))
+		families)
+	(mapcar (lambda (x)
+		  (vector (if (/= 0 (% x 10))
+			      ;; works with no LISP_FLOAT_TYPE
+			      (concat (int-to-string (/ x 10)) "."
+				      (int-to-string (% x 10)))
+			    (int-to-string (/ x 10)))
+			  (list 'font-menu-set-font nil nil x)
+			  ':style 'radio ':active nil ':selected nil))
+		sizes)
+	(mapcar (lambda (x)
+		  (vector x
+			  (list 'font-menu-set-font nil x nil)
+			  ':style 'radio ':active nil ':selected nil))
+		weights)))
       (cdr dev-cache))))
 
-(defsubst font-menu-truename (face)
-  (hack-font-truename
-   (if (featurep 'mule)
-       (face-font-instance face nil 'ascii)
-     (face-font-instance face))))
+;; Extract font information from a face.  We examine both the
+;; user-specified font name and the canonical (`true') font name.
+;; These can appear to have totally different properties.
+;; For examples, see the prolog above.
 
-;;; Extract a font family from a face.
-;;; Use the user-specified one if possible.
-;;; If the user didn't specify one (with "*", for example)
-;;; get the truename and use the guaranteed family from that.
-(defun font-menu-family (face)
-  (let ((dcache (cdr (assq (selected-device) device-fonts-cache)))
-	(name (font-instance-name (face-font-instance face)))
-	(family nil))
+;; We use the user-specified one if possible, else use the truename.
+;; If the user didn't specify one (with "-dt-*-*", for example)
+;; get the truename and use the possibly suboptimal data from that.
+(defun* font-menu-font-data (face dcache)
+  (let* ((case-fold-search t)
+	 (domain (if font-menu-this-frame-only-p
+				  (selected-frame)
+				(selected-device)))
+	 (name (font-instance-name (face-font-instance face domain)))
+	 (truename (font-instance-truename
+		    (face-font-instance face domain
+					(if (featurep 'mule) 'ascii))))
+	 family size weight entry slant)
     (when (string-match x-font-regexp-foundry-and-family name)
-      (setq family (capitalize (match-string 1 name))))
-    (when (not (and family (vassoc family (aref dcache 0))))
-      (setq name (font-menu-truename face))
-      (string-match x-font-regexp-foundry-and-family name)
-      (setq family (capitalize (match-string 1 name))))
-    family))
+      (setq family (capitalize (match-string 1 name)))
+      (setq entry (vassoc family (aref dcache 0))))
+    (when (and (null entry)
+	       (string-match x-font-regexp-foundry-and-family truename))
+      (setq family (capitalize (match-string 1 truename)))
+      (setq entry  (vassoc family (aref dcache 0))))
+    (when (null entry)
+      (return-from font-menu-font-data (make-vector 5 nil)))
+    
+    (when (string-match x-font-regexp name)
+      (setq weight (capitalize    (match-string 1 name)))
+      (setq size   (string-to-int (match-string 6 name))))
+      
+    (when (string-match x-font-regexp truename)
+      (when (not (member weight (aref entry 1)))
+	(setq weight (capitalize (match-string 1 truename))))
+      (when (not (member size   (aref entry 2)))
+	(setq size (string-to-int (match-string 6 truename))))
+      (setq slant (capitalize (match-string 2 truename))))
+      
+    (vector entry family size weight slant)))
 
 ;;;###autoload
 (defun font-menu-family-constructor (ignored)
-  ;; by Stig@hackvan.com
-  (if (not (eq 'x (device-type (selected-device))))
-      '(["Cannot parse current font" ding nil])
-    (let* ((dcache (cdr (assq (selected-device) device-fonts-cache)))
-	   (name (font-menu-truename 'default))
-	   (case-fold-search t)
-	   family weight size		; parsed from current font
-	   entry			; font cache entry
+  (catch 'menu
+    (unless (eq 'x (device-type (selected-device)))
+      (throw 'menu '(["Cannot parse current font" ding nil])))
+    (let* ((dcache (device-fonts-cache))
+	   (font-data (font-menu-font-data 'default dcache))
+	   (entry  (aref font-data 0))
+	   (family (aref font-data 1))
+	   (size   (aref font-data 2))
+	   (weight (aref font-data 3))
 	   f)
-      (or dcache
-	  (setq dcache (reset-device-font-menus (selected-device))))
-      (if (not (string-match x-font-regexp name))
-	  ;; couldn't parse current font
-	  '(["Cannot parse current font" ding nil])
-	(setq weight (capitalize (match-string 1 name)))
-	(setq size (string-to-number (match-string 6 name)))
-	(setq family (font-menu-family 'default))
-	(setq entry (vassoc family (aref dcache 0)))
-	(mapcar #'(lambda (item)
-		    ;;
-		    ;; Items on the Font menu are enabled iff that font
-		    ;; exists in the same size and weight as the current
-		    ;; font (scalable fonts exist in every size).  Only the
-		    ;; current font is marked as selected.
-		    ;;
-		    (setq f (aref item 0)
-			  entry (vassoc f (aref dcache 0)))
-		    (if (and (member weight (aref entry 1))
-			     (or (member size (aref entry 2))
-				 (and (not font-menu-ignore-scaled-fonts)
-				      (member 0 (aref entry 2)))))
-			(enable-menu-item item)
-		      (disable-menu-item item))
-		    (if (equal family f)
-			(select-toggle-menu-item item)
-		      (deselect-toggle-menu-item item))
-		    item)
-		(aref dcache 1)))
-      )))
+      (unless family
+	(throw 'menu '(["Cannot parse current font" ding nil])))
+      ;; Items on the Font menu are enabled iff that font exists in
+      ;; the same size and weight as the current font (scalable fonts
+      ;; exist in every size).  Only the current font is marked as
+      ;; selected.
+      (mapcar
+       (lambda (item)
+	 (setq f (aref item 0)
+	       entry (vassoc f (aref dcache 0)))
+	 (if (and (member weight (aref entry 1))
+		  (or (member size (aref entry 2))
+		      (and (not font-menu-ignore-scaled-fonts)
+			   (member 0 (aref entry 2)))))
+	     (enable-menu-item item)
+	   (disable-menu-item item))
+	 (if (string-equal family f)
+	     (select-toggle-menu-item item)
+	   (deselect-toggle-menu-item item))
+	 item)
+       (aref dcache 1)))))
 
 ;;;###autoload
 (defun font-menu-size-constructor (ignored)
-  ;; by Stig@hackvan.com
-  (if (not (eq 'x (device-type (selected-device))))
-      '(["Cannot parse current font" ding nil])
-    (let ((dcache (cdr (assq (selected-device) device-fonts-cache)))
-	  (name (font-menu-truename 'default))
-	  (case-fold-search t)
-	  family size			; parsed from current font
-	  entry				; font cache entry
-	  s)
-      (or dcache
-	  (setq dcache (reset-device-font-menus (selected-device))))
-      (if (not (string-match x-font-regexp name))
-	  ;; couldn't parse current font
-	  '(["Cannot parse current font" ding nil])
-	(setq size (string-to-number (match-string 6 name)))
-	(setq family (font-menu-family 'default))
-	(setq entry (vassoc family (aref dcache 0)))
-	(mapcar
-         (lambda (item)
-           ;;
-           ;; Items on the Size menu are enabled iff current font has
-           ;; that size.  Only the size of the current font is
-           ;; selected.  (If the current font comes in size 0, it is
-           ;; scalable, and thus has every size.)
-           ;;
-           (setq s (nth 3 (aref item 1)))
-           (if (or (member s (aref entry 2))
-                   (and (not font-menu-ignore-scaled-fonts)
-                        (member 0 (aref entry 2))))
-               (enable-menu-item item)
-             (disable-menu-item item))
-           (if (eq size s)
-               (select-toggle-menu-item item)
-             (deselect-toggle-menu-item item))
-           item)
-         (aref dcache 2)))
-      )))
+  (catch 'menu
+    (unless (eq 'x (device-type (selected-device)))
+      (throw 'menu '(["Cannot parse current font" ding nil])))
+    (let* ((dcache (device-fonts-cache))
+	   (font-data (font-menu-font-data 'default dcache))
+	   (entry  (aref font-data 0))
+	   (family (aref font-data 1))
+	   (size   (aref font-data 2))
+	   ;;(weight (aref font-data 3))
+	   s)
+      (unless family
+	(throw 'menu '(["Cannot parse current font" ding nil])))
+      ;; Items on the Size menu are enabled iff current font has
+      ;; that size.  Only the size of the current font is selected.
+      ;; (If the current font comes in size 0, it is scalable, and
+      ;; thus has every size.)
+      (mapcar
+       (lambda (item)
+	 (setq s (nth 3 (aref item 1)))
+	 (if (or (member s (aref entry 2))
+		 (and (not font-menu-ignore-scaled-fonts)
+		      (member 0 (aref entry 2))))
+	     (enable-menu-item item)
+	   (disable-menu-item item))
+	 (if (eq size s)
+	     (select-toggle-menu-item item)
+	   (deselect-toggle-menu-item item))
+	 item)
+       (aref dcache 2)))))
 
 ;;;###autoload
 (defun font-menu-weight-constructor (ignored)
-  ;; by Stig@hackvan.com
-  (if (not (eq 'x (device-type (selected-device))))
-      '(["Cannot parse current font" ding nil])
-    (let ((dcache (cdr (assq (selected-device) device-fonts-cache)))
-	  (name (font-menu-truename 'default))
-	  (case-fold-search t)
-	  family weight			; parsed from current font
-	  entry				; font cache entry
-	  w)
-      (or dcache
-	  (setq dcache (reset-device-font-menus (selected-device))))
-      (if (not (string-match x-font-regexp name))
-	  ;; couldn't parse current font
-	  '(["Cannot parse current font" ding nil])
-	(setq weight (capitalize (match-string 1 name)))
-	(setq family (font-menu-family 'default))
-	(setq entry (vassoc family (aref dcache 0)))
-	(mapcar #'(lambda (item)
-		    ;; Items on the Weight menu are enabled iff current font
-		    ;; has that weight.  Only the weight of the current font
-		    ;; is selected.
-		    (setq w (aref item 0))
-		    (if (member w (aref entry 1))
-			(enable-menu-item item)
-		      (disable-menu-item item))
-		    (if (equal weight w)
-			(select-toggle-menu-item item)
-		      (deselect-toggle-menu-item item))
-		    item)
-		(aref dcache 3)))
-      )))
+  (catch 'menu
+    (unless (eq 'x (device-type (selected-device)))
+      (throw 'menu '(["Cannot parse current font" ding nil])))
+    (let* ((dcache (device-fonts-cache))
+	   (font-data (font-menu-font-data 'default dcache))
+	   (entry  (aref font-data 0))
+	   (family (aref font-data 1))
+	   ;;(size   (aref font-data 2))
+	   (weight (aref font-data 3))
+	   w)
+      (unless family
+	(throw 'menu '(["Cannot parse current font" ding nil])))
+      ;; Items on the Weight menu are enabled iff current font
+      ;; has that weight.  Only the weight of the current font
+      ;; is selected.
+      (mapcar
+       (lambda (item)
+	 (setq w (aref item 0))
+	 (if (member w (aref entry 1))
+	     (enable-menu-item item)
+	   (disable-menu-item item))
+	 (if (string-equal weight w)
+	     (select-toggle-menu-item item)
+	   (deselect-toggle-menu-item item))
+	 item)
+       (aref dcache 3)))))
 
 
 ;;; Changing font sizes
@@ -450,35 +456,31 @@
   ;; This is what gets run when an item is selected from any of the three
   ;; fonts menus.  It needs to be rather clever.
   ;; (size is measured in 10ths of points.)
-  (let ((faces (delq 'default (face-list)))
-	(default-name (font-menu-truename 'default))
-	(case-fold-search t)
-	new-default-face-font
-	from-family from-weight from-size)
-    ;;
-    ;; First, parse out the default face's font.
-    ;;
-    (setq from-family (font-menu-family 'default))
-    (or (string-match x-font-regexp default-name)
-	(signal 'error (list "couldn't parse font name" default-name)))
-    (setq from-weight (capitalize (match-string 1 default-name)))
-    (setq from-size (match-string 6 default-name))
+  (let* ((dcache (device-fonts-cache))
+	 (font-data (font-menu-font-data 'default dcache))
+	 (from-family (aref font-data 1))
+	 (from-size   (aref font-data 2))
+	 (from-weight (aref font-data 3))
+	 (from-slant  (aref font-data 4))
+	 new-default-face-font)
+    (unless from-family
+      (signal 'error '("couldn't parse font name for default face")))
     (setq new-default-face-font
 	  (font-menu-load-font (or family from-family)
 			       (or weight from-weight)
 			       (or size   from-size)
-			       default-name))
-    (while faces
-      (cond ((face-font-instance (car faces))
-	     (message "Changing font of `%s'..." (car faces))
-	     (condition-case c
-		 (font-menu-change-face (car faces)
-					from-family from-weight from-size
-					family weight size)
-	       (error
-		(display-error c nil)
-		(sit-for 1)))))
-      (setq faces (cdr faces)))
+			       from-slant
+			       font-menu-preferred-resolution))
+    (dolist (face (delq 'default (face-list)))
+      (when (face-font-instance face)
+	(message "Changing font of `%s'..." face)
+	(condition-case c
+	    (font-menu-change-face face
+				   from-family from-weight from-size
+				   family      weight      size)
+	  (error
+	   (display-error c nil)
+	   (sit-for 1)))))
     ;; Set the default face's font after hacking the other faces, so that
     ;; the frame size doesn't change until we are all done.
 
@@ -492,146 +494,58 @@
 			      from-family from-weight from-size
 			      to-family   to-weight   to-size)
   (or (symbolp face) (signal 'wrong-type-argument (list 'symbolp face)))
-  (let* ((name (font-menu-truename face))
-	 (case-fold-search t)
-	 face-family
-	 face-weight
-	 face-size)
-    ;; First, parse out the face's font.
-    (or (string-match x-font-regexp-foundry-and-family name)
-	(signal 'error (list "couldn't parse font name" name)))
-    (setq face-family (capitalize (match-string 1 name)))
-    (or (string-match x-font-regexp name)
-	(signal 'error (list "couldn't parse font name" name)))
-    (setq face-weight (match-string 1 name))
-    (setq face-size (match-string 6 name))
+  (let* ((dcache (device-fonts-cache))
+	 (font-data (font-menu-font-data face dcache))
+	 (face-family (aref font-data 1))
+	 (face-size   (aref font-data 2))
+	 (face-weight (aref font-data 3))
+	 (face-slant  (aref font-data 4)))
+
+    (or face-family
+	(signal 'error (list "couldn't parse font name for face" face)))
 
     ;; If this face matches the old default face in the attribute we
     ;; are changing, then change it to the new attribute along that
     ;; dimension.  Also, the face must have its own global attribute.
     ;; If its value is inherited, we don't touch it.  If any of this
     ;; is not true, we leave it alone.
-    (if (and (face-font face 'global)
-	     (cond 
-	      (to-family (equal face-family from-family))
-	      (to-weight (equal face-weight from-weight))
-	      (to-size   (equal face-size from-size))))
-	(set-face-font face
-		       (font-menu-load-font (or to-family face-family)
-					    (or to-weight face-weight)
-					    (or to-size   face-size)
-					    name)
-		       (and font-menu-this-frame-only-p
-			    (selected-frame)))
-      nil)))
-
-
-(defun font-menu-load-font (family weight size from-font)
-  (and (numberp size) (setq size (int-to-string size)))
-  (let ((case-fold-search t)
-	slant other-slant
-	registry encoding resx resy)
-    (or (string-match x-font-regexp-registry-and-encoding from-font)
-	(signal 'error (list "couldn't parse font name" from-font)))
-    (setq registry (match-string 1 from-font)
-	  encoding (match-string 2 from-font))
+    (when (and (face-font face 'global)
+	       (cond 
+		(to-family (string-equal face-family from-family))
+		(to-weight (string-equal face-weight from-weight))
+		(to-size   (=            face-size   from-size))))
+      (set-face-font face
+		     (font-menu-load-font (or to-family face-family)
+					  (or to-weight face-weight)
+					  (or to-size   face-size)
+					  face-slant
+					  font-menu-preferred-resolution)
+		     (and font-menu-this-frame-only-p
+			  (selected-frame))))))
 
-    (or (string-match x-font-regexp from-font)
-	(signal 'error (list "couldn't parse font name" from-font)))
-    (setq slant (capitalize (match-string 2 from-font))
-	  resx  (match-string 7 from-font)
-	  resy  (match-string 8 from-font))
-    (setq other-slant (cond ((equal slant "O") "I") ; oh, bite me.
-			    ((equal slant "I") "O")
-			    (t nil)))
-    ;;
-    ;; Remember these values for the first font we switch away from
-    ;; (the original default font).
-    ;;
-    (or font-menu-preferred-resolution
-	(setq font-menu-preferred-resolution (cons resx resy)))
-    (or font-menu-preferred-registry
-	(setq font-menu-preferred-registry (cons registry encoding)))
-    ;;
-    ;; Now we know all the interesting properties of the font we want.
-    ;; Let's see what we can actually *get*.
-    ;;
-    (or ;; First try the default resolution, registry, and encoding.
-        (make-font-instance
-	 (concat "-*-" family "-" weight "-" slant "-*-*-*-" size
-		 "-" (car font-menu-preferred-resolution)
-		 "-" (cdr font-menu-preferred-resolution)
-		 "-*-*-"
-		 (car font-menu-preferred-registry) "-"
-		 (cdr font-menu-preferred-registry))
-	 nil t)
-	;; Then try that in the other slant.
-	(and other-slant
-	     (make-font-instance
-	      (concat "-*-" family "-" weight "-" other-slant
-		      "-*-*-*-" size
-		      "-" (car font-menu-preferred-resolution)
-		      "-" (cdr font-menu-preferred-resolution)
-		      "-*-*-"
-		      (car font-menu-preferred-registry) "-"
-		      (cdr font-menu-preferred-registry))
-	      nil t))
-	;; Then try the default resolution and registry, any encoding.
-	(make-font-instance
-	 (concat "-*-" family "-" weight "-" slant "-*-*-*-" size
-		 "-" (car font-menu-preferred-resolution)
-		 "-" (cdr font-menu-preferred-resolution)
-		 "-*-*-"
-		 (car font-menu-preferred-registry) "-*")
-	 nil t)
-	;; Then try that in the other slant.
-	(and other-slant
-	     (make-font-instance
-	      (concat "-*-" family "-" weight "-" other-slant
-		      "-*-*-*-" size
-		      "-" (car font-menu-preferred-resolution)
-		      "-" (cdr font-menu-preferred-resolution)
-		      "-*-*-"
-		      (car font-menu-preferred-registry) "-*")
-	      nil t))
-	;; Then try the default registry and encoding, any resolution.
-	(make-font-instance
-	 (concat "-*-" family "-" weight "-" slant "-*-*-*-" size
-		 "-*-*-*-*-"
-		 (car font-menu-preferred-registry) "-"
-		 (cdr font-menu-preferred-registry))
-	 nil t)
-	;; Then try that in the other slant.
-	(and other-slant
-	     (make-font-instance
-	      (concat "-*-" family "-" weight "-" other-slant
-		      "-*-*-*-" size
-		      "-*-*-*-*-"
-		      (car font-menu-preferred-registry) "-"
-		      (cdr font-menu-preferred-registry))
-	      nil t))
-	;; Then try the default registry, any encoding or resolution.
-	(make-font-instance
-	 (concat "-*-" family "-" weight "-" slant "-*-*-*-" size
-		 "-*-*-*-*-"
-		 (car font-menu-preferred-registry) "-*")
-	 nil t)
-	;; Then try that in the other slant.
-	(and other-slant
-	     (make-font-instance
-	      (concat "-*-" family "-" weight "-" slant "-*-*-*-"
-		      size "-*-*-*-*-"
-		      (car font-menu-preferred-registry) "-*")
-	      nil t))
-	;; Then try anything in the same slant, and error if it fails...
-	(and other-slant
-	     (make-font-instance
-	      (concat "-*-" family "-" weight "-" slant "-*-*-*-"
-		      size "-*-*-*-*-*-*")))
-	(make-font-instance
-	 (concat "-*-" family "-" weight "-" (or other-slant slant)
-		 "-*-*-*-" size "-*-*-*-*-*-*"))
-	)))
+(defun font-menu-load-font (family weight size slant resolution)
+  "Try to load a font with the requested properties.
+The weight, slant and resolution are only hints."
+  (when (integerp size) (setq size (int-to-string size)))
+  (let (font)
+    (catch 'got-font
+      (dolist (weight (list weight "*"))
+	(dolist (slant
+		 (cond ((string-equal slant "O") '("O" "I" "*"))
+		       ((string-equal slant "I") '("I" "O" "*"))
+		       ((string-equal slant "*") '("*"))
+		       (t (list slant "*"))))
+	  (dolist (resolution
+		   (if (string-equal resolution "*-*")
+		       (list resolution)
+		     (list resolution "*-*")))
+	    (when (setq font
+			(make-font-instance
+			 (concat  "-*-" family "-" weight "-" slant "-*-*-*-"
+				  size "-" resolution "-*-*-"
+				  font-menu-registry-encoding)
+			 nil t))
+	      (throw 'got-font font))))))))
 
 (defun flush-device-fonts-cache (device)
   ;; by Stig@hackvan.com