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