428
|
1 /* X-specific Lisp objects.
|
|
2 Copyright (C) 1993, 1994 Free Software Foundation, Inc.
|
|
3 Copyright (C) 1995 Board of Trustees, University of Illinois.
|
|
4 Copyright (C) 1995 Tinker Systems.
|
2367
|
5 Copyright (C) 1995, 1996, 2000, 2001, 2002, 2004 Ben Wing.
|
428
|
6 Copyright (C) 1995 Sun Microsystems, Inc.
|
|
7
|
|
8 This file is part of XEmacs.
|
|
9
|
|
10 XEmacs is free software; you can redistribute it and/or modify it
|
|
11 under the terms of the GNU General Public License as published by the
|
|
12 Free Software Foundation; either version 2, or (at your option) any
|
|
13 later version.
|
|
14
|
|
15 XEmacs is distributed in the hope that it will be useful, but WITHOUT
|
|
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
18 for more details.
|
|
19
|
|
20 You should have received a copy of the GNU General Public License
|
|
21 along with XEmacs; see the file COPYING. If not, write to
|
|
22 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
23 Boston, MA 02111-1307, USA. */
|
|
24
|
|
25 /* Synched up with: Not in FSF. */
|
|
26
|
|
27 /* Authors: Jamie Zawinski, Chuck Thompson, Ben Wing */
|
|
28
|
442
|
29 /* This file Mule-ized by Ben Wing, 7-10-00. */
|
|
30
|
428
|
31 #include <config.h>
|
|
32 #include "lisp.h"
|
|
33
|
872
|
34 #include "charset.h"
|
|
35 #include "device-impl.h"
|
|
36 #include "insdel.h"
|
428
|
37
|
872
|
38 #include "console-x-impl.h"
|
|
39 #include "objects-x-impl.h"
|
428
|
40
|
3094
|
41 #ifdef USE_XFT
|
3354
|
42 #include "font-mgr.h"
|
3094
|
43 #endif
|
|
44
|
428
|
45 int x_handle_non_fully_specified_fonts;
|
|
46
|
|
47
|
|
48 /************************************************************************/
|
|
49 /* color instances */
|
|
50 /************************************************************************/
|
|
51
|
442
|
52 static int
|
|
53 x_parse_nearest_color (struct device *d, XColor *color, Lisp_Object name,
|
578
|
54 Error_Behavior errb)
|
428
|
55 {
|
|
56 Display *dpy = DEVICE_X_DISPLAY (d);
|
|
57 Colormap cmap = DEVICE_X_COLORMAP (d);
|
|
58 Visual *visual = DEVICE_X_VISUAL (d);
|
|
59 int result;
|
|
60
|
|
61 xzero (*color);
|
|
62 {
|
442
|
63 const Extbyte *extname;
|
428
|
64
|
442
|
65 LISP_STRING_TO_EXTERNAL (name, extname, Qx_color_name_encoding);
|
|
66 result = XParseColor (dpy, cmap, extname, color);
|
428
|
67 }
|
|
68 if (!result)
|
|
69 {
|
563
|
70 maybe_signal_error (Qgui_error, "Unrecognized color",
|
|
71 name, Qcolor, errb);
|
428
|
72 return 0;
|
|
73 }
|
3094
|
74 result = x_allocate_nearest_color (dpy, cmap, visual, color);
|
428
|
75 if (!result)
|
|
76 {
|
563
|
77 maybe_signal_error (Qgui_error, "Couldn't allocate color",
|
|
78 name, Qcolor, errb);
|
428
|
79 return 0;
|
|
80 }
|
|
81
|
|
82 return result;
|
|
83 }
|
|
84
|
|
85 static int
|
440
|
86 x_initialize_color_instance (Lisp_Color_Instance *c, Lisp_Object name,
|
578
|
87 Lisp_Object device, Error_Behavior errb)
|
428
|
88 {
|
|
89 XColor color;
|
3094
|
90 #ifdef USE_XFT
|
|
91 XftColor xftColor;
|
|
92 #endif
|
428
|
93 int result;
|
|
94
|
442
|
95 result = x_parse_nearest_color (XDEVICE (device), &color, name, errb);
|
428
|
96
|
|
97 if (!result)
|
|
98 return 0;
|
|
99
|
|
100 /* Don't allocate the data until we're sure that we will succeed,
|
|
101 or the finalize method may get fucked. */
|
|
102 c->data = xnew (struct x_color_instance_data);
|
|
103 if (result == 3)
|
|
104 COLOR_INSTANCE_X_DEALLOC (c) = 0;
|
|
105 else
|
|
106 COLOR_INSTANCE_X_DEALLOC (c) = 1;
|
|
107 COLOR_INSTANCE_X_COLOR (c) = color;
|
3094
|
108
|
|
109 #ifdef USE_XFT
|
|
110 xftColor.pixel = color.pixel;
|
|
111 xftColor.color.red = color.red;
|
|
112 xftColor.color.green = color.green;
|
|
113 xftColor.color.blue = color.blue;
|
|
114 xftColor.color.alpha = 0xffff;
|
|
115
|
|
116 COLOR_INSTANCE_X_XFTCOLOR (c) = xftColor;
|
|
117 #endif
|
|
118
|
428
|
119 return 1;
|
|
120 }
|
|
121
|
|
122 static void
|
440
|
123 x_print_color_instance (Lisp_Color_Instance *c,
|
428
|
124 Lisp_Object printcharfun,
|
2286
|
125 int UNUSED (escapeflag))
|
428
|
126 {
|
|
127 XColor color = COLOR_INSTANCE_X_COLOR (c);
|
800
|
128 write_fmt_string (printcharfun, " %ld=(%X,%X,%X)",
|
|
129 color.pixel, color.red, color.green, color.blue);
|
428
|
130 }
|
|
131
|
|
132 static void
|
440
|
133 x_finalize_color_instance (Lisp_Color_Instance *c)
|
428
|
134 {
|
|
135 if (c->data)
|
|
136 {
|
|
137 if (DEVICE_LIVE_P (XDEVICE (c->device)))
|
|
138 {
|
|
139 if (COLOR_INSTANCE_X_DEALLOC (c))
|
|
140 {
|
442
|
141 XFreeColors (DEVICE_X_DISPLAY (XDEVICE (c->device)),
|
|
142 DEVICE_X_COLORMAP (XDEVICE (c->device)),
|
428
|
143 &COLOR_INSTANCE_X_COLOR (c).pixel, 1, 0);
|
|
144 }
|
|
145 }
|
1726
|
146 xfree (c->data, void *);
|
428
|
147 c->data = 0;
|
|
148 }
|
|
149 }
|
|
150
|
|
151 /* Color instances are equal if they resolve to the same color on the
|
|
152 screen (have the same RGB values). I imagine that
|
|
153 "same RGB values" == "same cell in the colormap." Arguably we should
|
|
154 be comparing their names or pixel values instead. */
|
|
155
|
|
156 static int
|
440
|
157 x_color_instance_equal (Lisp_Color_Instance *c1,
|
|
158 Lisp_Color_Instance *c2,
|
2286
|
159 int UNUSED (depth))
|
428
|
160 {
|
|
161 XColor color1 = COLOR_INSTANCE_X_COLOR (c1);
|
|
162 XColor color2 = COLOR_INSTANCE_X_COLOR (c2);
|
|
163 return ((color1.red == color2.red) &&
|
|
164 (color1.green == color2.green) &&
|
|
165 (color1.blue == color2.blue));
|
|
166 }
|
|
167
|
2515
|
168 static Hashcode
|
2286
|
169 x_color_instance_hash (Lisp_Color_Instance *c, int UNUSED (depth))
|
428
|
170 {
|
|
171 XColor color = COLOR_INSTANCE_X_COLOR (c);
|
|
172 return HASH3 (color.red, color.green, color.blue);
|
|
173 }
|
|
174
|
|
175 static Lisp_Object
|
440
|
176 x_color_instance_rgb_components (Lisp_Color_Instance *c)
|
428
|
177 {
|
|
178 XColor color = COLOR_INSTANCE_X_COLOR (c);
|
|
179 return (list3 (make_int (color.red),
|
|
180 make_int (color.green),
|
|
181 make_int (color.blue)));
|
|
182 }
|
|
183
|
|
184 static int
|
|
185 x_valid_color_name_p (struct device *d, Lisp_Object color)
|
|
186 {
|
|
187 XColor c;
|
|
188 Display *dpy = DEVICE_X_DISPLAY (d);
|
|
189 Colormap cmap = DEVICE_X_COLORMAP (d);
|
442
|
190 const Extbyte *extname;
|
428
|
191
|
442
|
192 LISP_STRING_TO_EXTERNAL (color, extname, Qx_color_name_encoding);
|
428
|
193
|
440
|
194 return XParseColor (dpy, cmap, extname, &c);
|
428
|
195 }
|
|
196
|
2527
|
197 static Lisp_Object
|
|
198 x_color_list (void)
|
|
199 {
|
|
200 return call0 (intern ("x-color-list-internal"));
|
|
201 }
|
|
202
|
428
|
203
|
|
204 /************************************************************************/
|
|
205 /* font instances */
|
|
206 /************************************************************************/
|
|
207
|
3094
|
208 #ifdef USE_XFT
|
3354
|
209 /* #### all these #defines should probably move to font-mgr.h */
|
3094
|
210
|
|
211 /*
|
|
212 The format of a fontname (as returned by fontconfig) is not well-documented,
|
|
213 But the character repertoire is represented in an ASCII-compatible way. See
|
|
214 fccharset.c (FcCharSetUnparse). So we can use UTF-8 for long names.
|
|
215
|
|
216 Currently we have a hack where different versions of the unparsed name are
|
|
217 used in different contexts fairly arbitrarily. I don't think this is close
|
|
218 to coherency; even without the charset and lang properties fontconfig names
|
|
219 are too unwieldy to use. We need to rethink the approach here. I think
|
|
220 probably Lisp_Font_Instance.name should contain the font name as specified
|
|
221 to Lisp (almost surely much shorter than shortname, even, and most likely
|
|
222 wildcarded), while Lisp_Font_Instance.truename should contain the longname.
|
|
223 For now, I'm going to #ifdef the return values defaulting to short. -- sjt
|
|
224 */
|
|
225
|
|
226 /* DEBUGGING STUFF */
|
|
227
|
|
228 /* print message to stderr: one internal-format string argument */
|
|
229 #define DEBUG_XFT0(level,s) \
|
|
230 if (debug_xft > level) stderr_out (s)
|
|
231
|
|
232 /* print message to stderr: one formatted argument */
|
|
233 #define DEBUG_XFT1(level,format,x1) \
|
|
234 if (debug_xft > level) stderr_out (format, x1)
|
|
235
|
|
236 /* print message to stderr: two formatted arguments */
|
|
237 #define DEBUG_XFT2(level,format,x1,x2) \
|
|
238 if (debug_xft > level) stderr_out (format, x1, x2)
|
|
239
|
|
240 /* print message to stderr: three formatted arguments */
|
|
241 #define DEBUG_XFT3(level,format,x1,x2,x3) \
|
|
242 if (debug_xft > level) stderr_out (format, x1, x2, x3)
|
|
243
|
|
244 /* print message to stderr: four formatted arguments */
|
|
245 #define DEBUG_XFT4(level,format,x1,x2,x3,x4) \
|
|
246 if (debug_xft > level) stderr_out (format, x1, x2, x3, x4)
|
|
247
|
|
248 /* print an Xft pattern to stderr
|
|
249 LEVEL is the debug level (to compare to debug_xft)
|
|
250 FORMAT is a newline-terminated printf format with one %s for the pattern
|
|
251 and must be internal format (eg, pure ASCII)
|
|
252 PATTERN is an FcPattern *. */
|
|
253 #define PRINT_XFT_PATTERN(level,format,pattern) \
|
|
254 do { \
|
|
255 DECLARE_EISTRING (eistrpxft_name); \
|
|
256 FcChar8 *name = FcNameUnparse (pattern); \
|
|
257 \
|
3360
|
258 eicpy_ext(eistrpxft_name, name, Qfc_font_name_encoding); \
|
3094
|
259 DEBUG_XFT1 (level, format, eidata(eistrpxft_name)); \
|
|
260 free (name); \
|
|
261 } while (0)
|
|
262
|
|
263 /* print a progress message
|
|
264 LEVEL is the debug level (to compare to debug_xft)
|
|
265 FONT is the Xft font name in UTF-8 (the native encoding of Xft)
|
|
266 LANG is the language being checked for support (must be ASCII). */
|
|
267 #define CHECKING_LANG(level,font,lang) \
|
|
268 do { \
|
|
269 DECLARE_EISTRING (eistrcl_name); \
|
3360
|
270 eicpy_ext(eistrcl_name, font, Qfc_font_name_encoding); \
|
3094
|
271 DEBUG_XFT2 (level, "checking if %s handles %s\n", \
|
|
272 eidata(eistrcl_name), lang); \
|
|
273 } while (0)
|
|
274
|
|
275 #endif /* USE_XFT */
|
|
276
|
428
|
277 static int
|
2286
|
278 x_initialize_font_instance (Lisp_Font_Instance *f, Lisp_Object UNUSED (name),
|
578
|
279 Lisp_Object device, Error_Behavior errb)
|
428
|
280 {
|
440
|
281 Display *dpy = DEVICE_X_DISPLAY (XDEVICE (device));
|
3094
|
282 Extbyte *extname;
|
|
283 XFontStruct *fs = NULL; /* _F_ont _S_truct */
|
|
284 #ifdef USE_XFT
|
|
285 XftFont *rf = NULL; /* _R_ender _F_ont (X Render extension) */
|
|
286 #else
|
|
287 #define rf (0)
|
|
288 #endif
|
428
|
289
|
3094
|
290 #ifdef USE_XFT
|
|
291 DEBUG_XFT1 (2, "attempting to initialize font spec %s\n",
|
|
292 XSTRING_DATA(f->name));
|
|
293 /* #### serialize (optimize) these later... */
|
|
294 /* #### This function really needs to go away.
|
|
295 The problem is that the fontconfig/Xft functions work much too hard
|
|
296 to ensure that something is returned; but that something need not be
|
|
297 at all close to what we asked for. */
|
3360
|
298 LISP_STRING_TO_EXTERNAL (f->name, extname, Qfc_font_name_encoding);
|
3094
|
299 rf = xft_open_font_by_name (dpy, extname);
|
|
300 #endif
|
442
|
301 LISP_STRING_TO_EXTERNAL (f->name, extname, Qx_font_name_encoding);
|
3094
|
302 fs = XLoadQueryFont (dpy, extname);
|
|
303
|
|
304 if (!fs && !rf)
|
428
|
305 {
|
3094
|
306 /* #### should this refer to X and/or Xft? */
|
|
307 maybe_signal_error (Qgui_error, "Couldn't load font", f->name,
|
|
308 Qfont, errb);
|
428
|
309 return 0;
|
|
310 }
|
|
311
|
3389
|
312 if (rf && fs)
|
|
313 {
|
|
314 XFreeFont (dpy, fs);
|
|
315 fs = NULL; /* we don' need no steenkin' X font */
|
|
316 }
|
|
317
|
3094
|
318 if (fs && !fs->max_bounds.width)
|
|
319 {
|
|
320 /* yes, this has been known to happen. */
|
|
321 XFreeFont (dpy, fs);
|
|
322 fs = NULL;
|
|
323 maybe_signal_error (Qgui_error, "X font is too small", f->name, Qfont,
|
|
324 errb);
|
3389
|
325 return 0;
|
3094
|
326 }
|
|
327
|
|
328 /* Now that we're sure that we will succeed, we can allocate data without
|
|
329 fear that the finalize method may get fucked. */
|
428
|
330 f->data = xnew (struct x_font_instance_data);
|
|
331
|
3094
|
332 #ifdef USE_XFT
|
|
333 FONT_INSTANCE_X_XFTFONT (f) = rf;
|
|
334 if (rf)
|
|
335 /* Have an Xft font, initialize font info from it. */
|
|
336 {
|
|
337 DEBUG_XFT4 (2, "pre-initial ascent %d descent %d width %d height %d\n",
|
|
338 f->ascent, f->descent, f->width, f->height);
|
428
|
339
|
3094
|
340 /* #### This shit is just plain wrong unless we have a character cell
|
|
341 font. It really hoses us on large repertoire Unicode fonts with
|
|
342 "double-width" characters. */
|
|
343 f->ascent = rf->ascent;
|
|
344 f->descent = rf->descent;
|
428
|
345 {
|
3094
|
346 /* This is an approximation that AFAIK only gets used to compute
|
|
347 cell size for estimating window dimensions. The test_string8
|
|
348 is an ASCII string whose characters should approximate the
|
|
349 distribution of widths expected in real text. */
|
|
350 static const char test_string8[] = "Mmneei";
|
|
351 static const int len = sizeof (test_string8) - 1;
|
|
352 XGlyphInfo glyphinfo;
|
|
353
|
|
354 XftTextExtents8 (dpy, rf, test_string8, len, &glyphinfo);
|
|
355 /* #### maybe should be glyphinfo.xOff - glyphinfo.x? */
|
|
356 f->width = (2*glyphinfo.width + len)/(2*len);
|
428
|
357 }
|
3094
|
358 f->height = rf->height;
|
|
359 f->proportional_p = 1; /* we can't recognize monospaced fonts! */
|
|
360
|
3389
|
361 /* #### This message appears wa-a-ay too often!
|
|
362 We probably need to cache truenames or something?
|
|
363 Even if Xft does it for us, we cons too many font instances. */
|
|
364 DEBUG_XFT4 (0,
|
|
365 "initialized metrics ascent %d descent %d width %d height %d\n",
|
|
366 f->ascent, f->descent, f->width, f->height);
|
3094
|
367 }
|
|
368 else
|
|
369 {
|
|
370 DEBUG_XFT1 (0, "couldn't initialize Xft font %s\n",
|
|
371 XSTRING_DATA(f->name));
|
|
372 }
|
|
373 #endif
|
|
374
|
|
375 FONT_INSTANCE_X_FONT (f) = fs;
|
|
376 if (fs)
|
|
377 /* Have to use a core font, initialize font info from it. */
|
|
378 {
|
|
379 f->ascent = fs->ascent;
|
|
380 f->descent = fs->descent;
|
|
381 f->height = fs->ascent + fs->descent;
|
|
382 {
|
|
383 /* following change suggested by Ted Phelps <phelps@dstc.edu.au> */
|
|
384 int def_char = 'n'; /*fs->default_char;*/
|
|
385 int byte1, byte2;
|
428
|
386
|
3094
|
387 once_more:
|
|
388 byte1 = def_char >> 8;
|
|
389 byte2 = def_char & 0xFF;
|
|
390
|
|
391 if (fs->per_char)
|
|
392 {
|
|
393 /* Old versions of the R5 font server have garbage (>63k) as
|
|
394 def_char. 'n' might not be a valid character. */
|
|
395 if (byte1 < (int) fs->min_byte1 ||
|
|
396 byte1 > (int) fs->max_byte1 ||
|
|
397 byte2 < (int) fs->min_char_or_byte2 ||
|
|
398 byte2 > (int) fs->max_char_or_byte2)
|
|
399 f->width = 0;
|
|
400 else
|
|
401 f->width = fs->per_char[(byte1 - fs->min_byte1) *
|
|
402 (fs->max_char_or_byte2 -
|
|
403 fs->min_char_or_byte2 + 1) +
|
|
404 (byte2 - fs->min_char_or_byte2)].width;
|
|
405 }
|
428
|
406 else
|
3094
|
407 f->width = fs->max_bounds.width;
|
|
408
|
|
409 /* Some fonts have a default char whose width is 0. This is no good.
|
|
410 If that's the case, first try 'n' as the default char, and if n has
|
|
411 0 width too (unlikely) then just use the max width. */
|
|
412 if (f->width == 0)
|
428
|
413 {
|
3094
|
414 if (def_char == (int) fs->default_char)
|
|
415 f->width = fs->max_bounds.width;
|
|
416 else
|
|
417 {
|
|
418 def_char = fs->default_char;
|
|
419 goto once_more;
|
|
420 }
|
428
|
421 }
|
|
422 }
|
3094
|
423
|
|
424 /* If all characters don't exist then there could potentially be
|
|
425 0-width characters lurking out there. Not setting this flag
|
|
426 trips an optimization that would make them appear to have width
|
|
427 to redisplay. This is bad. So we set it if not all characters
|
|
428 have the same width or if not all characters are defined. */
|
|
429 /* #### This sucks. There is a measurable performance increase
|
|
430 when using proportional width fonts if this flag is not set.
|
|
431 Unfortunately so many of the fucking X fonts are not fully
|
|
432 defined that we could almost just get rid of this damn flag and
|
|
433 make it an assertion. */
|
|
434 f->proportional_p = (fs->min_bounds.width != fs->max_bounds.width ||
|
|
435 (x_handle_non_fully_specified_fonts &&
|
|
436 !fs->all_chars_exist));
|
|
437 }
|
|
438
|
|
439 #ifdef USE_XFT
|
|
440 if (debug_xft > 0)
|
|
441 {
|
|
442 int n = 3, d = 5;
|
|
443 /* check for weirdness */
|
|
444 if (n * f->height < d * f->width)
|
|
445 stderr_out ("font %s: width:height is %d:%d, larger than %d:%d\n",
|
|
446 XSTRING_DATA(f->name), f->width, f->height, n, d);
|
|
447 if (f->height <= 0 || f->width <= 0)
|
|
448 stderr_out ("bogus dimensions of font %s: width = %d, height = %d\n",
|
|
449 XSTRING_DATA(f->name), f->width, f->height);
|
|
450 stderr_out ("initialized font %s\n", XSTRING_DATA(f->name));
|
|
451 }
|
|
452 #else
|
|
453 #undef rf
|
|
454 #endif
|
428
|
455
|
|
456 return 1;
|
|
457 }
|
|
458
|
|
459 static void
|
440
|
460 x_print_font_instance (Lisp_Font_Instance *f,
|
428
|
461 Lisp_Object printcharfun,
|
2286
|
462 int UNUSED (escapeflag))
|
428
|
463 {
|
3094
|
464 if (FONT_INSTANCE_X_FONT (f))
|
|
465 write_fmt_string (printcharfun, " font id: 0x%lx",
|
|
466 (unsigned long) FONT_INSTANCE_X_FONT (f)->fid);
|
|
467 #ifdef USE_XFT
|
|
468 /* #### What should we do here? For now, print the address. */
|
|
469 if (FONT_INSTANCE_X_XFTFONT (f))
|
|
470 write_fmt_string (printcharfun, " xft font: 0x%lx",
|
|
471 (unsigned long) FONT_INSTANCE_X_XFTFONT (f));
|
|
472 #endif
|
428
|
473 }
|
|
474
|
|
475 static void
|
440
|
476 x_finalize_font_instance (Lisp_Font_Instance *f)
|
428
|
477 {
|
|
478
|
3094
|
479 #ifdef USE_XFT
|
|
480 DEBUG_XFT1 (0, "finalizing %s\n", (STRINGP (f->name)
|
|
481 ? (char *) XSTRING_DATA (f->name)
|
|
482 : "(unnamed font)"));
|
|
483 #endif
|
|
484
|
428
|
485 if (f->data)
|
|
486 {
|
|
487 if (DEVICE_LIVE_P (XDEVICE (f->device)))
|
|
488 {
|
|
489 Display *dpy = DEVICE_X_DISPLAY (XDEVICE (f->device));
|
|
490
|
3094
|
491 if (FONT_INSTANCE_X_FONT (f))
|
|
492 XFreeFont (dpy, FONT_INSTANCE_X_FONT (f));
|
|
493 #ifdef USE_XFT
|
|
494 if (FONT_INSTANCE_X_XFTFONT (f))
|
|
495 XftFontClose (dpy, FONT_INSTANCE_X_XFTFONT (f));
|
|
496 #endif
|
428
|
497 }
|
1726
|
498 xfree (f->data, void *);
|
428
|
499 f->data = 0;
|
|
500 }
|
|
501 }
|
|
502
|
|
503 /* Determining the truename of a font is hard. (Big surprise.)
|
|
504
|
3094
|
505 This is not true for fontconfig. Each font has a (nearly) canonical
|
|
506 representation up to permutation of the order of properties. It is
|
|
507 possible to construct a name which exactly identifies the properties of
|
|
508 the current font. However, it is theoretically possible that there exists
|
|
509 another font with a super set of those properties that would happen to get
|
|
510 selected. -- sjt
|
|
511
|
428
|
512 By "truename" we mean an XLFD-form name which contains no wildcards, yet
|
|
513 which resolves to *exactly* the same font as the one which we already have
|
|
514 the (probably wildcarded) name and `XFontStruct' of.
|
|
515
|
|
516 One might think that the first font returned by XListFonts would be the one
|
|
517 that XOpenFont would pick. Apparently this is the case on some servers,
|
|
518 but not on others. It would seem not to be specified.
|
|
519
|
|
520 The MIT R5 server sometimes appears to be picking the lexicographically
|
|
521 smallest font which matches the name (thus picking "adobe" fonts before
|
|
522 "bitstream" fonts even if the bitstream fonts are earlier in the path, and
|
|
523 also picking 100dpi adobe fonts over 75dpi adobe fonts even though the
|
|
524 75dpi are in the path earlier) but sometimes appears to be doing something
|
442
|
525 else entirely (for example, removing the bitstream fonts from the path will
|
428
|
526 cause the 75dpi adobe fonts to be used instead of the 100dpi, even though
|
|
527 their relative positions in the path (and their names!) have not changed).
|
|
528
|
|
529 The documentation for XSetFontPath() seems to indicate that the order of
|
442
|
530 entries in the font path means something, but it's pretty noncommittal about
|
428
|
531 it, and the spirit of the law is apparently not being obeyed...
|
|
532
|
|
533 All the fonts I've seen have a property named `FONT' which contains the
|
|
534 truename of the font. However, there are two problems with using this: the
|
|
535 first is that the X Protocol Document is quite explicit that all properties
|
|
536 are optional, so we can't depend on it being there. The second is that
|
|
537 it's conceivable that this alleged truename isn't actually accessible as a
|
|
538 font, due to some difference of opinion between the font designers and
|
|
539 whoever installed the font on the system.
|
|
540
|
|
541 So, our first attempt is to look for a FONT property, and then verify that
|
|
542 the name there is a valid name by running XListFonts on it. There's still
|
|
543 the potential that this could be true but we could still be being lied to,
|
|
544 but that seems pretty remote.
|
|
545
|
|
546 Late breaking news: I've gotten reports that SunOS 4.1.3U1
|
|
547 with OpenWound 3.0 has a font whose truename is really
|
|
548 "-Adobe-Courier-Medium-R-Normal--12-120-75-75-M-70-ISO8859-1"
|
|
549 but whose FONT property contains "Courier".
|
|
550
|
|
551 So we disbelieve the FONT property unless it begins with a dash and
|
|
552 is more than 30 characters long. X Windows: The defacto substandard.
|
|
553 X Windows: Complex nonsolutions to simple nonproblems. X Windows:
|
|
554 Live the nightmare.
|
|
555
|
|
556 If the FONT property doesn't exist, then we try and construct an XLFD name
|
|
557 out of the other font properties (FOUNDRY, FAMILY_NAME, WEIGHT_NAME, etc).
|
|
558 This is necessary at least for some versions of OpenWound. But who knows
|
|
559 what the future will bring.
|
|
560
|
|
561 If that doesn't work, then we use XListFonts and either take the first font
|
|
562 (which I think is the most sensible thing) or we find the lexicographically
|
|
563 least, depending on whether the preprocessor constant `XOPENFONT_SORTS' is
|
|
564 defined. This sucks because the two behaviors are a property of the server
|
|
565 being used, not the architecture on which emacs has been compiled. Also,
|
|
566 as I described above, sorting isn't ALWAYS what the server does. Really it
|
|
567 does something seemingly random. There is no reliable way to win if the
|
|
568 FONT property isn't present.
|
|
569
|
|
570 Another possibility which I haven't bothered to implement would be to map
|
|
571 over all of the matching fonts and find the first one that has the same
|
|
572 character metrics as the font we already have loaded. Even if this didn't
|
|
573 return exactly the same font, it would at least return one whose characters
|
|
574 were the same sizes, which would probably be good enough.
|
|
575
|
|
576 More late-breaking news: on RS/6000 AIX 3.2.4, the expression
|
|
577 XLoadQueryFont (dpy, "-*-Fixed-Medium-R-*-*-*-130-75-75-*-*-ISO8859-1")
|
|
578 actually returns the font
|
|
579 -Misc-Fixed-Medium-R-Normal--13-120-75-75-C-80-ISO8859-1
|
|
580 which is crazy, because that font doesn't even match that pattern! It is
|
|
581 also not included in the output produced by `xlsfonts' with that pattern.
|
|
582
|
|
583 So this is yet another example of XListFonts() and XOpenFont() using
|
|
584 completely different algorithms. This, however, is a goofier example of
|
|
585 this bug, because in this case, it's not just the search order that is
|
|
586 different -- the sets don't even intersect.
|
|
587
|
|
588 If anyone has any better ideas how to do this, or any insights on what it is
|
|
589 that the various servers are actually doing, please let me know! -- jwz. */
|
|
590
|
|
591 static int
|
442
|
592 valid_x_font_name_p (Display *dpy, Extbyte *name)
|
428
|
593 {
|
|
594 /* Maybe this should be implemented by calling XLoadFont and trapping
|
|
595 the error. That would be a lot of work, and wasteful as hell, but
|
|
596 might be more correct.
|
|
597 */
|
|
598 int nnames = 0;
|
444
|
599 Extbyte **names = 0;
|
428
|
600 if (! name)
|
|
601 return 0;
|
|
602 names = XListFonts (dpy, name, 1, &nnames);
|
|
603 if (names)
|
|
604 XFreeFontNames (names);
|
|
605 return (nnames != 0);
|
|
606 }
|
|
607
|
442
|
608 static Extbyte *
|
428
|
609 truename_via_FONT_prop (Display *dpy, XFontStruct *font)
|
|
610 {
|
|
611 unsigned long value = 0;
|
442
|
612 Extbyte *result = 0;
|
428
|
613 if (XGetFontProperty (font, XA_FONT, &value))
|
|
614 result = XGetAtomName (dpy, value);
|
|
615 /* result is now 0, or the string value of the FONT property. */
|
|
616 if (result)
|
|
617 {
|
|
618 /* Verify that result is an XLFD name (roughly...) */
|
647
|
619 if (result [0] != '-' || strlen (result) < 30)
|
428
|
620 {
|
|
621 XFree (result);
|
|
622 result = 0;
|
|
623 }
|
|
624 }
|
|
625 return result; /* this must be freed by caller if non-0 */
|
|
626 }
|
|
627
|
442
|
628 static Extbyte *
|
428
|
629 truename_via_random_props (Display *dpy, XFontStruct *font)
|
|
630 {
|
|
631 struct device *d = get_device_from_display (dpy);
|
|
632 unsigned long value = 0;
|
442
|
633 Extbyte *foundry, *family, *weight, *slant, *setwidth, *add_style;
|
428
|
634 unsigned long pixel, point, res_x, res_y;
|
442
|
635 Extbyte *spacing;
|
428
|
636 unsigned long avg_width;
|
442
|
637 Extbyte *registry, *encoding;
|
|
638 Extbyte composed_name [2048];
|
428
|
639 int ok = 0;
|
442
|
640 Extbyte *result;
|
428
|
641
|
|
642 #define get_string(atom,var) \
|
|
643 if (XGetFontProperty (font, (atom), &value)) \
|
|
644 var = XGetAtomName (dpy, value); \
|
|
645 else { \
|
|
646 var = 0; \
|
|
647 goto FAIL; }
|
|
648 #define get_number(atom,var) \
|
|
649 if (!XGetFontProperty (font, (atom), &var) || \
|
|
650 var > 999) \
|
|
651 goto FAIL;
|
|
652
|
|
653 foundry = family = weight = slant = setwidth = 0;
|
|
654 add_style = spacing = registry = encoding = 0;
|
|
655
|
|
656 get_string (DEVICE_XATOM_FOUNDRY (d), foundry);
|
|
657 get_string (DEVICE_XATOM_FAMILY_NAME (d), family);
|
|
658 get_string (DEVICE_XATOM_WEIGHT_NAME (d), weight);
|
|
659 get_string (DEVICE_XATOM_SLANT (d), slant);
|
|
660 get_string (DEVICE_XATOM_SETWIDTH_NAME (d), setwidth);
|
|
661 get_string (DEVICE_XATOM_ADD_STYLE_NAME (d), add_style);
|
|
662 get_number (DEVICE_XATOM_PIXEL_SIZE (d), pixel);
|
|
663 get_number (DEVICE_XATOM_POINT_SIZE (d), point);
|
|
664 get_number (DEVICE_XATOM_RESOLUTION_X (d), res_x);
|
|
665 get_number (DEVICE_XATOM_RESOLUTION_Y (d), res_y);
|
|
666 get_string (DEVICE_XATOM_SPACING (d), spacing);
|
|
667 get_number (DEVICE_XATOM_AVERAGE_WIDTH (d), avg_width);
|
|
668 get_string (DEVICE_XATOM_CHARSET_REGISTRY (d), registry);
|
|
669 get_string (DEVICE_XATOM_CHARSET_ENCODING (d), encoding);
|
|
670 #undef get_number
|
|
671 #undef get_string
|
|
672
|
|
673 sprintf (composed_name,
|
|
674 "-%s-%s-%s-%s-%s-%s-%ld-%ld-%ld-%ld-%s-%ld-%s-%s",
|
|
675 foundry, family, weight, slant, setwidth, add_style, pixel,
|
|
676 point, res_x, res_y, spacing, avg_width, registry, encoding);
|
|
677 ok = 1;
|
|
678
|
|
679 FAIL:
|
|
680 if (ok)
|
|
681 {
|
|
682 int L = strlen (composed_name) + 1;
|
2367
|
683 result = xnew_extbytes (L);
|
428
|
684 strncpy (result, composed_name, L);
|
|
685 }
|
|
686 else
|
|
687 result = 0;
|
|
688
|
|
689 if (foundry) XFree (foundry);
|
|
690 if (family) XFree (family);
|
|
691 if (weight) XFree (weight);
|
|
692 if (slant) XFree (slant);
|
|
693 if (setwidth) XFree (setwidth);
|
|
694 if (add_style) XFree (add_style);
|
|
695 if (spacing) XFree (spacing);
|
|
696 if (registry) XFree (registry);
|
|
697 if (encoding) XFree (encoding);
|
|
698
|
|
699 return result;
|
|
700 }
|
|
701
|
3169
|
702 /* XListFonts doesn't allocate memory unconditionally based on this. (For
|
|
703 XFree86 in 2005, at least. */
|
|
704 #define MAX_FONT_COUNT INT_MAX
|
428
|
705
|
442
|
706 static Extbyte *
|
|
707 truename_via_XListFonts (Display *dpy, Extbyte *font_name)
|
428
|
708 {
|
442
|
709 Extbyte *result = 0;
|
444
|
710 Extbyte **names;
|
428
|
711 int count = 0;
|
|
712
|
|
713 #ifndef XOPENFONT_SORTS
|
|
714 /* In a sensible world, the first font returned by XListFonts()
|
|
715 would be the font that XOpenFont() would use. */
|
|
716 names = XListFonts (dpy, font_name, 1, &count);
|
|
717 if (count) result = names [0];
|
|
718 #else
|
|
719 /* But the world I live in is much more perverse. */
|
|
720 names = XListFonts (dpy, font_name, MAX_FONT_COUNT, &count);
|
3094
|
721 /* Find the lexicographic minimum of names[].
|
|
722 (#### Should we be comparing case-insensitively?) */
|
428
|
723 while (count--)
|
3094
|
724 /* [[ !!#### Not Mule-friendly ]]
|
|
725 Doesn't matter, XLFDs are HPC (old) or Latin1 (modern). If they
|
|
726 aren't, who knows what they are? -- sjt */
|
428
|
727 if (result == 0 || (strcmp (result, names [count]) < 0))
|
|
728 result = names [count];
|
|
729 #endif
|
|
730
|
|
731 if (result)
|
|
732 result = xstrdup (result);
|
|
733 if (names)
|
|
734 XFreeFontNames (names);
|
|
735
|
|
736 return result; /* this must be freed by caller if non-0 */
|
|
737 }
|
|
738
|
|
739 static Lisp_Object
|
442
|
740 x_font_truename (Display *dpy, Extbyte *name, XFontStruct *font)
|
428
|
741 {
|
442
|
742 Extbyte *truename_FONT = 0;
|
|
743 Extbyte *truename_random = 0;
|
|
744 Extbyte *truename = 0;
|
428
|
745
|
|
746 /* The search order is:
|
|
747 - if FONT property exists, and is a valid name, return it.
|
|
748 - if the other props exist, and add up to a valid name, return it.
|
|
749 - if we find a matching name with XListFonts, return it.
|
|
750 - if FONT property exists, return it regardless.
|
|
751 - if other props exist, return the resultant name regardless.
|
|
752 - else return 0.
|
|
753 */
|
|
754
|
|
755 truename = truename_FONT = truename_via_FONT_prop (dpy, font);
|
|
756 if (truename && !valid_x_font_name_p (dpy, truename))
|
|
757 truename = 0;
|
|
758 if (!truename)
|
|
759 truename = truename_random = truename_via_random_props (dpy, font);
|
|
760 if (truename && !valid_x_font_name_p (dpy, truename))
|
|
761 truename = 0;
|
|
762 if (!truename && name)
|
|
763 truename = truename_via_XListFonts (dpy, name);
|
|
764
|
|
765 if (!truename)
|
|
766 {
|
|
767 /* Gag - we weren't able to find a seemingly-valid truename.
|
|
768 Well, maybe we're on one of those braindead systems where
|
|
769 XListFonts() and XLoadFont() are in violent disagreement.
|
|
770 If we were able to compute a truename, try using that even
|
|
771 if evidence suggests that it's not a valid name - because
|
|
772 maybe it is, really, and that's better than nothing.
|
|
773 X Windows: You'll envy the dead.
|
|
774 */
|
|
775 if (truename_FONT)
|
|
776 truename = truename_FONT;
|
|
777 else if (truename_random)
|
|
778 truename = truename_random;
|
|
779 }
|
|
780
|
|
781 /* One or both of these are not being used - free them. */
|
|
782 if (truename_FONT && truename_FONT != truename)
|
|
783 XFree (truename_FONT);
|
|
784 if (truename_random && truename_random != truename)
|
|
785 XFree (truename_random);
|
|
786
|
|
787 if (truename)
|
|
788 {
|
442
|
789 Lisp_Object result = build_ext_string (truename, Qx_font_name_encoding);
|
428
|
790 XFree (truename);
|
|
791 return result;
|
|
792 }
|
|
793 else
|
|
794 return Qnil;
|
|
795 }
|
|
796
|
|
797 static Lisp_Object
|
578
|
798 x_font_instance_truename (Lisp_Font_Instance *f, Error_Behavior errb)
|
428
|
799 {
|
|
800 struct device *d = XDEVICE (f->device);
|
3094
|
801 Display *dpy = DEVICE_X_DISPLAY (d);
|
|
802 Extbyte *nameext;
|
|
803
|
|
804 /* #### restructure this so that we return a valid truename at the end,
|
|
805 and otherwise only return when we return something desperate that
|
|
806 doesn't get stored for future use. */
|
|
807
|
|
808 #ifdef USE_XFT
|
|
809 /* First, try an Xft font. */
|
|
810 if (NILP (FONT_INSTANCE_TRUENAME (f)) && FONT_INSTANCE_X_XFTFONT (f))
|
|
811 {
|
|
812 /* The font is already open, we just unparse. */
|
|
813 FcChar8 *res = FcNameUnparse (FONT_INSTANCE_X_XFTFONT (f)->pattern);
|
|
814 if (res)
|
|
815 {
|
3174
|
816 FONT_INSTANCE_TRUENAME (f) =
|
3360
|
817 build_ext_string (res, Qfc_font_name_encoding);
|
3094
|
818 free (res);
|
|
819 return FONT_INSTANCE_TRUENAME (f);
|
|
820 }
|
|
821 else
|
|
822 {
|
|
823 maybe_signal_error (Qgui_error,
|
|
824 "Couldn't unparse Xft font to truename",
|
|
825 Qnil, Qfont, errb);
|
|
826 /* used to return Qnil here */
|
|
827 }
|
|
828 }
|
|
829 #endif /* USE_XFT */
|
|
830
|
|
831 /* OK, fall back to core font. */
|
|
832 if (NILP (FONT_INSTANCE_TRUENAME (f))
|
|
833 && FONT_INSTANCE_X_FONT (f))
|
|
834 {
|
3286
|
835 nameext = NEW_LISP_STRING_TO_EXTERNAL (f->name, Qx_font_name_encoding);
|
3094
|
836 FONT_INSTANCE_TRUENAME (f) =
|
|
837 x_font_truename (dpy, nameext, FONT_INSTANCE_X_FONT (f));
|
|
838 }
|
428
|
839
|
872
|
840 if (NILP (FONT_INSTANCE_TRUENAME (f)))
|
428
|
841 {
|
3094
|
842 /* Urk, no luck. Whine about our bad luck and exit. */
|
|
843 Lisp_Object font_instance = wrap_font_instance (f);
|
|
844
|
|
845
|
|
846 maybe_signal_error (Qgui_error, "Couldn't determine font truename",
|
|
847 font_instance, Qfont, errb);
|
|
848 /* Ok, just this once, return the font name as the truename.
|
|
849 (This is only used by Fequal() right now.) */
|
|
850 return f->name;
|
|
851 }
|
442
|
852
|
3094
|
853 /* Return what we found. */
|
872
|
854 return FONT_INSTANCE_TRUENAME (f);
|
428
|
855 }
|
|
856
|
|
857 static Lisp_Object
|
440
|
858 x_font_instance_properties (Lisp_Font_Instance *f)
|
428
|
859 {
|
|
860 struct device *d = XDEVICE (f->device);
|
|
861 int i;
|
|
862 Lisp_Object result = Qnil;
|
444
|
863 Display *dpy = DEVICE_X_DISPLAY (d);
|
3094
|
864 XFontProp *props = NULL;
|
428
|
865
|
3094
|
866 /* #### really should hack Xft fonts, too
|
|
867 Strategy: fontconfig must have an iterator for this purpose. */
|
|
868 if (! FONT_INSTANCE_X_FONT (f)) return result;
|
|
869
|
|
870 props = FONT_INSTANCE_X_FONT (f)->properties;
|
428
|
871 for (i = FONT_INSTANCE_X_FONT (f)->n_properties - 1; i >= 0; i--)
|
|
872 {
|
|
873 Lisp_Object name, value;
|
|
874 Atom atom = props [i].name;
|
867
|
875 Ibyte *name_str = 0;
|
647
|
876 Bytecount name_len;
|
442
|
877 Extbyte *namestrext = XGetAtomName (dpy, atom);
|
|
878
|
|
879 if (namestrext)
|
444
|
880 TO_INTERNAL_FORMAT (C_STRING, namestrext,
|
|
881 ALLOCA, (name_str, name_len),
|
|
882 Qx_atom_name_encoding);
|
442
|
883
|
771
|
884 name = (name_str ? intern_int (name_str) : Qnil);
|
428
|
885 if (name_str &&
|
|
886 (atom == XA_FONT ||
|
|
887 atom == DEVICE_XATOM_FOUNDRY (d) ||
|
|
888 atom == DEVICE_XATOM_FAMILY_NAME (d) ||
|
|
889 atom == DEVICE_XATOM_WEIGHT_NAME (d) ||
|
|
890 atom == DEVICE_XATOM_SLANT (d) ||
|
|
891 atom == DEVICE_XATOM_SETWIDTH_NAME (d) ||
|
|
892 atom == DEVICE_XATOM_ADD_STYLE_NAME (d) ||
|
|
893 atom == DEVICE_XATOM_SPACING (d) ||
|
|
894 atom == DEVICE_XATOM_CHARSET_REGISTRY (d) ||
|
|
895 atom == DEVICE_XATOM_CHARSET_ENCODING (d) ||
|
2367
|
896 !qxestrcmp_ascii (name_str, "CHARSET_COLLECTIONS") ||
|
|
897 !qxestrcmp_ascii (name_str, "FONTNAME_REGISTRY") ||
|
|
898 !qxestrcmp_ascii (name_str, "CLASSIFICATION") ||
|
|
899 !qxestrcmp_ascii (name_str, "COPYRIGHT") ||
|
|
900 !qxestrcmp_ascii (name_str, "DEVICE_FONT_NAME") ||
|
|
901 !qxestrcmp_ascii (name_str, "FULL_NAME") ||
|
|
902 !qxestrcmp_ascii (name_str, "MONOSPACED") ||
|
|
903 !qxestrcmp_ascii (name_str, "QUALITY") ||
|
|
904 !qxestrcmp_ascii (name_str, "RELATIVE_SET") ||
|
|
905 !qxestrcmp_ascii (name_str, "RELATIVE_WEIGHT") ||
|
|
906 !qxestrcmp_ascii (name_str, "STYLE")))
|
428
|
907 {
|
442
|
908 Extbyte *val_str = XGetAtomName (dpy, props [i].card32);
|
|
909
|
|
910 value = (val_str ? build_ext_string (val_str, Qx_atom_name_encoding)
|
|
911 : Qnil);
|
428
|
912 }
|
|
913 else
|
|
914 value = make_int (props [i].card32);
|
442
|
915 if (namestrext) XFree (namestrext);
|
428
|
916 result = Fcons (Fcons (name, value), result);
|
|
917 }
|
|
918 return result;
|
|
919 }
|
|
920
|
|
921 static Lisp_Object
|
2527
|
922 x_font_list (Lisp_Object pattern, Lisp_Object device, Lisp_Object maxnumber)
|
428
|
923 {
|
444
|
924 Extbyte **names;
|
428
|
925 int count = 0;
|
1701
|
926 int max_number = MAX_FONT_COUNT;
|
428
|
927 Lisp_Object result = Qnil;
|
442
|
928 const Extbyte *patternext;
|
428
|
929
|
442
|
930 LISP_STRING_TO_EXTERNAL (pattern, patternext, Qx_font_name_encoding);
|
428
|
931
|
1701
|
932 if (!NILP(maxnumber) && INTP(maxnumber))
|
|
933 {
|
|
934 max_number = XINT(maxnumber);
|
|
935 }
|
|
936
|
428
|
937 names = XListFonts (DEVICE_X_DISPLAY (XDEVICE (device)),
|
1701
|
938 patternext, max_number, &count);
|
428
|
939 while (count--)
|
442
|
940 result = Fcons (build_ext_string (names[count], Qx_font_name_encoding),
|
|
941 result);
|
428
|
942 if (names)
|
|
943 XFreeFontNames (names);
|
|
944 return result;
|
|
945 }
|
|
946
|
|
947 #ifdef MULE
|
|
948
|
|
949 static int
|
3094
|
950 x_font_spec_matches_charset (struct device * USED_IF_XFT (d),
|
|
951 Lisp_Object charset,
|
867
|
952 const Ibyte *nonreloc, Lisp_Object reloc,
|
872
|
953 Bytecount offset, Bytecount length,
|
|
954 int stage)
|
428
|
955 {
|
872
|
956 if (stage)
|
3094
|
957 #ifdef USE_XFT
|
|
958 {
|
|
959 Display *dpy = DEVICE_X_DISPLAY (d);
|
|
960 Extbyte *extname;
|
|
961 XftFont *rf;
|
|
962 const Ibyte *the_nonreloc;
|
|
963
|
|
964 if (!NILP(reloc))
|
|
965 {
|
|
966 the_nonreloc = XSTRING_DATA (reloc);
|
|
967 LISP_STRING_TO_EXTERNAL (reloc, extname, Qx_font_name_encoding);
|
|
968 rf = xft_open_font_by_name (dpy, extname);
|
|
969 return 0; /* #### maybe this will compile and run ;) */
|
|
970 }
|
|
971 }
|
|
972 #else
|
872
|
973 return 0;
|
3094
|
974 #endif
|
872
|
975
|
428
|
976 if (UNBOUNDP (charset))
|
|
977 return 1;
|
|
978 /* Hack! Short font names don't have the registry in them,
|
|
979 so we just assume the user knows what they're doing in the
|
|
980 case of ASCII. For other charsets, you gotta give the
|
|
981 long form; sorry buster.
|
3094
|
982 #### FMH: this screws fontconfig/Xft?
|
|
983 STRATEGY: use fontconfig's ability to hack languages and character
|
|
984 sets (lang and charset properties).
|
|
985 #### Maybe we can use the fontconfig model to eliminate the difference
|
|
986 between faces and fonts? No - it looks like that would be an abuse
|
|
987 (fontconfig doesn't know about colors, although Xft does).
|
428
|
988 */
|
|
989 if (EQ (charset, Vcharset_ascii))
|
|
990 {
|
867
|
991 const Ibyte *the_nonreloc = nonreloc;
|
428
|
992 int i;
|
|
993 Bytecount the_length = length;
|
|
994
|
|
995 if (!the_nonreloc)
|
|
996 the_nonreloc = XSTRING_DATA (reloc);
|
|
997 fixup_internal_substring (nonreloc, reloc, offset, &the_length);
|
|
998 the_nonreloc += offset;
|
|
999 if (!memchr (the_nonreloc, '*', the_length))
|
|
1000 {
|
|
1001 for (i = 0;; i++)
|
|
1002 {
|
867
|
1003 const Ibyte *new_nonreloc = (const Ibyte *)
|
428
|
1004 memchr (the_nonreloc, '-', the_length);
|
|
1005 if (!new_nonreloc)
|
|
1006 break;
|
|
1007 new_nonreloc++;
|
|
1008 the_length -= new_nonreloc - the_nonreloc;
|
|
1009 the_nonreloc = new_nonreloc;
|
|
1010 }
|
|
1011
|
|
1012 /* If it has less than 5 dashes, it's a short font.
|
|
1013 Of course, long fonts always have 14 dashes or so, but short
|
|
1014 fonts never have more than 1 or 2 dashes, so this is some
|
|
1015 sort of reasonable heuristic. */
|
|
1016 if (i < 5)
|
|
1017 return 1;
|
|
1018 }
|
|
1019 }
|
|
1020
|
|
1021 return (fast_string_match (XCHARSET_REGISTRY (charset),
|
|
1022 nonreloc, reloc, offset, length, 1,
|
|
1023 ERROR_ME, 0) >= 0);
|
|
1024 }
|
|
1025
|
3094
|
1026 #ifdef USE_XFT
|
|
1027 /* #### debug functions: find a better place for us */
|
|
1028 const char *FcResultToString (FcResult r);
|
|
1029 const char *
|
|
1030 FcResultToString (FcResult r)
|
|
1031 {
|
|
1032 static char buffer[256];
|
|
1033 switch (r)
|
|
1034 {
|
|
1035 case FcResultMatch:
|
|
1036 return "FcResultMatch";
|
|
1037 case FcResultNoMatch:
|
|
1038 return "FcResultNoMatch";
|
|
1039 case FcResultTypeMismatch:
|
|
1040 return "FcResultTypeMismatch";
|
|
1041 case FcResultNoId:
|
|
1042 return "FcResultNoId";
|
|
1043 default:
|
|
1044 snprintf (buffer, 255, "FcResultUndocumentedValue (%d)", r);
|
|
1045 return buffer;
|
|
1046 }
|
|
1047 }
|
|
1048
|
|
1049 const char *FcTypeOfValueToString (FcValue v);
|
|
1050 const char *
|
|
1051 FcTypeOfValueToString (FcValue v)
|
|
1052 {
|
|
1053 static char buffer[256];
|
|
1054 switch (v.type)
|
|
1055 {
|
|
1056 case FcTypeMatrix:
|
|
1057 return "FcTypeMatrix";
|
|
1058 case FcTypeString:
|
|
1059 return "FcTypeString";
|
|
1060 case FcTypeVoid:
|
|
1061 return "FcTypeVoid";
|
|
1062 case FcTypeDouble:
|
|
1063 return "FcTypeDouble";
|
|
1064 case FcTypeInteger:
|
|
1065 return "FcTypeInteger";
|
|
1066 case FcTypeBool:
|
|
1067 return "FcTypeBool";
|
|
1068 case FcTypeCharSet:
|
|
1069 return "FcTypeCharSet";
|
|
1070 case FcTypeLangSet:
|
|
1071 return "FcTypeLangSet";
|
|
1072 /* #### There is no union member of this type, but there are void* and
|
|
1073 FcPattern* members, as of fontconfig.h FC_VERSION 10002 */
|
|
1074 case FcTypeFTFace:
|
|
1075 return "FcTypeFTFace";
|
|
1076 default:
|
|
1077 snprintf (buffer, 255, "FcTypeUndocumentedType (%d)", v.type);
|
|
1078 return buffer;
|
|
1079 }
|
|
1080 }
|
|
1081
|
|
1082 static FcCharSet *
|
|
1083 mule_to_fc_charset (Lisp_Object cs)
|
|
1084 {
|
|
1085 int ucode, i, j;
|
|
1086 FcCharSet *fccs;
|
|
1087
|
|
1088 CHECK_CHARSET (cs);
|
|
1089 fccs = FcCharSetCreate ();
|
|
1090 /* #### do we also need to deal with 94 vs. 96 charsets?
|
|
1091 ie, how are SP and DEL treated in ASCII? non-graphic should return -1 */
|
|
1092 if (1 == XCHARSET_DIMENSION (cs))
|
|
1093 /* Unicode tables are indexed by offsets from ASCII SP, not by ASCII */
|
|
1094 for (i = 0; i < 96; i++)
|
|
1095 {
|
|
1096 ucode = ((int *) XCHARSET_TO_UNICODE_TABLE (cs))[i];
|
|
1097 if (ucode >= 0)
|
|
1098 /* #### should check for allocation failure */
|
|
1099 FcCharSetAddChar (fccs, (FcChar32) ucode);
|
|
1100 }
|
|
1101 else if (2 == XCHARSET_DIMENSION (cs))
|
|
1102 /* Unicode tables are indexed by offsets from ASCII SP, not by ASCII */
|
|
1103 for (i = 0; i < 96; i++)
|
|
1104 for (j = 0; j < 96; j++)
|
|
1105 {
|
|
1106 ucode = ((int **) XCHARSET_TO_UNICODE_TABLE (cs))[i][j];
|
|
1107 if (ucode >= 0)
|
|
1108 /* #### should check for allocation failure */
|
|
1109 FcCharSetAddChar (fccs, (FcChar32) ucode);
|
|
1110 }
|
|
1111 else
|
|
1112 {
|
|
1113 FcCharSetDestroy (fccs);
|
|
1114 fccs = NULL;
|
|
1115 }
|
|
1116 return fccs;
|
|
1117 }
|
|
1118
|
|
1119 struct charset_reporter {
|
|
1120 Lisp_Object *charset;
|
|
1121 /* This is a debug facility, require ASCII. */
|
|
1122 Extbyte *language; /* ASCII, please */
|
|
1123 FcChar8 *rfc3066; /* ASCII, please */
|
|
1124 };
|
|
1125
|
|
1126 static struct charset_reporter charset_table[] =
|
|
1127 {
|
|
1128 /* #### It's my branch, my favorite charsets get checked first!
|
|
1129 That's a joke, Son.
|
|
1130 Ie, I don't know what I'm doing, so my charsets first is as good as
|
|
1131 any other arbitrary order. If you have a better idea, speak up! */
|
|
1132 { &Vcharset_ascii, "English", "en" },
|
|
1133 { &Vcharset_japanese_jisx0208, "Japanese", "ja" },
|
|
1134 { &Vcharset_japanese_jisx0212, "Japanese", "ja" },
|
|
1135 { &Vcharset_katakana_jisx0201, "Japanese", "ja" },
|
|
1136 { &Vcharset_latin_jisx0201, "Japanese", "ja" },
|
|
1137 { &Vcharset_japanese_jisx0208_1978, "Japanese", "ja" },
|
|
1138 { &Vcharset_greek_iso8859_7, "Greek", "el" },
|
|
1139 /* #### all the Chinese need checking
|
|
1140 Damn the blood-sucking ISO anyway. */
|
|
1141 { &Vcharset_chinese_gb2312, "simplified Chinese", "zh-CN" },
|
|
1142 { &Vcharset_korean_ksc5601, "Korean", "ko" },
|
|
1143 { &Vcharset_chinese_cns11643_1, "traditional Chinese", "zh-TW" },
|
|
1144 { &Vcharset_chinese_cns11643_2, "traditional Chinese", "zh-TW" },
|
|
1145 { &Vcharset_latin_iso8859_1, NULL, NULL },
|
|
1146 { &Vcharset_latin_iso8859_2, NULL, NULL },
|
|
1147 { &Vcharset_latin_iso8859_3, NULL, NULL },
|
|
1148 { &Vcharset_latin_iso8859_4, NULL, NULL },
|
|
1149 { &Vcharset_latin_iso8859_9, NULL, NULL },
|
|
1150 { &Vcharset_latin_iso8859_15, NULL, NULL },
|
|
1151 { &Vcharset_thai_tis620, NULL, NULL },
|
|
1152 { &Vcharset_arabic_iso8859_6, NULL, NULL },
|
|
1153 { &Vcharset_hebrew_iso8859_8, "Hebrew", "he" },
|
|
1154 { &Vcharset_cyrillic_iso8859_5, NULL, NULL },
|
|
1155 /* #### these probably are not quite right */
|
|
1156 { &Vcharset_chinese_big5_1, "traditional Chinese", "zh-TW" },
|
|
1157 { &Vcharset_chinese_big5_2, "traditional Chinese", "zh-TW" },
|
|
1158 { NULL, NULL, NULL }
|
|
1159 };
|
|
1160
|
|
1161 /* Choose appropriate font name for debug messages.
|
|
1162 Use only in the top half of next function (enforced with #undef). */
|
3097
|
1163 #define DECLARE_DEBUG_FONTNAME(__xemacs_name) \
|
|
1164 Eistring *__xemacs_name; \
|
|
1165 do \
|
|
1166 { \
|
|
1167 __xemacs_name = debug_xft > 2 ? eistr_fullname \
|
|
1168 : debug_xft > 1 ? eistr_longname \
|
|
1169 : eistr_shortname; \
|
|
1170 } while (0)
|
3094
|
1171
|
|
1172 #endif /* USE_XFT */
|
|
1173
|
428
|
1174 /* find a font spec that matches font spec FONT and also matches
|
|
1175 (the registry of) CHARSET. */
|
|
1176 static Lisp_Object
|
872
|
1177 x_find_charset_font (Lisp_Object device, Lisp_Object font, Lisp_Object charset,
|
|
1178 int stage)
|
428
|
1179 {
|
444
|
1180 Extbyte **names;
|
428
|
1181 int count = 0;
|
442
|
1182 const Extbyte *patternext;
|
3174
|
1183 Lisp_Object result = Qnil;
|
428
|
1184 int i;
|
|
1185
|
3094
|
1186 /* #### with Xft need to handle second stage here -- sjt
|
|
1187 Hm. Or maybe not. That would be cool. :-) */
|
872
|
1188 if (stage)
|
|
1189 return Qnil;
|
|
1190
|
3094
|
1191 #ifdef USE_XFT
|
|
1192 /* Fontconfig converts all FreeType names to UTF-8 before passing them
|
|
1193 back to callers---see fcfreetype.c (FcFreeTypeQuery).
|
|
1194 I don't believe this is documented. */
|
|
1195
|
|
1196 DEBUG_XFT1 (1, "confirming charset for font instance %s\n",
|
|
1197 XSTRING_DATA(font));
|
|
1198
|
|
1199 /* #### this looks like a fair amount of work, but the basic design
|
|
1200 has never been rethought, and it should be
|
|
1201
|
|
1202 what really should happen here is that we use FcFontSort (FcFontList?)
|
|
1203 to get a list of matching fonts, then pick the first (best) one that
|
|
1204 gives language or repertoire coverage.
|
|
1205 */
|
|
1206
|
|
1207 FcInit (); /* No-op if already initialized.
|
|
1208 In fontconfig 2.3.2, this cannot return
|
|
1209 failure, but that looks like a bug. We
|
|
1210 check for it with FcGetCurrentConfig(),
|
|
1211 which *can* fail. */
|
|
1212 if (!FcConfigGetCurrent()) /* #### We should expose FcInit* interfaces
|
|
1213 to LISP and decide when to reinitialize
|
|
1214 intelligently. */
|
|
1215 stderr_out ("Failed fontconfig initialization\n");
|
|
1216 else
|
|
1217 {
|
|
1218 FcPattern *fontxft; /* long-lived, freed at end of this block */
|
|
1219 FcResult fcresult;
|
|
1220 FcConfig *fcc;
|
|
1221 FcChar8 *lang = "en"; /* #### fix this bogus hack! */
|
|
1222 FcCharSet *fccs = NULL;
|
|
1223 DECLARE_EISTRING (eistr_shortname); /* user-friendly nickname */
|
|
1224 DECLARE_EISTRING (eistr_longname); /* omit FC_LANG and FC_CHARSET */
|
|
1225 DECLARE_EISTRING (eistr_fullname); /* everything */
|
|
1226
|
3360
|
1227 LISP_STRING_TO_EXTERNAL (font, patternext, Qfc_font_name_encoding);
|
3094
|
1228 fcc = FcConfigGetCurrent ();
|
|
1229
|
|
1230 /* parse the name, do the substitutions, and match the font */
|
|
1231
|
|
1232 {
|
|
1233 FcPattern *p = FcNameParse (patternext);
|
|
1234 PRINT_XFT_PATTERN (3, "FcNameParse'ed name is %s\n", p);
|
|
1235 /* #### Next two return FcBool, but what does the return mean? */
|
|
1236 /* The order is correct according the fontconfig docs. */
|
|
1237 FcConfigSubstitute (fcc, p, FcMatchPattern);
|
|
1238 PRINT_XFT_PATTERN (2, "FcConfigSubstitute'ed name is %s\n", p);
|
|
1239 FcDefaultSubstitute (p);
|
|
1240 PRINT_XFT_PATTERN (3, "FcDefaultSubstitute'ed name is %s\n", p);
|
|
1241 /* #### check fcresult of following match? */
|
|
1242 fontxft = FcFontMatch (fcc, p, &fcresult);
|
|
1243 /* this prints the long fontconfig name */
|
|
1244 PRINT_XFT_PATTERN (1, "FcFontMatch'ed name is %s\n", fontxft);
|
|
1245 FcPatternDestroy (p);
|
|
1246 }
|
|
1247
|
|
1248 /* heuristic to give reasonable-length names for debug reports
|
|
1249
|
|
1250 I considered #ifdef SUPPORT_FULL_FONTCONFIG_NAME etc but that's
|
|
1251 pointless. We're just going to remove this code once the font/
|
|
1252 face refactoring is done, but until then it could be very useful.
|
|
1253 */
|
|
1254 {
|
|
1255 FcPattern *p = FcFontRenderPrepare (fcc, fontxft, fontxft);
|
|
1256 FcChar8 *name;
|
|
1257
|
|
1258 /* full name, including language coverage and repertoire */
|
|
1259 name = FcNameUnparse (p);
|
3360
|
1260 eicpy_ext (eistr_fullname, name, Qfc_font_name_encoding);
|
3094
|
1261 free (name);
|
|
1262
|
|
1263 /* long name, omitting coverage and repertoire, plus a number
|
|
1264 of rarely useful properties */
|
|
1265 FcPatternDel (p, FC_CHARSET);
|
|
1266 FcPatternDel (p, FC_LANG);
|
|
1267 FcPatternDel (p, FC_WIDTH);
|
|
1268 FcPatternDel (p, FC_SPACING);
|
|
1269 FcPatternDel (p, FC_HINTING);
|
|
1270 FcPatternDel (p, FC_VERTICAL_LAYOUT);
|
|
1271 FcPatternDel (p, FC_AUTOHINT);
|
|
1272 FcPatternDel (p, FC_GLOBAL_ADVANCE);
|
|
1273 FcPatternDel (p, FC_INDEX);
|
|
1274 FcPatternDel (p, FC_SCALE);
|
|
1275 FcPatternDel (p, FC_FONTVERSION);
|
|
1276 name = FcNameUnparse (p);
|
3360
|
1277 eicpy_ext (eistr_longname, name, Qfc_font_name_encoding);
|
3094
|
1278 free (name);
|
|
1279
|
|
1280 /* nickname, just family and size, but
|
|
1281 "family" names usually have style, slant, and weight */
|
|
1282 FcPatternDel (p, FC_FOUNDRY);
|
|
1283 FcPatternDel (p, FC_STYLE);
|
|
1284 FcPatternDel (p, FC_SLANT);
|
|
1285 FcPatternDel (p, FC_WEIGHT);
|
|
1286 FcPatternDel (p, FC_PIXEL_SIZE);
|
|
1287 FcPatternDel (p, FC_OUTLINE);
|
|
1288 FcPatternDel (p, FC_SCALABLE);
|
|
1289 FcPatternDel (p, FC_DPI);
|
|
1290 name = FcNameUnparse (p);
|
3360
|
1291 eicpy_ext (eistr_shortname, name, Qfc_font_name_encoding);
|
3094
|
1292 free (name);
|
|
1293
|
|
1294 FcPatternDestroy (p);
|
|
1295 }
|
|
1296
|
|
1297 /* The language approach may better in the long run, but we can't use
|
|
1298 it based on Mule charsets; fontconfig doesn't provide a way to test
|
|
1299 for unions of languages, etc. That will require support from the
|
|
1300 text module.
|
|
1301
|
|
1302 Optimization: cache the generated FcCharSet in the Mule charset.
|
|
1303 Don't forget to destroy it if the Mule charset gets deallocated. */
|
|
1304
|
3433
|
1305 {
|
|
1306 /* This block possibly should be a function, but it generates
|
|
1307 multiple values. I find the "pass an address to return the
|
|
1308 value in" idiom opaque, so prefer a block. */
|
|
1309 struct charset_reporter *cr;
|
|
1310 for (cr = charset_table;
|
|
1311 cr->charset && !EQ (*(cr->charset), charset);
|
|
1312 cr++)
|
|
1313 ;
|
3094
|
1314
|
3433
|
1315 if (cr->rfc3066)
|
|
1316 {
|
|
1317 DECLARE_DEBUG_FONTNAME (name);
|
|
1318 CHECKING_LANG (0, eidata(name), cr->language);
|
|
1319 lang = cr->rfc3066;
|
|
1320 }
|
|
1321 else if (cr->charset)
|
|
1322 {
|
|
1323 /* what the hey, build 'em on the fly */
|
|
1324 /* #### in the case of error this could return NULL! */
|
|
1325 fccs = mule_to_fc_charset (charset);
|
|
1326 lang = XSTRING_DATA (XSYMBOL (XCHARSET_NAME (charset))-> name);
|
|
1327 }
|
|
1328 else
|
|
1329 {
|
|
1330 /* OK, we fell off the end of the table */
|
|
1331 warn_when_safe_lispobj (intern ("xft"), intern ("alert"),
|
|
1332 list2 (build_string ("unchecked charset"),
|
|
1333 charset));
|
|
1334 }
|
3094
|
1335 /* default to "en"
|
|
1336 #### THIS IS WRONG, WRONG, WRONG!!
|
|
1337 It is why we never fall through to XLFD-checking. */
|
3433
|
1338 }
|
3094
|
1339
|
|
1340 ASSERT_ASCTEXT_ASCII(lang);
|
|
1341
|
|
1342 if (fccs)
|
|
1343 {
|
|
1344 /* check for character set coverage */
|
|
1345 int i = 0;
|
|
1346 FcCharSet *v;
|
|
1347 FcResult r = FcPatternGetCharSet (fontxft, FC_CHARSET, i, &v);
|
|
1348
|
|
1349 if (r == FcResultTypeMismatch)
|
|
1350 {
|
|
1351 DEBUG_XFT0 (0, "Unexpected type return in charset value\n");
|
|
1352 result = Qnil;
|
|
1353 }
|
|
1354 else if (r == FcResultMatch && FcCharSetIsSubset (fccs, v))
|
|
1355 {
|
|
1356 /* The full pattern with the bitmap coverage is massively
|
|
1357 unwieldy, but the shorter names are's just *wrong*. We
|
|
1358 should have the full thing internally as truename, and
|
|
1359 filter stuff the client doesn't want to see on output.
|
|
1360 Should we just store it into the truename right here? */
|
3097
|
1361 DECLARE_DEBUG_FONTNAME (name);
|
|
1362 DEBUG_XFT2 (0, "Xft font %s supports %s\n",
|
|
1363 eidata(name), lang);
|
3094
|
1364 #ifdef RETURN_LONG_FONTCONFIG_NAMES
|
|
1365 result = eimake_string(eistr_fullname);
|
|
1366 #else
|
|
1367 result = eimake_string(eistr_longname);
|
|
1368 #endif
|
|
1369 }
|
|
1370 else
|
|
1371 {
|
3097
|
1372 DECLARE_DEBUG_FONTNAME (name);
|
|
1373 DEBUG_XFT2 (0, "Xft font %s doesn't support %s\n",
|
|
1374 eidata(name), lang);
|
3094
|
1375 result = Qnil;
|
|
1376 }
|
|
1377
|
|
1378 /* clean up */
|
|
1379 FcCharSetDestroy (fccs);
|
|
1380 }
|
|
1381 else
|
|
1382 {
|
|
1383 /* check for language coverage */
|
|
1384 int i = 0;
|
|
1385 FcValue v;
|
|
1386 /* the main event */
|
|
1387 FcResult r = FcPatternGet (fontxft, FC_LANG, i, &v);
|
|
1388
|
|
1389 if (r == FcResultMatch)
|
|
1390 {
|
|
1391 if (v.type != FcTypeLangSet) /* excessive paranoia */
|
|
1392 {
|
|
1393 ASSERT_ASCTEXT_ASCII(FcTypeOfValueToString(v));
|
|
1394 /* Urk! Fall back and punt to core font. */
|
|
1395 DEBUG_XFT1 (0, "Unexpected type of lang value (%s)\n",
|
|
1396 FcTypeOfValueToString (v));
|
|
1397 result = Qnil;
|
|
1398 }
|
|
1399 else if (FcLangSetHasLang (v.u.l, lang) != FcLangDifferentLang)
|
|
1400 {
|
3097
|
1401 DECLARE_DEBUG_FONTNAME (name);
|
|
1402 DEBUG_XFT2 (0, "Xft font %s supports %s\n",
|
|
1403 eidata(name), lang);
|
3094
|
1404 #ifdef RETURN_LONG_FONTCONFIG_NAMES
|
|
1405 result = eimake_string(eistr_fullname);
|
|
1406 #else
|
|
1407 result = eimake_string(eistr_longname);
|
|
1408 #endif
|
|
1409 }
|
|
1410 else
|
|
1411 {
|
3097
|
1412 DECLARE_DEBUG_FONTNAME (name);
|
|
1413 DEBUG_XFT2 (0, "Xft font %s doesn't support %s\n",
|
|
1414 eidata(name), lang);
|
3094
|
1415 result = Qnil;
|
|
1416 }
|
|
1417 }
|
|
1418 else
|
|
1419 {
|
|
1420 ASSERT_ASCTEXT_ASCII(FcResultToString(r));
|
|
1421 DEBUG_XFT1 (0, "Getting lang: unexpected result=%s\n",
|
|
1422 FcResultToString (r));
|
|
1423 result = Qnil;
|
|
1424 }
|
|
1425 }
|
|
1426
|
|
1427 /* clean up and maybe return */
|
|
1428 FcPatternDestroy (fontxft);
|
|
1429 if (!UNBOUNDP (result))
|
|
1430 return result;
|
|
1431 }
|
|
1432
|
|
1433 DEBUG_XFT1 (0, "shit happens, try X11 charset match for %s\n",
|
|
1434 XSTRING_DATA(font));
|
3097
|
1435 #undef DECLARE_DEBUG_FONTNAME
|
3094
|
1436 #endif /* USE_XFT */
|
|
1437
|
442
|
1438 LISP_STRING_TO_EXTERNAL (font, patternext, Qx_font_name_encoding);
|
428
|
1439 names = XListFonts (DEVICE_X_DISPLAY (XDEVICE (device)),
|
|
1440 patternext, MAX_FONT_COUNT, &count);
|
440
|
1441 /* #### This code seems awfully bogus -- mrb */
|
3094
|
1442 /* #### fontconfig does it better -- sjt */
|
428
|
1443 for (i = 0; i < count; i ++)
|
|
1444 {
|
867
|
1445 const Ibyte *intname;
|
444
|
1446 Bytecount intlen;
|
428
|
1447
|
444
|
1448 TO_INTERNAL_FORMAT (C_STRING, names[i],
|
|
1449 ALLOCA, (intname, intlen),
|
|
1450 Qx_font_name_encoding);
|
428
|
1451 if (x_font_spec_matches_charset (XDEVICE (device), charset,
|
872
|
1452 intname, Qnil, 0, -1, 0))
|
428
|
1453 {
|
3209
|
1454 result = build_ext_string ((const Extbyte *) intname,
|
|
1455 Qx_font_name_encoding);
|
428
|
1456 break;
|
|
1457 }
|
|
1458 }
|
|
1459
|
|
1460 if (names)
|
|
1461 XFreeFontNames (names);
|
|
1462
|
|
1463 /* Check for a short font name. */
|
|
1464 if (NILP (result)
|
|
1465 && x_font_spec_matches_charset (XDEVICE (device), charset, 0,
|
872
|
1466 font, 0, -1, 0))
|
428
|
1467 return font;
|
|
1468
|
|
1469 return result;
|
|
1470 }
|
|
1471
|
|
1472 #endif /* MULE */
|
|
1473
|
|
1474
|
|
1475 /************************************************************************/
|
|
1476 /* initialization */
|
|
1477 /************************************************************************/
|
|
1478
|
|
1479 void
|
|
1480 syms_of_objects_x (void)
|
|
1481 {
|
|
1482 }
|
|
1483
|
|
1484 void
|
|
1485 console_type_create_objects_x (void)
|
|
1486 {
|
|
1487 /* object methods */
|
|
1488
|
|
1489 CONSOLE_HAS_METHOD (x, initialize_color_instance);
|
|
1490 CONSOLE_HAS_METHOD (x, print_color_instance);
|
|
1491 CONSOLE_HAS_METHOD (x, finalize_color_instance);
|
|
1492 CONSOLE_HAS_METHOD (x, color_instance_equal);
|
|
1493 CONSOLE_HAS_METHOD (x, color_instance_hash);
|
|
1494 CONSOLE_HAS_METHOD (x, color_instance_rgb_components);
|
|
1495 CONSOLE_HAS_METHOD (x, valid_color_name_p);
|
2527
|
1496 CONSOLE_HAS_METHOD (x, color_list);
|
428
|
1497
|
|
1498 CONSOLE_HAS_METHOD (x, initialize_font_instance);
|
|
1499 CONSOLE_HAS_METHOD (x, print_font_instance);
|
|
1500 CONSOLE_HAS_METHOD (x, finalize_font_instance);
|
|
1501 CONSOLE_HAS_METHOD (x, font_instance_truename);
|
|
1502 CONSOLE_HAS_METHOD (x, font_instance_properties);
|
2527
|
1503 CONSOLE_HAS_METHOD (x, font_list);
|
428
|
1504 #ifdef MULE
|
|
1505 CONSOLE_HAS_METHOD (x, find_charset_font);
|
|
1506 CONSOLE_HAS_METHOD (x, font_spec_matches_charset);
|
|
1507 #endif
|
|
1508 }
|
|
1509
|
|
1510 void
|
|
1511 vars_of_objects_x (void)
|
|
1512 {
|
|
1513 DEFVAR_BOOL ("x-handle-non-fully-specified-fonts",
|
|
1514 &x_handle_non_fully_specified_fonts /*
|
|
1515 If this is true then fonts which do not have all characters specified
|
|
1516 will be considered to be proportional width even if they are actually
|
|
1517 fixed-width. If this is not done then characters which are supposed to
|
|
1518 have 0 width may appear to actually have some width.
|
|
1519
|
|
1520 Note: While setting this to t guarantees correct output in all
|
|
1521 circumstances, it also causes a noticeable performance hit when using
|
|
1522 fixed-width fonts. Since most people don't use characters which could
|
|
1523 cause problems this is set to nil by default.
|
|
1524 */ );
|
|
1525 x_handle_non_fully_specified_fonts = 0;
|
3094
|
1526
|
|
1527 #ifdef USE_XFT
|
|
1528 Fprovide (intern ("xft-fonts"));
|
|
1529 #endif
|
428
|
1530 }
|
|
1531
|
|
1532 void
|
|
1533 Xatoms_of_objects_x (struct device *d)
|
|
1534 {
|
|
1535 Display *D = DEVICE_X_DISPLAY (d);
|
|
1536
|
|
1537 DEVICE_XATOM_FOUNDRY (d) = XInternAtom (D, "FOUNDRY", False);
|
|
1538 DEVICE_XATOM_FAMILY_NAME (d) = XInternAtom (D, "FAMILY_NAME", False);
|
|
1539 DEVICE_XATOM_WEIGHT_NAME (d) = XInternAtom (D, "WEIGHT_NAME", False);
|
|
1540 DEVICE_XATOM_SLANT (d) = XInternAtom (D, "SLANT", False);
|
|
1541 DEVICE_XATOM_SETWIDTH_NAME (d) = XInternAtom (D, "SETWIDTH_NAME", False);
|
|
1542 DEVICE_XATOM_ADD_STYLE_NAME (d) = XInternAtom (D, "ADD_STYLE_NAME", False);
|
|
1543 DEVICE_XATOM_PIXEL_SIZE (d) = XInternAtom (D, "PIXEL_SIZE", False);
|
|
1544 DEVICE_XATOM_POINT_SIZE (d) = XInternAtom (D, "POINT_SIZE", False);
|
|
1545 DEVICE_XATOM_RESOLUTION_X (d) = XInternAtom (D, "RESOLUTION_X", False);
|
|
1546 DEVICE_XATOM_RESOLUTION_Y (d) = XInternAtom (D, "RESOLUTION_Y", False);
|
|
1547 DEVICE_XATOM_SPACING (d) = XInternAtom (D, "SPACING", False);
|
|
1548 DEVICE_XATOM_AVERAGE_WIDTH (d) = XInternAtom (D, "AVERAGE_WIDTH", False);
|
|
1549 DEVICE_XATOM_CHARSET_REGISTRY(d) = XInternAtom (D, "CHARSET_REGISTRY",False);
|
|
1550 DEVICE_XATOM_CHARSET_ENCODING(d) = XInternAtom (D, "CHARSET_ENCODING",False);
|
|
1551 }
|