Mercurial > hg > xemacs-beta
comparison 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 |
comparison
equal
deleted
inserted
replaced
85:c661705957e0 | 86:364816949b59 |
---|---|
1 ;; x-font-menu.el --- Managing menus of X fonts. | 1 ;; x-font-menu.el --- Managing menus of X fonts. |
2 | 2 |
3 ;; Copyright (C) 1994 Free Software Foundation, Inc. | 3 ;; Copyright (C) 1994 Free Software Foundation, Inc. |
4 ;; Copyright (C) 1995 Tinker Systems and INS Engineering Corp. | 4 ;; Copyright (C) 1995 Tinker Systems and INS Engineering Corp. |
5 ;; Copyright (C) 1997 Sun Microsystems | |
5 | 6 |
6 ;; Author: Jamie Zawinski <jwz@lucid.com> | 7 ;; Author: Jamie Zawinski <jwz@lucid.com> |
7 ;; Restructured by: Jonathan Stigelman <Stig@hackvan.com> | 8 ;; Restructured by: Jonathan Stigelman <Stig@hackvan.com> |
9 ;; Mule-ized by: Martin Buchholz | |
8 | 10 |
9 ;; This file is part of XEmacs. | 11 ;; This file is part of XEmacs. |
10 | 12 |
11 ;; XEmacs is free software; you can redistribute it and/or modify it | 13 ;; XEmacs is free software; you can redistribute it and/or modify it |
12 ;; under the terms of the GNU General Public License as published by | 14 ;; under the terms of the GNU General Public License as published by |
60 ;;; XEmacs startup. At any time (i.e.: after a font-path change or | 62 ;;; XEmacs startup. At any time (i.e.: after a font-path change or |
61 ;;; immediately after device creation), you can call | 63 ;;; immediately after device creation), you can call |
62 ;;; `reset-device-font-menus' to rebuild the menus from all currently | 64 ;;; `reset-device-font-menus' to rebuild the menus from all currently |
63 ;;; available fonts. | 65 ;;; available fonts. |
64 ;;; | 66 ;;; |
65 ;;; There is knowledge here about the regexp match numbers in `x-font-regexp', | 67 ;;; There is knowledge here about the regexp match numbers in |
66 ;;; `x-font-regexp-foundry-and-family', and | 68 ;;; `x-font-regexp' and `x-font-regexp-foundry-and-family' defined in |
67 ;;; `x-font-regexp-registry-and-encoding' defined in x-faces.el. | 69 ;;; x-faces.el. |
68 ;;; | 70 ;;; |
69 ;;; There are at least three kinds of fonts under X11r5: | 71 ;;; There are at least three kinds of fonts under X11r5: |
70 ;;; | 72 ;;; |
71 ;;; - bitmap fonts, which can be assumed to look as good as possible; | 73 ;;; - bitmap fonts, which can be assumed to look as good as possible; |
72 ;;; - bitmap fonts which have been (or can be) automatically scaled to | 74 ;;; - bitmap fonts which have been (or can be) automatically scaled to |
95 ;;; (face-font 'default) | 97 ;;; (face-font 'default) |
96 ;;; (font-truename (face-font 'default)) | 98 ;;; (font-truename (face-font 'default)) |
97 ;;; (font-properties (face-font 'default)) | 99 ;;; (font-properties (face-font 'default)) |
98 ;;; - The values of the following variables after making a selection: | 100 ;;; - The values of the following variables after making a selection: |
99 ;;; font-menu-preferred-resolution | 101 ;;; font-menu-preferred-resolution |
100 ;;; font-menu-preferred-registry | 102 ;;; font-menu-registry-encoding |
101 ;;; | 103 ;;; |
102 ;;; There is a common misconception that "*-courier-medium-r-*-11-*", also | 104 ;;; There is a common misconception that "*-courier-medium-r-*-11-*", also |
103 ;;; known as "-adobe-courier-medium-r-normal--11-80-100-100-m-60-iso8859-1", | 105 ;;; known as "-adobe-courier-medium-r-normal--11-80-100-100-m-60-iso8859-1", |
104 ;;; is an 11-point font. It is not -- it is an 11-pixel font at 100dpi, | 106 ;;; is an 11-point font. It is not -- it is an 11-pixel font at 100dpi, |
105 ;;; which is an 8-point font (the number after -11- is the size in tenths | 107 ;;; which is an 8-point font (the number after -11- is the size in tenths |
106 ;;; of points). So if you expect to be seeing an "11" entry in the "Size" | 108 ;;; of points). So if you expect to be seeing an "11" entry in the "Size" |
107 ;;; menu and are not, this may be why. | 109 ;;; menu and are not, this may be why. |
110 ;;; | |
111 ;;; In the real world (aka Solaris), one has to deal with fonts that | |
112 ;;; appear to be medium-i but are really light-r, and fonts that | |
113 ;;; resolve to different resolutions depending on the charset: | |
114 ;;; | |
115 ;;; (font-instance-truename | |
116 ;;; (make-font-instance "-*-mincho-medium-i-normal-*-*-*-*-*-*-*-jisx0201*-*")) | |
117 ;;; ==> | |
118 ;;; "-morisawa-ryumin light kl-light-r-normal--10-100-72-72-m-50-jisx0201.1976-0" | |
119 ;;; | |
120 ;;; (list-fonts "-dt-interface user-medium-r-normal-s*-*-*-*-*-*-*-*-*") | |
121 ;;; ==> | |
122 ;;; ("-dt-interface user-medium-r-normal-s sans-12-120-72-72-m-70-iso8859-1" | |
123 ;;; "-dt-interface user-medium-r-normal-s-14-120-75-75-m-120-jisx0208.1983-0" | |
124 ;;; "-dt-interface user-medium-r-normal-s-14-120-75-75-m-60-jisx0201.1976-0") | |
108 | 125 |
109 ;;; Code: | 126 ;;; Code: |
110 | 127 |
111 ;; #### - implement these... | 128 ;; #### - implement these... |
112 ;; | 129 ;; |
124 | 141 |
125 ;; only call XListFonts (and parse) once per device. | 142 ;; only call XListFonts (and parse) once per device. |
126 ;; ( (device . [parsed-list-fonts family-menu size-menu weight-menu]) ...) | 143 ;; ( (device . [parsed-list-fonts family-menu size-menu weight-menu]) ...) |
127 (defvar device-fonts-cache nil) | 144 (defvar device-fonts-cache nil) |
128 | 145 |
129 (defconst font-menu-preferred-registry nil) | 146 (defvar font-menu-registry-encoding nil |
130 (defconst font-menu-preferred-resolution nil) | 147 "Registry and encoding to use with font menu fonts.") |
131 | 148 |
132 (defconst fonts-menu-junk-families | 149 (defvar font-menu-preferred-resolution "*-*" |
150 "Preferred horizontal and vertical font menu resolution (e.g. \"75-75\").") | |
151 | |
152 (defvar fonts-menu-junk-families | |
133 (purecopy | 153 (purecopy |
134 (mapconcat | 154 (mapconcat |
135 #'identity | 155 #'identity |
136 '("cursor" "glyph" "symbol" ; Obvious losers. | 156 '("cursor" "glyph" "symbol" ; Obvious losers. |
137 "\\`Ax...\\'" ; FrameMaker fonts - there are just way too | 157 "\\`Ax...\\'" ; FrameMaker fonts - there are just way too |
140 ; "Axcor" -> "Applix Courier Roman", | 160 ; "Axcor" -> "Applix Courier Roman", |
141 ; "Axcob" -> "Applix Courier Bold", etc. | 161 ; "Axcob" -> "Applix Courier Bold", etc. |
142 ) | 162 ) |
143 "\\|")) | 163 "\\|")) |
144 "A regexp matching font families which are uninteresting (e.g. cursor fonts).") | 164 "A regexp matching font families which are uninteresting (e.g. cursor fonts).") |
165 | |
166 (eval-when-compile | |
167 (defsubst device-fonts-cache () | |
168 (or (cdr (assq (selected-device) device-fonts-cache)) | |
169 (reset-device-font-menus (selected-device))))) | |
145 | 170 |
146 (defun hack-font-truename (fn) | 171 (defun hack-font-truename (fn) |
147 "Filter the output of `font-instance-truename' to deal with Japanese fontsets." | 172 "Filter the output of `font-instance-truename' to deal with Japanese fontsets." |
148 (if (string-match "," (font-instance-truename fn)) | 173 (if (string-match "," (font-instance-truename fn)) |
149 (let ((fpnt (nth 8 (split-string (font-instance-name fn) "-"))) | 174 (let ((fpnt (nth 8 (split-string (font-instance-name fn) "-"))) |
159 | 184 |
160 ;;;###autoload | 185 ;;;###autoload |
161 (fset 'install-font-menus 'reset-device-font-menus) | 186 (fset 'install-font-menus 'reset-device-font-menus) |
162 (make-obsolete 'install-font-menus 'reset-device-font-menus) | 187 (make-obsolete 'install-font-menus 'reset-device-font-menus) |
163 | 188 |
164 (defvar x-font-regexp-ja nil | 189 (defvar x-font-regexp-ascii nil |
165 "This is used to filter out fonts that don't work in the locale. | 190 "This is used to filter out font families that can't display ASCII text. |
166 It must be set at run-time.") | 191 It must be set at run-time.") |
167 | 192 |
168 (defun vassoc (key valist) | 193 (defun vassoc (key valist) |
169 "Search VALIST for a vector whose first element is equal to KEY. | 194 "Search VALIST for a vector whose first element is equal to KEY. |
170 See also `assoc'." | 195 See also `assoc'." |
189 (message "Getting list of fonts from server... ") | 214 (message "Getting list of fonts from server... ") |
190 (if (or noninteractive | 215 (if (or noninteractive |
191 (not (or device (setq device (selected-device)))) | 216 (not (or device (setq device (selected-device)))) |
192 (not (eq (device-type device) 'x))) | 217 (not (eq (device-type device) 'x))) |
193 nil | 218 nil |
194 (if (and (getenv "LANG") | 219 (unless x-font-regexp-ascii |
195 (string-match "^\\(ja\\|japanese\\)$" | 220 (setq x-font-regexp-ascii (if (fboundp 'charset-registry) |
196 (getenv "LANG"))) | 221 (charset-registry 'ascii) |
197 ;; #### - this is questionable behavior left over from the I18N4 code. | 222 "iso8859-1"))) |
198 (setq x-font-regexp-ja "jisx[^-]*-[^-]*$" | 223 (setq font-menu-registry-encoding |
199 font-menu-preferred-registry '("*" . "*") | 224 (if (featurep 'mule) "*-*" "iso8859-1")) |
200 font-menu-preferred-resolution '("*" . "*"))) | 225 (let ((case-fold-search t) |
201 (let ((all-fonts nil) | 226 family size weight entry monospaced-p |
202 (case-fold-search t) | 227 dev-cache cache families sizes weights) |
203 name family size weight entry monospaced-p | 228 (dolist (name (cond ((null debug) ; debugging kludge |
204 dev-cache | 229 (list-fonts "*-*-*-*-*-*-*-*-*-*-*-*-*-*" device)) |
205 (cache nil) | 230 ((stringp debug) (split-string debug "\n")) |
206 (families nil) | 231 (t debug))) |
207 (sizes nil) | 232 (when (and (string-match x-font-regexp-ascii name) |
208 (weights nil)) | |
209 (cond ((stringp debug) ; kludge | |
210 (setq all-fonts (split-string debug "\n"))) | |
211 (t | |
212 (setq all-fonts | |
213 (or debug | |
214 (list-fonts "*-*-*-*-*-*-*-*-*-*-*-*-*-*" device))))) | |
215 (while (setq name (pop all-fonts)) | |
216 (when (and (or (not x-font-regexp-ja) | |
217 (string-match x-font-regexp-ja name)) | |
218 (string-match x-font-regexp name)) | 233 (string-match x-font-regexp name)) |
219 (setq weight (capitalize (match-string 1 name)) | 234 (setq weight (capitalize (match-string 1 name)) |
220 size (string-to-int (match-string 6 name))) | 235 size (string-to-int (match-string 6 name))) |
221 (or (string-match x-font-regexp-foundry-and-family name) | 236 (or (string-match x-font-regexp-foundry-and-family name) |
222 (error "internal error")) | 237 (error "internal error")) |
227 (unless (string-match fonts-menu-junk-families family) | 242 (unless (string-match fonts-menu-junk-families family) |
228 (setq entry (or (vassoc family cache) | 243 (setq entry (or (vassoc family cache) |
229 (car (setq cache | 244 (car (setq cache |
230 (cons (vector family nil nil t) | 245 (cons (vector family nil nil t) |
231 cache))))) | 246 cache))))) |
232 (or (member family families) | 247 (or (member family families) (push family families)) |
233 (setq families (cons family families))) | 248 (or (member weight weights) (push weight weights)) |
234 (or (member weight weights) | 249 (or (member size sizes) (push size sizes)) |
235 (setq weights (cons weight weights))) | 250 (or (member weight (aref entry 1)) (push weight (aref entry 1))) |
236 (or (member weight (aref entry 1)) | 251 (or (member size (aref entry 2)) (push size (aref entry 2))) |
237 (aset entry 1 (cons weight (aref entry 1)))) | 252 (aset entry 3 (and (aref entry 3) monospaced-p))))) |
238 (or (member size sizes) | |
239 (setq sizes (cons size sizes))) | |
240 (or (member size (aref entry 2)) | |
241 (aset entry 2 (cons size (aref entry 2)))) | |
242 (aset entry 3 (and (aref entry 3) monospaced-p)) | |
243 ))) | |
244 ;; | 253 ;; |
245 ;; Hack scalable fonts. | 254 ;; Hack scalable fonts. |
246 ;; Some fonts come only in scalable versions (the only size is 0) | 255 ;; Some fonts come only in scalable versions (the only size is 0) |
247 ;; and some fonts come in both scalable and non-scalable versions | 256 ;; and some fonts come in both scalable and non-scalable versions |
248 ;; (one size is 0). If there are any scalable fonts at all, make | 257 ;; (one size is 0). If there are any scalable fonts at all, make |
265 (setq sizes (cons (car common) sizes))) | 274 (setq sizes (cons (car common) sizes))) |
266 (setq common (cdr common))) | 275 (setq common (cdr common))) |
267 (setq sizes (delq 0 sizes)))) | 276 (setq sizes (delq 0 sizes)))) |
268 | 277 |
269 (setq families (sort families 'string-lessp) | 278 (setq families (sort families 'string-lessp) |
270 weights (sort weights 'string-lessp) | 279 weights (sort weights 'string-lessp) |
271 sizes (sort sizes '<)) | 280 sizes (sort sizes '<)) |
272 | 281 |
273 (let ((rest cache)) | 282 (dolist (entry cache) |
274 (while rest | 283 (aset entry 1 (sort (aref entry 1) 'string-lessp)) |
275 (aset (car rest) 1 (sort (aref (car rest) 1) 'string-lessp)) | 284 (aset entry 2 (sort (aref entry 2) '<))) |
276 (aset (car rest) 2 (sort (aref (car rest) 2) '<)) | |
277 (setq rest (cdr rest)))) | |
278 | 285 |
279 (message "Getting list of fonts from server... done.") | 286 (message "Getting list of fonts from server... done.") |
280 | 287 |
281 (setq dev-cache (assq device device-fonts-cache)) | 288 (setq dev-cache (assq device device-fonts-cache)) |
282 (or dev-cache | 289 (or dev-cache |
283 (setq dev-cache (car (push (list device) device-fonts-cache)))) | 290 (setq dev-cache (car (push (list device) device-fonts-cache)))) |
284 (setcdr dev-cache | 291 (setcdr |
285 (vector | 292 dev-cache |
286 cache | 293 (vector |
287 (mapcar #'(lambda (x) | 294 cache |
288 (vector x | 295 (mapcar (lambda (x) |
289 (list 'font-menu-set-font x nil nil) | 296 (vector x |
290 ':style 'radio ':active nil ':selected nil)) | 297 (list 'font-menu-set-font x nil nil) |
291 families) | 298 ':style 'radio ':active nil ':selected nil)) |
292 (mapcar #'(lambda (x) | 299 families) |
293 (vector (if (/= 0 (% x 10)) | 300 (mapcar (lambda (x) |
294 ;; works with no LISP_FLOAT_TYPE | 301 (vector (if (/= 0 (% x 10)) |
295 (concat (int-to-string (/ x 10)) "." | 302 ;; works with no LISP_FLOAT_TYPE |
296 (int-to-string (% x 10))) | 303 (concat (int-to-string (/ x 10)) "." |
297 (int-to-string (/ x 10))) | 304 (int-to-string (% x 10))) |
298 (list 'font-menu-set-font nil nil x) | 305 (int-to-string (/ x 10))) |
299 ':style 'radio ':active nil ':selected nil)) | 306 (list 'font-menu-set-font nil nil x) |
300 sizes) | 307 ':style 'radio ':active nil ':selected nil)) |
301 (mapcar #'(lambda (x) | 308 sizes) |
302 (vector x | 309 (mapcar (lambda (x) |
303 (list 'font-menu-set-font nil x nil) | 310 (vector x |
304 ':style 'radio ':active nil ':selected nil)) | 311 (list 'font-menu-set-font nil x nil) |
305 weights))) | 312 ':style 'radio ':active nil ':selected nil)) |
313 weights))) | |
306 (cdr dev-cache)))) | 314 (cdr dev-cache)))) |
307 | 315 |
308 (defsubst font-menu-truename (face) | 316 ;; Extract font information from a face. We examine both the |
309 (hack-font-truename | 317 ;; user-specified font name and the canonical (`true') font name. |
310 (if (featurep 'mule) | 318 ;; These can appear to have totally different properties. |
311 (face-font-instance face nil 'ascii) | 319 ;; For examples, see the prolog above. |
312 (face-font-instance face)))) | 320 |
313 | 321 ;; We use the user-specified one if possible, else use the truename. |
314 ;;; Extract a font family from a face. | 322 ;; If the user didn't specify one (with "-dt-*-*", for example) |
315 ;;; Use the user-specified one if possible. | 323 ;; get the truename and use the possibly suboptimal data from that. |
316 ;;; If the user didn't specify one (with "*", for example) | 324 (defun* font-menu-font-data (face dcache) |
317 ;;; get the truename and use the guaranteed family from that. | 325 (let* ((case-fold-search t) |
318 (defun font-menu-family (face) | 326 (domain (if font-menu-this-frame-only-p |
319 (let ((dcache (cdr (assq (selected-device) device-fonts-cache))) | 327 (selected-frame) |
320 (name (font-instance-name (face-font-instance face))) | 328 (selected-device))) |
321 (family nil)) | 329 (name (font-instance-name (face-font-instance face domain))) |
330 (truename (font-instance-truename | |
331 (face-font-instance face domain | |
332 (if (featurep 'mule) 'ascii)))) | |
333 family size weight entry slant) | |
322 (when (string-match x-font-regexp-foundry-and-family name) | 334 (when (string-match x-font-regexp-foundry-and-family name) |
323 (setq family (capitalize (match-string 1 name)))) | 335 (setq family (capitalize (match-string 1 name))) |
324 (when (not (and family (vassoc family (aref dcache 0)))) | 336 (setq entry (vassoc family (aref dcache 0)))) |
325 (setq name (font-menu-truename face)) | 337 (when (and (null entry) |
326 (string-match x-font-regexp-foundry-and-family name) | 338 (string-match x-font-regexp-foundry-and-family truename)) |
327 (setq family (capitalize (match-string 1 name)))) | 339 (setq family (capitalize (match-string 1 truename))) |
328 family)) | 340 (setq entry (vassoc family (aref dcache 0)))) |
341 (when (null entry) | |
342 (return-from font-menu-font-data (make-vector 5 nil))) | |
343 | |
344 (when (string-match x-font-regexp name) | |
345 (setq weight (capitalize (match-string 1 name))) | |
346 (setq size (string-to-int (match-string 6 name)))) | |
347 | |
348 (when (string-match x-font-regexp truename) | |
349 (when (not (member weight (aref entry 1))) | |
350 (setq weight (capitalize (match-string 1 truename)))) | |
351 (when (not (member size (aref entry 2))) | |
352 (setq size (string-to-int (match-string 6 truename)))) | |
353 (setq slant (capitalize (match-string 2 truename)))) | |
354 | |
355 (vector entry family size weight slant))) | |
329 | 356 |
330 ;;;###autoload | 357 ;;;###autoload |
331 (defun font-menu-family-constructor (ignored) | 358 (defun font-menu-family-constructor (ignored) |
332 ;; by Stig@hackvan.com | 359 (catch 'menu |
333 (if (not (eq 'x (device-type (selected-device)))) | 360 (unless (eq 'x (device-type (selected-device))) |
334 '(["Cannot parse current font" ding nil]) | 361 (throw 'menu '(["Cannot parse current font" ding nil]))) |
335 (let* ((dcache (cdr (assq (selected-device) device-fonts-cache))) | 362 (let* ((dcache (device-fonts-cache)) |
336 (name (font-menu-truename 'default)) | 363 (font-data (font-menu-font-data 'default dcache)) |
337 (case-fold-search t) | 364 (entry (aref font-data 0)) |
338 family weight size ; parsed from current font | 365 (family (aref font-data 1)) |
339 entry ; font cache entry | 366 (size (aref font-data 2)) |
367 (weight (aref font-data 3)) | |
340 f) | 368 f) |
341 (or dcache | 369 (unless family |
342 (setq dcache (reset-device-font-menus (selected-device)))) | 370 (throw 'menu '(["Cannot parse current font" ding nil]))) |
343 (if (not (string-match x-font-regexp name)) | 371 ;; Items on the Font menu are enabled iff that font exists in |
344 ;; couldn't parse current font | 372 ;; the same size and weight as the current font (scalable fonts |
345 '(["Cannot parse current font" ding nil]) | 373 ;; exist in every size). Only the current font is marked as |
346 (setq weight (capitalize (match-string 1 name))) | 374 ;; selected. |
347 (setq size (string-to-number (match-string 6 name))) | 375 (mapcar |
348 (setq family (font-menu-family 'default)) | 376 (lambda (item) |
349 (setq entry (vassoc family (aref dcache 0))) | 377 (setq f (aref item 0) |
350 (mapcar #'(lambda (item) | 378 entry (vassoc f (aref dcache 0))) |
351 ;; | 379 (if (and (member weight (aref entry 1)) |
352 ;; Items on the Font menu are enabled iff that font | 380 (or (member size (aref entry 2)) |
353 ;; exists in the same size and weight as the current | 381 (and (not font-menu-ignore-scaled-fonts) |
354 ;; font (scalable fonts exist in every size). Only the | 382 (member 0 (aref entry 2))))) |
355 ;; current font is marked as selected. | 383 (enable-menu-item item) |
356 ;; | 384 (disable-menu-item item)) |
357 (setq f (aref item 0) | 385 (if (string-equal family f) |
358 entry (vassoc f (aref dcache 0))) | 386 (select-toggle-menu-item item) |
359 (if (and (member weight (aref entry 1)) | 387 (deselect-toggle-menu-item item)) |
360 (or (member size (aref entry 2)) | 388 item) |
361 (and (not font-menu-ignore-scaled-fonts) | 389 (aref dcache 1))))) |
362 (member 0 (aref entry 2))))) | |
363 (enable-menu-item item) | |
364 (disable-menu-item item)) | |
365 (if (equal family f) | |
366 (select-toggle-menu-item item) | |
367 (deselect-toggle-menu-item item)) | |
368 item) | |
369 (aref dcache 1))) | |
370 ))) | |
371 | 390 |
372 ;;;###autoload | 391 ;;;###autoload |
373 (defun font-menu-size-constructor (ignored) | 392 (defun font-menu-size-constructor (ignored) |
374 ;; by Stig@hackvan.com | 393 (catch 'menu |
375 (if (not (eq 'x (device-type (selected-device)))) | 394 (unless (eq 'x (device-type (selected-device))) |
376 '(["Cannot parse current font" ding nil]) | 395 (throw 'menu '(["Cannot parse current font" ding nil]))) |
377 (let ((dcache (cdr (assq (selected-device) device-fonts-cache))) | 396 (let* ((dcache (device-fonts-cache)) |
378 (name (font-menu-truename 'default)) | 397 (font-data (font-menu-font-data 'default dcache)) |
379 (case-fold-search t) | 398 (entry (aref font-data 0)) |
380 family size ; parsed from current font | 399 (family (aref font-data 1)) |
381 entry ; font cache entry | 400 (size (aref font-data 2)) |
382 s) | 401 ;;(weight (aref font-data 3)) |
383 (or dcache | 402 s) |
384 (setq dcache (reset-device-font-menus (selected-device)))) | 403 (unless family |
385 (if (not (string-match x-font-regexp name)) | 404 (throw 'menu '(["Cannot parse current font" ding nil]))) |
386 ;; couldn't parse current font | 405 ;; Items on the Size menu are enabled iff current font has |
387 '(["Cannot parse current font" ding nil]) | 406 ;; that size. Only the size of the current font is selected. |
388 (setq size (string-to-number (match-string 6 name))) | 407 ;; (If the current font comes in size 0, it is scalable, and |
389 (setq family (font-menu-family 'default)) | 408 ;; thus has every size.) |
390 (setq entry (vassoc family (aref dcache 0))) | 409 (mapcar |
391 (mapcar | 410 (lambda (item) |
392 (lambda (item) | 411 (setq s (nth 3 (aref item 1))) |
393 ;; | 412 (if (or (member s (aref entry 2)) |
394 ;; Items on the Size menu are enabled iff current font has | 413 (and (not font-menu-ignore-scaled-fonts) |
395 ;; that size. Only the size of the current font is | 414 (member 0 (aref entry 2)))) |
396 ;; selected. (If the current font comes in size 0, it is | 415 (enable-menu-item item) |
397 ;; scalable, and thus has every size.) | 416 (disable-menu-item item)) |
398 ;; | 417 (if (eq size s) |
399 (setq s (nth 3 (aref item 1))) | 418 (select-toggle-menu-item item) |
400 (if (or (member s (aref entry 2)) | 419 (deselect-toggle-menu-item item)) |
401 (and (not font-menu-ignore-scaled-fonts) | 420 item) |
402 (member 0 (aref entry 2)))) | 421 (aref dcache 2))))) |
403 (enable-menu-item item) | |
404 (disable-menu-item item)) | |
405 (if (eq size s) | |
406 (select-toggle-menu-item item) | |
407 (deselect-toggle-menu-item item)) | |
408 item) | |
409 (aref dcache 2))) | |
410 ))) | |
411 | 422 |
412 ;;;###autoload | 423 ;;;###autoload |
413 (defun font-menu-weight-constructor (ignored) | 424 (defun font-menu-weight-constructor (ignored) |
414 ;; by Stig@hackvan.com | 425 (catch 'menu |
415 (if (not (eq 'x (device-type (selected-device)))) | 426 (unless (eq 'x (device-type (selected-device))) |
416 '(["Cannot parse current font" ding nil]) | 427 (throw 'menu '(["Cannot parse current font" ding nil]))) |
417 (let ((dcache (cdr (assq (selected-device) device-fonts-cache))) | 428 (let* ((dcache (device-fonts-cache)) |
418 (name (font-menu-truename 'default)) | 429 (font-data (font-menu-font-data 'default dcache)) |
419 (case-fold-search t) | 430 (entry (aref font-data 0)) |
420 family weight ; parsed from current font | 431 (family (aref font-data 1)) |
421 entry ; font cache entry | 432 ;;(size (aref font-data 2)) |
422 w) | 433 (weight (aref font-data 3)) |
423 (or dcache | 434 w) |
424 (setq dcache (reset-device-font-menus (selected-device)))) | 435 (unless family |
425 (if (not (string-match x-font-regexp name)) | 436 (throw 'menu '(["Cannot parse current font" ding nil]))) |
426 ;; couldn't parse current font | 437 ;; Items on the Weight menu are enabled iff current font |
427 '(["Cannot parse current font" ding nil]) | 438 ;; has that weight. Only the weight of the current font |
428 (setq weight (capitalize (match-string 1 name))) | 439 ;; is selected. |
429 (setq family (font-menu-family 'default)) | 440 (mapcar |
430 (setq entry (vassoc family (aref dcache 0))) | 441 (lambda (item) |
431 (mapcar #'(lambda (item) | 442 (setq w (aref item 0)) |
432 ;; Items on the Weight menu are enabled iff current font | 443 (if (member w (aref entry 1)) |
433 ;; has that weight. Only the weight of the current font | 444 (enable-menu-item item) |
434 ;; is selected. | 445 (disable-menu-item item)) |
435 (setq w (aref item 0)) | 446 (if (string-equal weight w) |
436 (if (member w (aref entry 1)) | 447 (select-toggle-menu-item item) |
437 (enable-menu-item item) | 448 (deselect-toggle-menu-item item)) |
438 (disable-menu-item item)) | 449 item) |
439 (if (equal weight w) | 450 (aref dcache 3))))) |
440 (select-toggle-menu-item item) | |
441 (deselect-toggle-menu-item item)) | |
442 item) | |
443 (aref dcache 3))) | |
444 ))) | |
445 | 451 |
446 | 452 |
447 ;;; Changing font sizes | 453 ;;; Changing font sizes |
448 | 454 |
449 (defun font-menu-set-font (family weight size) | 455 (defun font-menu-set-font (family weight size) |
450 ;; This is what gets run when an item is selected from any of the three | 456 ;; This is what gets run when an item is selected from any of the three |
451 ;; fonts menus. It needs to be rather clever. | 457 ;; fonts menus. It needs to be rather clever. |
452 ;; (size is measured in 10ths of points.) | 458 ;; (size is measured in 10ths of points.) |
453 (let ((faces (delq 'default (face-list))) | 459 (let* ((dcache (device-fonts-cache)) |
454 (default-name (font-menu-truename 'default)) | 460 (font-data (font-menu-font-data 'default dcache)) |
455 (case-fold-search t) | 461 (from-family (aref font-data 1)) |
456 new-default-face-font | 462 (from-size (aref font-data 2)) |
457 from-family from-weight from-size) | 463 (from-weight (aref font-data 3)) |
458 ;; | 464 (from-slant (aref font-data 4)) |
459 ;; First, parse out the default face's font. | 465 new-default-face-font) |
460 ;; | 466 (unless from-family |
461 (setq from-family (font-menu-family 'default)) | 467 (signal 'error '("couldn't parse font name for default face"))) |
462 (or (string-match x-font-regexp default-name) | |
463 (signal 'error (list "couldn't parse font name" default-name))) | |
464 (setq from-weight (capitalize (match-string 1 default-name))) | |
465 (setq from-size (match-string 6 default-name)) | |
466 (setq new-default-face-font | 468 (setq new-default-face-font |
467 (font-menu-load-font (or family from-family) | 469 (font-menu-load-font (or family from-family) |
468 (or weight from-weight) | 470 (or weight from-weight) |
469 (or size from-size) | 471 (or size from-size) |
470 default-name)) | 472 from-slant |
471 (while faces | 473 font-menu-preferred-resolution)) |
472 (cond ((face-font-instance (car faces)) | 474 (dolist (face (delq 'default (face-list))) |
473 (message "Changing font of `%s'..." (car faces)) | 475 (when (face-font-instance face) |
474 (condition-case c | 476 (message "Changing font of `%s'..." face) |
475 (font-menu-change-face (car faces) | 477 (condition-case c |
476 from-family from-weight from-size | 478 (font-menu-change-face face |
477 family weight size) | 479 from-family from-weight from-size |
478 (error | 480 family weight size) |
479 (display-error c nil) | 481 (error |
480 (sit-for 1))))) | 482 (display-error c nil) |
481 (setq faces (cdr faces))) | 483 (sit-for 1))))) |
482 ;; Set the default face's font after hacking the other faces, so that | 484 ;; Set the default face's font after hacking the other faces, so that |
483 ;; the frame size doesn't change until we are all done. | 485 ;; the frame size doesn't change until we are all done. |
484 | 486 |
485 ;;; WMP - we need to honor font-menu-this-frame-only-p here! | 487 ;;; WMP - we need to honor font-menu-this-frame-only-p here! |
486 (set-face-font 'default new-default-face-font | 488 (set-face-font 'default new-default-face-font |
490 | 492 |
491 (defun font-menu-change-face (face | 493 (defun font-menu-change-face (face |
492 from-family from-weight from-size | 494 from-family from-weight from-size |
493 to-family to-weight to-size) | 495 to-family to-weight to-size) |
494 (or (symbolp face) (signal 'wrong-type-argument (list 'symbolp face))) | 496 (or (symbolp face) (signal 'wrong-type-argument (list 'symbolp face))) |
495 (let* ((name (font-menu-truename face)) | 497 (let* ((dcache (device-fonts-cache)) |
496 (case-fold-search t) | 498 (font-data (font-menu-font-data face dcache)) |
497 face-family | 499 (face-family (aref font-data 1)) |
498 face-weight | 500 (face-size (aref font-data 2)) |
499 face-size) | 501 (face-weight (aref font-data 3)) |
500 ;; First, parse out the face's font. | 502 (face-slant (aref font-data 4))) |
501 (or (string-match x-font-regexp-foundry-and-family name) | 503 |
502 (signal 'error (list "couldn't parse font name" name))) | 504 (or face-family |
503 (setq face-family (capitalize (match-string 1 name))) | 505 (signal 'error (list "couldn't parse font name for face" face))) |
504 (or (string-match x-font-regexp name) | |
505 (signal 'error (list "couldn't parse font name" name))) | |
506 (setq face-weight (match-string 1 name)) | |
507 (setq face-size (match-string 6 name)) | |
508 | 506 |
509 ;; If this face matches the old default face in the attribute we | 507 ;; If this face matches the old default face in the attribute we |
510 ;; are changing, then change it to the new attribute along that | 508 ;; are changing, then change it to the new attribute along that |
511 ;; dimension. Also, the face must have its own global attribute. | 509 ;; dimension. Also, the face must have its own global attribute. |
512 ;; If its value is inherited, we don't touch it. If any of this | 510 ;; If its value is inherited, we don't touch it. If any of this |
513 ;; is not true, we leave it alone. | 511 ;; is not true, we leave it alone. |
514 (if (and (face-font face 'global) | 512 (when (and (face-font face 'global) |
515 (cond | 513 (cond |
516 (to-family (equal face-family from-family)) | 514 (to-family (string-equal face-family from-family)) |
517 (to-weight (equal face-weight from-weight)) | 515 (to-weight (string-equal face-weight from-weight)) |
518 (to-size (equal face-size from-size)))) | 516 (to-size (= face-size from-size)))) |
519 (set-face-font face | 517 (set-face-font face |
520 (font-menu-load-font (or to-family face-family) | 518 (font-menu-load-font (or to-family face-family) |
521 (or to-weight face-weight) | 519 (or to-weight face-weight) |
522 (or to-size face-size) | 520 (or to-size face-size) |
523 name) | 521 face-slant |
524 (and font-menu-this-frame-only-p | 522 font-menu-preferred-resolution) |
525 (selected-frame))) | 523 (and font-menu-this-frame-only-p |
526 nil))) | 524 (selected-frame)))))) |
527 | 525 |
528 | 526 (defun font-menu-load-font (family weight size slant resolution) |
529 (defun font-menu-load-font (family weight size from-font) | 527 "Try to load a font with the requested properties. |
530 (and (numberp size) (setq size (int-to-string size))) | 528 The weight, slant and resolution are only hints." |
531 (let ((case-fold-search t) | 529 (when (integerp size) (setq size (int-to-string size))) |
532 slant other-slant | 530 (let (font) |
533 registry encoding resx resy) | 531 (catch 'got-font |
534 (or (string-match x-font-regexp-registry-and-encoding from-font) | 532 (dolist (weight (list weight "*")) |
535 (signal 'error (list "couldn't parse font name" from-font))) | 533 (dolist (slant |
536 (setq registry (match-string 1 from-font) | 534 (cond ((string-equal slant "O") '("O" "I" "*")) |
537 encoding (match-string 2 from-font)) | 535 ((string-equal slant "I") '("I" "O" "*")) |
538 | 536 ((string-equal slant "*") '("*")) |
539 (or (string-match x-font-regexp from-font) | 537 (t (list slant "*")))) |
540 (signal 'error (list "couldn't parse font name" from-font))) | 538 (dolist (resolution |
541 (setq slant (capitalize (match-string 2 from-font)) | 539 (if (string-equal resolution "*-*") |
542 resx (match-string 7 from-font) | 540 (list resolution) |
543 resy (match-string 8 from-font)) | 541 (list resolution "*-*"))) |
544 (setq other-slant (cond ((equal slant "O") "I") ; oh, bite me. | 542 (when (setq font |
545 ((equal slant "I") "O") | 543 (make-font-instance |
546 (t nil))) | 544 (concat "-*-" family "-" weight "-" slant "-*-*-*-" |
547 ;; | 545 size "-" resolution "-*-*-" |
548 ;; Remember these values for the first font we switch away from | 546 font-menu-registry-encoding) |
549 ;; (the original default font). | 547 nil t)) |
550 ;; | 548 (throw 'got-font font)))))))) |
551 (or font-menu-preferred-resolution | |
552 (setq font-menu-preferred-resolution (cons resx resy))) | |
553 (or font-menu-preferred-registry | |
554 (setq font-menu-preferred-registry (cons registry encoding))) | |
555 ;; | |
556 ;; Now we know all the interesting properties of the font we want. | |
557 ;; Let's see what we can actually *get*. | |
558 ;; | |
559 (or ;; First try the default resolution, registry, and encoding. | |
560 (make-font-instance | |
561 (concat "-*-" family "-" weight "-" slant "-*-*-*-" size | |
562 "-" (car font-menu-preferred-resolution) | |
563 "-" (cdr font-menu-preferred-resolution) | |
564 "-*-*-" | |
565 (car font-menu-preferred-registry) "-" | |
566 (cdr font-menu-preferred-registry)) | |
567 nil t) | |
568 ;; Then try that in the other slant. | |
569 (and other-slant | |
570 (make-font-instance | |
571 (concat "-*-" family "-" weight "-" other-slant | |
572 "-*-*-*-" size | |
573 "-" (car font-menu-preferred-resolution) | |
574 "-" (cdr font-menu-preferred-resolution) | |
575 "-*-*-" | |
576 (car font-menu-preferred-registry) "-" | |
577 (cdr font-menu-preferred-registry)) | |
578 nil t)) | |
579 ;; Then try the default resolution and registry, any encoding. | |
580 (make-font-instance | |
581 (concat "-*-" family "-" weight "-" slant "-*-*-*-" size | |
582 "-" (car font-menu-preferred-resolution) | |
583 "-" (cdr font-menu-preferred-resolution) | |
584 "-*-*-" | |
585 (car font-menu-preferred-registry) "-*") | |
586 nil t) | |
587 ;; Then try that in the other slant. | |
588 (and other-slant | |
589 (make-font-instance | |
590 (concat "-*-" family "-" weight "-" other-slant | |
591 "-*-*-*-" size | |
592 "-" (car font-menu-preferred-resolution) | |
593 "-" (cdr font-menu-preferred-resolution) | |
594 "-*-*-" | |
595 (car font-menu-preferred-registry) "-*") | |
596 nil t)) | |
597 ;; Then try the default registry and encoding, any resolution. | |
598 (make-font-instance | |
599 (concat "-*-" family "-" weight "-" slant "-*-*-*-" size | |
600 "-*-*-*-*-" | |
601 (car font-menu-preferred-registry) "-" | |
602 (cdr font-menu-preferred-registry)) | |
603 nil t) | |
604 ;; Then try that in the other slant. | |
605 (and other-slant | |
606 (make-font-instance | |
607 (concat "-*-" family "-" weight "-" other-slant | |
608 "-*-*-*-" size | |
609 "-*-*-*-*-" | |
610 (car font-menu-preferred-registry) "-" | |
611 (cdr font-menu-preferred-registry)) | |
612 nil t)) | |
613 ;; Then try the default registry, any encoding or resolution. | |
614 (make-font-instance | |
615 (concat "-*-" family "-" weight "-" slant "-*-*-*-" size | |
616 "-*-*-*-*-" | |
617 (car font-menu-preferred-registry) "-*") | |
618 nil t) | |
619 ;; Then try that in the other slant. | |
620 (and other-slant | |
621 (make-font-instance | |
622 (concat "-*-" family "-" weight "-" slant "-*-*-*-" | |
623 size "-*-*-*-*-" | |
624 (car font-menu-preferred-registry) "-*") | |
625 nil t)) | |
626 ;; Then try anything in the same slant, and error if it fails... | |
627 (and other-slant | |
628 (make-font-instance | |
629 (concat "-*-" family "-" weight "-" slant "-*-*-*-" | |
630 size "-*-*-*-*-*-*"))) | |
631 (make-font-instance | |
632 (concat "-*-" family "-" weight "-" (or other-slant slant) | |
633 "-*-*-*-" size "-*-*-*-*-*-*")) | |
634 ))) | |
635 | 549 |
636 (defun flush-device-fonts-cache (device) | 550 (defun flush-device-fonts-cache (device) |
637 ;; by Stig@hackvan.com | 551 ;; by Stig@hackvan.com |
638 (let ((elt (assq device device-fonts-cache))) | 552 (let ((elt (assq device device-fonts-cache))) |
639 (and elt | 553 (and elt |