0
|
1 ;; x-font-menu.el --- Managing menus of X fonts.
|
|
2
|
|
3 ;; Copyright (C) 1994 Free Software Foundation, Inc.
|
|
4 ;; Copyright (C) 1995 Tinker Systems and INS Engineering Corp.
|
|
5
|
|
6 ;; Author: Jamie Zawinski <jwz@lucid.com>
|
|
7 ;; Restructured by: Jonathan Stigelman <Stig@hackvan.com>
|
|
8
|
|
9 ;; This file is part of XEmacs.
|
|
10
|
|
11 ;; 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
|
|
13 ;; the Free Software Foundation; either version 2, or (at your option)
|
|
14 ;; any later version.
|
|
15
|
|
16 ;; XEmacs is distributed in the hope that it will be useful, but
|
|
17 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
19 ;; General Public License for more details.
|
|
20
|
|
21 ;; You should have received a copy of the GNU General Public License
|
|
22 ;; along with XEmacs; see the file COPYING. If not, write to the Free
|
|
23 ;; Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
24
|
|
25 ;;; Commentary:
|
|
26 ;;;
|
|
27 ;;; Creates three menus, "Font", "Size", and "Weight", and puts them on the
|
|
28 ;;; "Options" menu. The contents of these menus are the superset of those
|
|
29 ;;; properties available on any fonts, but only the intersection of the three
|
|
30 ;;; sets is selectable at one time.
|
|
31 ;;;
|
|
32 ;;; Known Problems:
|
|
33 ;;; ===============
|
|
34 ;;; Items on the Font menu are selectable if and only if that font exists in
|
|
35 ;;; the same size and weight as the current font. This means that some fonts
|
|
36 ;;; are simply not reachable from some other fonts - if only one font comes
|
|
37 ;;; in only one point size (like "Nil", which comes only in 2), you will never
|
|
38 ;;; be able to select it. It would be better if the items on the Fonts menu
|
|
39 ;;; were always selectable, and selecting them would set the size to be the
|
|
40 ;;; closest size to the current font's size.
|
|
41 ;;;
|
|
42 ;;; This attempts to change all other faces in an analagous way to the change
|
|
43 ;;; that was made to the default face; if it can't, it will skip over the face.
|
|
44 ;;; However, this could leave incongruous font sizes around, which may cause
|
|
45 ;;; some nonreversibility problems if further changes are made. Perhaps it
|
|
46 ;;; should remember the initial fonts of all faces, and derive all subsequent
|
|
47 ;;; fonts from that initial state.
|
|
48 ;;;
|
|
49 ;;; xfontsel(1) is a lot more flexible (but probably harder to understand).
|
|
50 ;;;
|
|
51 ;;; The code to construct menus from all of the x11 fonts available from the
|
|
52 ;;; server is autoloaded and executed the very first time that one of the Font
|
|
53 ;;; menus is selected on each device. That is, if XEmacs has frames on two
|
|
54 ;;; different devices, then separate font menu information will be maintained
|
|
55 ;;; for each X display. If the font path changes after emacs has already
|
|
56 ;;; asked the X server on a particular display for its list of fonts, this
|
|
57 ;;; won't notice. Also, the first time that a font menu is posted on each
|
|
58 ;;; display will entail a lengthy delay, but that's better than slowing down
|
|
59 ;;; XEmacs startup. At any time (i.e.: after a font-path change or
|
|
60 ;;; immediately after device creation), you can call
|
|
61 ;;; `reset-device-font-menus' to rebuild the menus from all currently
|
|
62 ;;; available fonts.
|
|
63 ;;;
|
|
64 ;;; There is knowledge here about the regexp match numbers in `x-font-regexp',
|
|
65 ;;; `x-font-regexp-foundry-and-family', and
|
|
66 ;;; `x-font-regexp-registry-and-encoding' defined in x-faces.el.
|
|
67 ;;;
|
|
68 ;;; There are at least three kinds of fonts under X11r5:
|
|
69 ;;;
|
|
70 ;;; - bitmap fonts, which can be assumed to look as good as possible;
|
|
71 ;;; - bitmap fonts which have been (or can be) automatically scaled to
|
|
72 ;;; a new size, and which almost always look awful;
|
2
|
73 ;;; - and true outline fonts, which should look ok at any size, but in
|
0
|
74 ;;; practice (on at least some systems) look awful at any size, and
|
|
75 ;;; even in theory are unlikely ever to look as good as non-scaled
|
|
76 ;;; bitmap fonts.
|
|
77 ;;;
|
|
78 ;;; It would be nice to get this code to look for non-scaled bitmap fonts
|
|
79 ;;; first, then outline fonts, then scaled bitmap fonts as a last resort.
|
|
80 ;;; But it's not clear to me how to tell them apart based on their truenames
|
|
81 ;;; and/or the result of XListFonts(). I welcome any and all explanations
|
|
82 ;;; of the subtleties involved...
|
|
83 ;;;
|
|
84 ;;;
|
|
85 ;;; If You Think You'Re Seeing A Bug:
|
|
86 ;;; =================================
|
|
87 ;;; When reporting problems, send the following information:
|
|
88 ;;;
|
|
89 ;;; - Exactly what behavior you're seeing;
|
|
90 ;;; - The output of the `xlsfonts' program;
|
|
91 ;;; - The value of the variable `fonts-menu-cache';
|
|
92 ;;; - The values of the following expressions, both before and after
|
|
93 ;;; making a selection from any of the fonts-related menus:
|
|
94 ;;; (face-font 'default)
|
|
95 ;;; (font-instance-truename (face-font 'default))
|
|
96 ;;; (font-instance-properties (face-font 'default))
|
|
97 ;;; - The values of the following variables after making a selection:
|
|
98 ;;; font-menu-preferred-resolution
|
|
99 ;;; font-menu-preferred-registry
|
|
100 ;;;
|
|
101 ;;; There is a common misconception that "*-courier-medium-r-*-11-*", also
|
|
102 ;;; known as "-adobe-courier-medium-r-normal--11-80-100-100-m-60-iso8859-1",
|
|
103 ;;; is an 11-point font. It is not -- it is an 11-pixel font at 100dpi,
|
|
104 ;;; which is an 8-point font (the number after -11- is the size in tenths
|
|
105 ;;; of points). So if you expect to be seeing an "11" entry in the "Size"
|
|
106 ;;; menu and are not, this may be why.
|
|
107
|
|
108 ;;; Code:
|
|
109
|
|
110 ;; #### - implement these...
|
|
111 ;;
|
|
112 ;;; (defvar font-menu-ignore-proportional-fonts nil
|
|
113 ;;; "*If non-nil, then the font menu will only show fixed-width fonts.")
|
|
114
|
|
115 ;;;###autoload
|
|
116 (defvar font-menu-ignore-scaled-fonts t
|
|
117 "*If non-nil, then the font menu will try to show only bitmap fonts.")
|
|
118
|
|
119 ;;;###autoload
|
10
|
120 (defvar font-menu-this-frame-only-p nil
|
0
|
121 "*If non-nil, then changing the default font from the font menu will only
|
|
122 affect one frame instead of all frames.")
|
|
123
|
|
124 ;; only call XListFonts (and parse) once per device.
|
|
125 ;; ( (device . [parsed-list-fonts family-menu size-menu weight-menu]) ...)
|
|
126 (defvar device-fonts-cache nil)
|
|
127
|
|
128 (defconst font-menu-preferred-registry nil)
|
|
129 (defconst font-menu-preferred-resolution nil)
|
|
130
|
|
131 (defconst fonts-menu-junk-families
|
|
132 (purecopy
|
|
133 (mapconcat
|
|
134 #'identity
|
|
135 '("cursor" "glyph" "symbol" ; Obvious losers.
|
|
136 "\\`Ax...\\'" ; FrameMaker fonts - there are just way too
|
|
137 ; many of these, and there is a different
|
|
138 ; font family for each font face! Losers.
|
|
139 ; "Axcor" -> "Applix Courier Roman",
|
|
140 ; "Axcob" -> "Applix Courier Bold", etc.
|
|
141 )
|
|
142 "\\|"))
|
|
143 "A regexp matching font families which are uninteresting (cursor fonts).")
|
|
144
|
|
145 (defun hack-font-truename (fn)
|
|
146 "Filter the output of `font-instance-truename' to deal with Japanese fontsets."
|
|
147 (if (string-match "," (font-instance-truename fn))
|
|
148 (let ((fpnt (nth 8 (split-string (font-instance-name fn) "-")))
|
|
149 (flist (split-string (font-instance-truename fn) ","))
|
|
150 ret)
|
|
151 (while flist
|
|
152 (if (string-equal fpnt (nth 8 (split-string (car flist) "-")))
|
|
153 (progn (setq ret (car flist)) (setq flist nil))
|
|
154 (setq flist (cdr flist))
|
|
155 ))
|
|
156 ret)
|
|
157 (font-instance-truename fn)))
|
|
158
|
|
159 ;;;###autoload
|
|
160 (fset 'install-font-menus 'reset-device-font-menus)
|
|
161 (make-obsolete 'install-font-menus 'reset-device-font-menus)
|
|
162
|
|
163 (defvar x-font-regexp-ja nil
|
|
164 "This is used to filter out fonts that don't work in the locale.
|
|
165 It must be set at run-time.")
|
|
166
|
|
167 (defun vassoc (key valist)
|
|
168 "Search VALIST for a vector whose first element is equal to KEY.
|
|
169 See also `assoc'."
|
|
170 ;; by Stig@hackvan.com
|
|
171 (let (el)
|
|
172 (catch 'done
|
|
173 (while (setq el (pop valist))
|
|
174 (and (equal key (aref el 0))
|
|
175 (throw 'done el))))))
|
|
176
|
|
177 ;;;###autoload
|
|
178 (defun reset-device-font-menus (&optional device debug)
|
|
179 "Generates the `Font', `Size', and `Weight' submenus for the Options menu.
|
|
180 This is run the first time that a font-menu is needed for each device.
|
|
181 If you don't like the lazy invocation of this function, you can add it to
|
|
182 `create-device-hook' and that will make the font menus respond more quickly
|
|
183 when they are selected for the first time. If you add fonts to your system,
|
|
184 or if you change your font path, you can call this to re-initialize the menus."
|
|
185 ;; by Stig@hackvan.com
|
|
186 ;; #### - this should implement a `menus-only' option, which would
|
|
187 ;; recalculate the menus from the cache w/o having to do list-fonts again.
|
|
188 (message "Getting list of fonts from server... ")
|
|
189 (if (or noninteractive
|
|
190 (not (or device (setq device (selected-device))))
|
|
191 (not (eq (device-type device) 'x)))
|
|
192 nil
|
|
193 (if (and (getenv "LANG")
|
|
194 (string-match "^\\(ja\\|japanese\\)$"
|
|
195 (getenv "LANG")))
|
|
196 ;; #### - this is questionable behavior left over from the I18N4 code.
|
|
197 (setq x-font-regexp-ja "jisx[^-]*-[^-]*$"
|
|
198 font-menu-preferred-registry '("*" . "*")))
|
|
199 (let ((all-fonts nil)
|
|
200 (case-fold-search t)
|
|
201 name family size weight entry monospaced-p
|
|
202 dev-cache
|
|
203 (cache nil)
|
|
204 (families nil)
|
|
205 (sizes nil)
|
|
206 (weights nil))
|
|
207 (cond ((stringp debug) ; kludge
|
|
208 (setq all-fonts (split-string debug "\n")))
|
|
209 (t
|
|
210 (setq all-fonts
|
|
211 (or debug
|
|
212 (list-fonts "*-*-*-*-*-*-*-*-*-*-*-*-*-*" device)))))
|
|
213 (while (setq name (pop all-fonts))
|
|
214 (cond ((and (or (not x-font-regexp-ja)
|
|
215 (string-match x-font-regexp-ja name))
|
|
216 (string-match x-font-regexp name))
|
|
217 (setq weight (capitalize (match-string 1 name))
|
|
218 size (string-to-int (match-string 6 name)))
|
|
219 (or (string-match x-font-regexp-foundry-and-family name)
|
|
220 (error "internal error"))
|
|
221 (setq family (capitalize (match-string 1 name)))
|
|
222 (or (string-match x-font-regexp-spacing name)
|
|
223 (error "internal error"))
|
|
224 (setq monospaced-p (string= "m" (match-string 1 name)))
|
|
225 (if (string-match fonts-menu-junk-families family)
|
|
226 nil
|
|
227 (setq entry (or (vassoc family cache)
|
|
228 (car (setq cache
|
|
229 (cons (vector family nil nil t)
|
|
230 cache)))))
|
|
231 (or (member family families)
|
|
232 (setq families (cons family families)))
|
|
233 (or (member weight weights)
|
|
234 (setq weights (cons weight weights)))
|
|
235 (or (member weight (aref entry 1))
|
|
236 (aset entry 1 (cons weight (aref entry 1))))
|
|
237 (or (member size sizes)
|
|
238 (setq sizes (cons size sizes)))
|
|
239 (or (member size (aref entry 2))
|
|
240 (aset entry 2 (cons size (aref entry 2))))
|
|
241 (aset entry 3 (and (aref entry 3) monospaced-p))
|
|
242 ))))
|
|
243 ;;
|
|
244 ;; Hack scalable fonts.
|
|
245 ;; Some fonts come only in scalable versions (the only size is 0)
|
|
246 ;; and some fonts come in both scalable and non-scalable versions
|
|
247 ;; (one size is 0). If there are any scalable fonts at all, make
|
|
248 ;; sure that the union of all point sizes contains at least some
|
|
249 ;; common sizes - it's possible that some sensible sizes might end
|
|
250 ;; up not getting mentioned explicitly.
|
|
251 ;;
|
|
252 (if (member 0 sizes)
|
|
253 (let ((common '(60 80 100 120 140 160 180 240)))
|
|
254 (while common
|
|
255 (or;;(member (car common) sizes) ; not enough slack
|
|
256 (let ((rest sizes)
|
|
257 (done nil))
|
|
258 (while (and (not done) rest)
|
|
259 (if (and (> (car common) (- (car rest) 5))
|
|
260 (< (car common) (+ (car rest) 5)))
|
|
261 (setq done t))
|
|
262 (setq rest (cdr rest)))
|
|
263 done)
|
|
264 (setq sizes (cons (car common) sizes)))
|
|
265 (setq common (cdr common)))
|
|
266 (setq sizes (delq 0 sizes))))
|
|
267
|
|
268 (setq families (sort families 'string-lessp)
|
|
269 weights (sort weights 'string-lessp)
|
|
270 sizes (sort sizes '<))
|
|
271
|
|
272 (let ((rest cache))
|
|
273 (while rest
|
|
274 (aset (car rest) 1 (sort (aref (car rest) 1) 'string-lessp))
|
|
275 (aset (car rest) 2 (sort (aref (car rest) 2) '<))
|
|
276 (setq rest (cdr rest))))
|
|
277
|
|
278 (message "Getting list of fonts from server... done.")
|
|
279
|
|
280 (setq dev-cache (assq device device-fonts-cache))
|
|
281 (or dev-cache
|
|
282 (setq dev-cache (car (push (list device) device-fonts-cache))))
|
|
283 (setcdr dev-cache
|
|
284 (vector
|
|
285 cache
|
|
286 (mapcar #'(lambda (x)
|
|
287 (vector x
|
|
288 (list 'font-menu-set-font x nil nil)
|
|
289 ':style 'radio ':active nil ':selected nil))
|
|
290 families)
|
|
291 (mapcar #'(lambda (x)
|
|
292 (vector (if (/= 0 (% x 10))
|
|
293 ;; works with no LISP_FLOAT_TYPE
|
|
294 (concat (int-to-string (/ x 10)) "."
|
|
295 (int-to-string (% x 10)))
|
|
296 (int-to-string (/ x 10)))
|
|
297 (list 'font-menu-set-font nil nil x)
|
|
298 ':style 'radio ':active nil ':selected nil))
|
|
299 sizes)
|
|
300 (mapcar #'(lambda (x)
|
|
301 (vector x
|
|
302 (list 'font-menu-set-font nil x nil)
|
|
303 ':style 'radio ':active nil ':selected nil))
|
|
304 weights)))
|
|
305 (cdr dev-cache))))
|
|
306
|
|
307 ;;;###autoload
|
|
308 (defun font-menu-family-constructor (ignored)
|
|
309 ;; by Stig@hackvan.com
|
|
310 (if (not (eq 'x (device-type (selected-device))))
|
|
311 '(["Cannot parse current font" ding nil])
|
|
312 (let ((dcache (cdr (assq (selected-device) device-fonts-cache)))
|
|
313 (name (hack-font-truename (face-font-instance 'default)))
|
|
314 (case-fold-search t)
|
|
315 family weight size ; parsed from current font
|
|
316 entry ; font cache entry
|
|
317 f)
|
|
318 (or dcache
|
|
319 (setq dcache (reset-device-font-menus (selected-device))))
|
|
320 (if (not (string-match x-font-regexp name))
|
|
321 ;; couldn't parse current font
|
|
322 '(["Cannot parse current font" ding nil])
|
|
323 (setq weight (capitalize (match-string 1 name)))
|
|
324 (setq size (string-to-number (match-string 6 name)))
|
|
325 (and (string-match x-font-regexp-foundry-and-family name)
|
|
326 (setq family (capitalize (match-string 1 name))))
|
|
327 (setq entry (vassoc family (aref dcache 0)))
|
|
328 (mapcar #'(lambda (item)
|
|
329 ;;
|
|
330 ;; Items on the Font menu are enabled iff that font
|
|
331 ;; exists in the same size and weight as the current
|
|
332 ;; font (scalable fonts exist in every size). Only the
|
|
333 ;; current font is marked as selected.
|
|
334 ;;
|
|
335 (setq f (aref item 0)
|
|
336 entry (vassoc f (aref dcache 0)))
|
|
337 (if (and (member weight (aref entry 1))
|
|
338 (or (member size (aref entry 2))
|
|
339 (and (not font-menu-ignore-scaled-fonts)
|
|
340 (member 0 (aref entry 2)))))
|
|
341 (enable-menu-item item)
|
|
342 (disable-menu-item item))
|
|
343 (if (equal family f)
|
|
344 (select-toggle-menu-item item)
|
|
345 (deselect-toggle-menu-item item))
|
|
346 item)
|
|
347 (aref dcache 1)))
|
|
348 )))
|
|
349
|
|
350 ;;;###autoload
|
|
351 (defun font-menu-size-constructor (ignored)
|
|
352 ;; by Stig@hackvan.com
|
|
353 (if (not (eq 'x (device-type (selected-device))))
|
|
354 '(["Cannot parse current font" ding nil])
|
|
355 (let ((dcache (cdr (assq (selected-device) device-fonts-cache)))
|
|
356 (name (hack-font-truename (face-font-instance 'default)))
|
|
357 (case-fold-search t)
|
|
358 family size ; parsed from current font
|
|
359 entry ; font cache entry
|
|
360 s)
|
|
361 (or dcache
|
|
362 (setq dcache (reset-device-font-menus (selected-device))))
|
|
363 (if (not (string-match x-font-regexp name))
|
|
364 ;; couldn't parse current font
|
|
365 '(["Cannot parse current font" ding nil])
|
|
366 (setq size (string-to-number (match-string 6 name)))
|
|
367 (and (string-match x-font-regexp-foundry-and-family name)
|
|
368 (setq family (capitalize (match-string 1 name))))
|
|
369 (setq entry (vassoc family (aref dcache 0)))
|
2
|
370 (mapcar
|
|
371 (lambda (item)
|
|
372 ;;
|
|
373 ;; Items on the Size menu are enabled iff current font has
|
|
374 ;; that size. Only the size of the current font is
|
|
375 ;; selected. (If the current font comes in size 0, it is
|
|
376 ;; scalable, and thus has every size.)
|
|
377 ;;
|
|
378 (setq s (nth 3 (aref item 1)))
|
|
379 (if (or (member s (aref entry 2))
|
|
380 (and (not font-menu-ignore-scaled-fonts)
|
|
381 (member 0 (aref entry 2))))
|
|
382 (enable-menu-item item)
|
|
383 (disable-menu-item item))
|
|
384 (if (eq size s)
|
|
385 (select-toggle-menu-item item)
|
|
386 (deselect-toggle-menu-item item))
|
|
387 item)
|
|
388 (aref dcache 2)))
|
0
|
389 )))
|
|
390
|
|
391 ;;;###autoload
|
|
392 (defun font-menu-weight-constructor (ignored)
|
|
393 ;; by Stig@hackvan.com
|
|
394 (if (not (eq 'x (device-type (selected-device))))
|
|
395 '(["Cannot parse current font" ding nil])
|
|
396 (let ((dcache (cdr (assq (selected-device) device-fonts-cache)))
|
|
397 (name (hack-font-truename (face-font-instance 'default)))
|
|
398 (case-fold-search t)
|
|
399 family weight ; parsed from current font
|
|
400 entry ; font cache entry
|
|
401 w)
|
|
402 (or dcache
|
|
403 (setq dcache (reset-device-font-menus (selected-device))))
|
|
404 (if (not (string-match x-font-regexp name))
|
|
405 ;; couldn't parse current font
|
|
406 '(["Cannot parse current font" ding nil])
|
|
407 (setq weight (capitalize (match-string 1 name)))
|
|
408 (and (string-match x-font-regexp-foundry-and-family name)
|
|
409 (setq family (capitalize (match-string 1 name))))
|
|
410 (setq entry (vassoc family (aref dcache 0)))
|
|
411 (mapcar #'(lambda (item)
|
|
412 ;;
|
|
413 ;; Items on the Weight menu are enabled iff current font
|
|
414 ;; has that weight. Only the weight of the current font
|
|
415 ;; is selected.
|
|
416 ;;
|
|
417 (setq w (aref item 0))
|
|
418 (if (member w (aref entry 1))
|
|
419 (enable-menu-item item)
|
|
420 (disable-menu-item item))
|
|
421 (if (equal weight w)
|
|
422 (select-toggle-menu-item item)
|
|
423 (deselect-toggle-menu-item item))
|
|
424 item)
|
|
425 (aref dcache 3)))
|
|
426 )))
|
|
427
|
|
428
|
|
429 ;;; Changing font sizes
|
|
430
|
|
431 (defun font-menu-set-font (family weight size)
|
|
432 ;; This is what gets run when an item is selected from any of the three
|
|
433 ;; fonts menus. It needs to be rather clever.
|
|
434 ;; (size is measured in 10ths of points.)
|
|
435 (let ((faces (delq 'default (face-list)))
|
|
436 (default-name (hack-font-truename (face-font-instance 'default)))
|
|
437 (case-fold-search t)
|
|
438 new-default-face-font
|
|
439 from-family from-weight from-size)
|
|
440 ;;
|
|
441 ;; First, parse out the default face's font.
|
|
442 ;;
|
|
443 (or (string-match x-font-regexp-foundry-and-family default-name)
|
|
444 (signal 'error (list "couldn't parse font name" default-name)))
|
|
445 (setq from-family (capitalize (match-string 1 default-name)))
|
|
446 (or (string-match x-font-regexp default-name)
|
|
447 (signal 'error (list "couldn't parse font name" default-name)))
|
|
448 (setq from-weight (capitalize (match-string 1 default-name)))
|
|
449 (setq from-size (match-string 6 default-name))
|
|
450 (setq new-default-face-font
|
|
451 (font-menu-load-font (or family from-family)
|
|
452 (or weight from-weight)
|
|
453 (or size from-size)
|
|
454 default-name))
|
4
|
455 (setq save-options-font-hack (list 'font-menu-set-font
|
|
456 (or family from-family)
|
|
457 (or weight from-weight)
|
|
458 (or size from-size)))
|
0
|
459 (while faces
|
|
460 (cond ((face-font-instance (car faces))
|
|
461 (message "Changing font of `%s'..." (car faces))
|
|
462 (condition-case c
|
|
463 (font-menu-change-face (car faces)
|
|
464 from-family from-weight from-size
|
|
465 family weight size)
|
|
466 (error
|
|
467 (display-error c nil)
|
|
468 (sit-for 1)))))
|
|
469 (setq faces (cdr faces)))
|
|
470 ;; Set the default face's font after hacking the other faces, so that
|
|
471 ;; the frame size doesn't change until we are all done.
|
|
472
|
|
473 ;;; WMP - we need to honor font-menu-this-frame-only-p here!
|
|
474 (set-face-font 'default new-default-face-font
|
|
475 (and font-menu-this-frame-only-p (selected-frame)))
|
|
476 (message "Font %s" (face-font-name 'default))))
|
|
477
|
|
478
|
|
479 (defun font-menu-change-face (face
|
|
480 from-family from-weight from-size
|
|
481 to-family to-weight to-size)
|
|
482 (or (symbolp face) (signal 'wrong-type-argument (list 'symbolp face)))
|
|
483 (let* ((font (face-font-instance face))
|
|
484 (name (hack-font-truename font))
|
|
485 (case-fold-search t)
|
|
486 face-family
|
|
487 face-weight
|
|
488 face-size)
|
|
489 ;; First, parse out the face's font.
|
|
490 (or (string-match x-font-regexp-foundry-and-family name)
|
|
491 (signal 'error (list "couldn't parse font name" name)))
|
|
492 (setq face-family (capitalize (match-string 1 name)))
|
|
493 (or (string-match x-font-regexp name)
|
|
494 (signal 'error (list "couldn't parse font name" name)))
|
|
495 (setq face-weight (match-string 1 name))
|
|
496 (setq face-size (match-string 6 name))
|
|
497
|
|
498 ;; If this face matches the old default face in the attribute we
|
|
499 ;; are changing, then change it to the new attribute along that
|
|
500 ;; dimension. Also, the face must have its own global attribute.
|
|
501 ;; If its value is inherited, we don't touch it. If any of this
|
|
502 ;; is not true, we leave it alone.
|
|
503 (if (and (face-font face 'global)
|
|
504 (cond
|
|
505 (to-family (equal face-family from-family))
|
|
506 (to-weight (equal face-weight from-weight))
|
|
507 (to-size (equal face-size from-size))))
|
|
508 (set-face-font face
|
|
509 (font-menu-load-font (or to-family face-family)
|
|
510 (or to-weight face-weight)
|
|
511 (or to-size face-size)
|
|
512 name)
|
|
513 (and font-menu-this-frame-only-p
|
|
514 (selected-frame)))
|
|
515 nil)))
|
|
516
|
|
517
|
|
518 (defun font-menu-load-font (family weight size from-font)
|
|
519 (and (numberp size) (setq size (int-to-string size)))
|
|
520 (let ((case-fold-search t)
|
|
521 slant other-slant
|
|
522 registry encoding resx resy)
|
|
523 (or (string-match x-font-regexp-registry-and-encoding from-font)
|
|
524 (signal 'error (list "couldn't parse font name" from-font)))
|
|
525 (setq registry (match-string 1 from-font)
|
|
526 encoding (match-string 2 from-font))
|
|
527
|
|
528 (or (string-match x-font-regexp from-font)
|
|
529 (signal 'error (list "couldn't parse font name" from-font)))
|
|
530 (setq slant (capitalize (match-string 2 from-font))
|
|
531 resx (match-string 7 from-font)
|
|
532 resy (match-string 8 from-font))
|
|
533 (cond ((equal slant "O") (setq other-slant "I")) ; oh, bite me.
|
|
534 ((equal slant "I") (setq other-slant "O"))
|
|
535 (t (setq other-slant nil)))
|
|
536 ;;
|
|
537 ;; Remember these values for the first font we switch away from
|
|
538 ;; (the original default font).
|
|
539 ;;
|
|
540 (or font-menu-preferred-resolution
|
|
541 (setq font-menu-preferred-resolution (cons resx resy)))
|
|
542 (or font-menu-preferred-registry
|
|
543 (setq font-menu-preferred-registry (cons registry encoding)))
|
|
544 ;;
|
|
545 ;; Now we know all the interesting properties of the font we want.
|
|
546 ;; Let's see what we can actually *get*.
|
|
547 ;;
|
|
548 (or ;; First try the default resolution, registry, and encoding.
|
|
549 (make-font-instance
|
|
550 (concat "-*-" family "-" weight "-" slant "-*-*-*-" size
|
|
551 "-" (car font-menu-preferred-resolution)
|
|
552 "-" (cdr font-menu-preferred-resolution)
|
|
553 "-*-*-"
|
|
554 (car font-menu-preferred-registry) "-"
|
|
555 (cdr font-menu-preferred-registry))
|
|
556 nil t)
|
|
557 ;; Then try that in the other slant.
|
|
558 (and other-slant
|
|
559 (make-font-instance
|
|
560 (concat "-*-" family "-" weight "-" other-slant
|
|
561 "-*-*-*-" 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 the default resolution and registry, any encoding.
|
|
569 (make-font-instance
|
|
570 (concat "-*-" family "-" weight "-" slant "-*-*-*-" size
|
|
571 "-" (car font-menu-preferred-resolution)
|
|
572 "-" (cdr font-menu-preferred-resolution)
|
|
573 "-*-*-"
|
|
574 (car font-menu-preferred-registry) "-*")
|
|
575 nil t)
|
|
576 ;; Then try that in the other slant.
|
|
577 (and other-slant
|
|
578 (make-font-instance
|
|
579 (concat "-*-" family "-" weight "-" other-slant
|
|
580 "-*-*-*-" size
|
|
581 "-" (car font-menu-preferred-resolution)
|
|
582 "-" (cdr font-menu-preferred-resolution)
|
|
583 "-*-*-"
|
|
584 (car font-menu-preferred-registry) "-*")
|
|
585 nil t))
|
|
586 ;; Then try the default registry and encoding, any resolution.
|
|
587 (make-font-instance
|
|
588 (concat "-*-" family "-" weight "-" slant "-*-*-*-" size
|
|
589 "-*-*-*-*-"
|
|
590 (car font-menu-preferred-registry) "-"
|
|
591 (cdr font-menu-preferred-registry))
|
|
592 nil t)
|
|
593 ;; Then try that in the other slant.
|
|
594 (and other-slant
|
|
595 (make-font-instance
|
|
596 (concat "-*-" family "-" weight "-" other-slant
|
|
597 "-*-*-*-" size
|
|
598 "-*-*-*-*-"
|
|
599 (car font-menu-preferred-registry) "-"
|
|
600 (cdr font-menu-preferred-registry))
|
|
601 nil t))
|
|
602 ;; Then try the default registry, any encoding or resolution.
|
|
603 (make-font-instance
|
|
604 (concat "-*-" family "-" weight "-" slant "-*-*-*-" size
|
|
605 "-*-*-*-*-"
|
|
606 (car font-menu-preferred-registry) "-*")
|
|
607 nil t)
|
|
608 ;; Then try that in the other slant.
|
|
609 (and other-slant
|
|
610 (make-font-instance
|
|
611 (concat "-*-" family "-" weight "-" slant "-*-*-*-"
|
|
612 size "-*-*-*-*-"
|
|
613 (car font-menu-preferred-registry) "-*")
|
|
614 nil t))
|
|
615 ;; Then try anything in the same slant, and error if it fails...
|
|
616 (and other-slant
|
|
617 (make-font-instance
|
|
618 (concat "-*-" family "-" weight "-" slant "-*-*-*-"
|
|
619 size "-*-*-*-*-*-*")))
|
|
620 (make-font-instance
|
|
621 (concat "-*-" family "-" weight "-" (or other-slant slant)
|
|
622 "-*-*-*-" size "-*-*-*-*-*-*"))
|
|
623 )))
|
|
624
|
|
625 (defun flush-device-fonts-cache (device)
|
|
626 ;; by Stig@hackvan.com
|
|
627 (let ((elt (assq device device-fonts-cache)))
|
|
628 (and elt
|
|
629 (setq device-fonts-cache (delq elt device-fonts-cache)))))
|
|
630
|
|
631 (add-hook 'delete-device-hook 'flush-device-fonts-cache)
|
|
632
|
|
633 (provide 'x-font-menu)
|
|
634
|
|
635 ;;; x-font-menu.el ends here
|