diff lisp/gtk-font-menu.el @ 462:0784d089fdc9 r21-2-46

Import from CVS: tag r21-2-46
author cvs
date Mon, 13 Aug 2007 11:44:37 +0200
parents
children 7039e6323819
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/gtk-font-menu.el	Mon Aug 13 11:44:37 2007 +0200
@@ -0,0 +1,248 @@
+;; gtk-font-menu.el --- Managing menus of GTK fonts.
+
+;; 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@jwz.org>
+;; Restructured by: Jonathan Stigelman <Stig@hackvan.com>
+;; Mule-ized by: Martin Buchholz
+;; More restructuring for MS-Windows by Andy Piper <andy@xemacs.org>
+;; GTK-ized by: William Perry <wmperry@xemacs.org>
+
+;; This file is part of XEmacs.
+
+;; XEmacs is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; XEmacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with XEmacs; see the file COPYING.  If not, write to the 
+;; Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+;;; Code:
+
+;; #### - implement these...
+;;
+;;; (defvar font-menu-ignore-proportional-fonts nil
+;;;   "*If non-nil, then the font menu will only show fixed-width fonts.")
+
+(require 'font-menu)
+
+(defvar gtk-font-menu-registry-encoding nil
+  "Registry and encoding to use with font menu fonts.")
+
+(defvar gtk-fonts-menu-junk-families
+  (mapconcat
+   #'identity
+   '("cursor" "glyph" "symbol"	; Obvious losers.
+     "\\`Ax...\\'"		; FrameMaker fonts - there are just way too
+				;  many of these, and there is a different
+				;  font family for each font face!  Losers.
+				;  "Axcor" -> "Applix Courier Roman",
+				;  "Axcob" -> "Applix Courier Bold", etc.
+     )
+   "\\|")
+  "A regexp matching font families which are uninteresting (e.g. cursor fonts).")
+
+(defun hack-font-truename (fn)
+  "Filter the output of `font-instance-truename' to deal with Japanese fontsets."
+  (if (string-match "," (font-instance-truename fn))
+      (let ((fpnt (nth 8 (split-string (font-instance-name fn) "-")))
+	    (flist (split-string (font-instance-truename fn) ","))
+	    ret)
+	(while flist
+	  (if (string-equal fpnt (nth 8 (split-string (car flist) "-")))
+	      (progn (setq ret (car flist)) (setq flist nil))
+	    (setq flist (cdr flist))
+	    ))
+	ret)
+    (font-instance-truename fn)))
+
+(defvar gtk-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.")
+
+;;;###autoload
+(defun gtk-reset-device-font-menus (device &optional debug)
+  "Generates the `Font', `Size', and `Weight' submenus for the Options menu.
+This is run the first time that a font-menu is needed for each device.
+If you don't like the lazy invocation of this function, you can add it to
+`create-device-hook' and that will make the font menus respond more quickly
+when they are selected for the first time.  If you add fonts to your system, 
+or if you change your font path, you can call this to re-initialize the menus."
+  ;; by Stig@hackvan.com
+  ;; #### - this should implement a `menus-only' option, which would
+  ;; recalculate the menus from the cache w/o having to do list-fonts again.
+  (unless gtk-font-regexp-ascii
+    (setq gtk-font-regexp-ascii (if (featurep 'mule)
+				    (charset-registry 'ascii)
+				  "iso8859-1")))
+  (setq gtk-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 gtk-font-regexp-ascii name)
+		 (string-match gtk-font-regexp name))
+	(setq weight (capitalize (match-string 1 name))
+	      size   (string-to-int (match-string 6 name)))
+	(or (string-match gtk-font-regexp-foundry-and-family name)
+	    (error "internal error"))
+	(setq family (capitalize (match-string 1 name)))
+	(or (string-match gtk-font-regexp-spacing name)
+	    (error "internal error"))
+	(setq monospaced-p (string= "m" (match-string 1 name)))
+	(unless (string-match gtk-fonts-menu-junk-families family)
+	  (setq entry (or (vassoc family cache)
+			  (car (setq cache
+				     (cons (vector family nil nil t)
+					   cache)))))
+	  (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)
+    ;; and some fonts come in both scalable and non-scalable versions
+    ;; (one size is 0).  If there are any scalable fonts at all, make
+    ;; sure that the union of all point sizes contains at least some
+    ;; common sizes - it's possible that some sensible sizes might end
+    ;; up not getting mentioned explicitly.
+    ;;
+    (if (member 0 sizes)
+	(let ((common '(60 80 100 120 140 160 180 240)))
+	  (while common
+	    (or;;(member (car common) sizes)   ; not enough slack
+	     (let ((rest sizes)
+		   (done nil))
+	       (while (and (not done) rest)
+		 (if (and (> (car common) (- (car rest) 5))
+			  (< (car common) (+ (car rest) 5)))
+		     (setq done t))
+		 (setq rest (cdr rest)))
+	       done)
+	     (setq sizes (cons (car common) sizes)))
+	    (setq common (cdr common)))
+	  (setq sizes (delq 0 sizes))))
+    
+    (setq families (sort families 'string-lessp)
+	  weights  (sort weights 'string-lessp)
+	  sizes    (sort sizes '<))
+    
+    (dolist (entry cache)
+      (aset entry 1 (sort (aref entry 1) 'string-lessp))
+      (aset entry 2 (sort (aref entry 2) '<)))
+
+    (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)))
+    (cdr dev-cache)))
+
+;; 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.
+
+;; 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.
+;;;###autoload
+(defun* gtk-font-menu-font-data (face dcache)
+  (defvar gtk-font-regexp)
+  (defvar gtk-font-regexp-foundry-and-family)
+  (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 gtk-font-regexp-foundry-and-family name)
+      (setq family (capitalize (match-string 1 name)))
+      (setq entry (vassoc family (aref dcache 0))))
+    (when (and (null entry)
+	       (string-match gtk-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 gtk-font-menu-font-data (make-vector 5 nil)))
+    
+    (when (string-match gtk-font-regexp name)
+      (setq weight (capitalize    (match-string 1 name)))
+      (setq size   (string-to-int (match-string 6 name))))
+      
+    (when (string-match gtk-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)))
+
+(defun gtk-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 "-*-*-"
+				  gtk-font-menu-registry-encoding)
+			 nil t))
+	      (throw 'got-font font))))))))
+
+(provide 'gtk-font-menu)
+
+;;; gtk-font-menu.el ends here