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
|
3169
|
696 /* XListFonts doesn't allocate memory unconditionally based on this. (For
|
|
697 XFree86 in 2005, at least. */
|
|
698 #define MAX_FONT_COUNT INT_MAX
|
428
|
699
|
442
|
700 static Extbyte *
|
|
701 truename_via_XListFonts (Display *dpy, Extbyte *font_name)
|
428
|
702 {
|
442
|
703 Extbyte *result = 0;
|
444
|
704 Extbyte **names;
|
428
|
705 int count = 0;
|
|
706
|
|
707 #ifndef XOPENFONT_SORTS
|
|
708 /* In a sensible world, the first font returned by XListFonts()
|
|
709 would be the font that XOpenFont() would use. */
|
|
710 names = XListFonts (dpy, font_name, 1, &count);
|
|
711 if (count) result = names [0];
|
|
712 #else
|
|
713 /* But the world I live in is much more perverse. */
|
|
714 names = XListFonts (dpy, font_name, MAX_FONT_COUNT, &count);
|
3094
|
715 /* Find the lexicographic minimum of names[].
|
|
716 (#### Should we be comparing case-insensitively?) */
|
428
|
717 while (count--)
|
3094
|
718 /* [[ !!#### Not Mule-friendly ]]
|
|
719 Doesn't matter, XLFDs are HPC (old) or Latin1 (modern). If they
|
|
720 aren't, who knows what they are? -- sjt */
|
428
|
721 if (result == 0 || (strcmp (result, names [count]) < 0))
|
|
722 result = names [count];
|
|
723 #endif
|
|
724
|
|
725 if (result)
|
|
726 result = xstrdup (result);
|
|
727 if (names)
|
|
728 XFreeFontNames (names);
|
|
729
|
|
730 return result; /* this must be freed by caller if non-0 */
|
|
731 }
|
|
732
|
|
733 static Lisp_Object
|
442
|
734 x_font_truename (Display *dpy, Extbyte *name, XFontStruct *font)
|
428
|
735 {
|
442
|
736 Extbyte *truename_FONT = 0;
|
|
737 Extbyte *truename_random = 0;
|
|
738 Extbyte *truename = 0;
|
428
|
739
|
|
740 /* The search order is:
|
|
741 - if FONT property exists, and is a valid name, return it.
|
|
742 - if the other props exist, and add up to a valid name, return it.
|
|
743 - if we find a matching name with XListFonts, return it.
|
|
744 - if FONT property exists, return it regardless.
|
|
745 - if other props exist, return the resultant name regardless.
|
|
746 - else return 0.
|
|
747 */
|
|
748
|
|
749 truename = truename_FONT = truename_via_FONT_prop (dpy, font);
|
|
750 if (truename && !valid_x_font_name_p (dpy, truename))
|
|
751 truename = 0;
|
|
752 if (!truename)
|
|
753 truename = truename_random = truename_via_random_props (dpy, font);
|
|
754 if (truename && !valid_x_font_name_p (dpy, truename))
|
|
755 truename = 0;
|
|
756 if (!truename && name)
|
|
757 truename = truename_via_XListFonts (dpy, name);
|
|
758
|
|
759 if (!truename)
|
|
760 {
|
|
761 /* Gag - we weren't able to find a seemingly-valid truename.
|
|
762 Well, maybe we're on one of those braindead systems where
|
|
763 XListFonts() and XLoadFont() are in violent disagreement.
|
|
764 If we were able to compute a truename, try using that even
|
|
765 if evidence suggests that it's not a valid name - because
|
|
766 maybe it is, really, and that's better than nothing.
|
|
767 X Windows: You'll envy the dead.
|
|
768 */
|
|
769 if (truename_FONT)
|
|
770 truename = truename_FONT;
|
|
771 else if (truename_random)
|
|
772 truename = truename_random;
|
|
773 }
|
|
774
|
|
775 /* One or both of these are not being used - free them. */
|
|
776 if (truename_FONT && truename_FONT != truename)
|
|
777 XFree (truename_FONT);
|
|
778 if (truename_random && truename_random != truename)
|
|
779 XFree (truename_random);
|
|
780
|
|
781 if (truename)
|
|
782 {
|
442
|
783 Lisp_Object result = build_ext_string (truename, Qx_font_name_encoding);
|
428
|
784 XFree (truename);
|
|
785 return result;
|
|
786 }
|
|
787 else
|
|
788 return Qnil;
|
|
789 }
|
|
790
|
|
791 static Lisp_Object
|
578
|
792 x_font_instance_truename (Lisp_Font_Instance *f, Error_Behavior errb)
|
428
|
793 {
|
|
794 struct device *d = XDEVICE (f->device);
|
3094
|
795 Display *dpy = DEVICE_X_DISPLAY (d);
|
|
796 Extbyte *nameext;
|
|
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 {
|
3174
|
810 FONT_INSTANCE_TRUENAME (f) =
|
|
811 build_ext_string (res, Qxft_font_name_encoding);
|
3094
|
812 free (res);
|
|
813 return FONT_INSTANCE_TRUENAME (f);
|
|
814 }
|
|
815 else
|
|
816 {
|
|
817 maybe_signal_error (Qgui_error,
|
|
818 "Couldn't unparse Xft font to truename",
|
|
819 Qnil, Qfont, errb);
|
|
820 /* used to return Qnil here */
|
|
821 }
|
|
822 }
|
|
823 #endif /* USE_XFT */
|
|
824
|
|
825 /* OK, fall back to core font. */
|
|
826 if (NILP (FONT_INSTANCE_TRUENAME (f))
|
|
827 && FONT_INSTANCE_X_FONT (f))
|
|
828 {
|
3286
|
829 nameext = NEW_LISP_STRING_TO_EXTERNAL (f->name, Qx_font_name_encoding);
|
3094
|
830 FONT_INSTANCE_TRUENAME (f) =
|
|
831 x_font_truename (dpy, nameext, FONT_INSTANCE_X_FONT (f));
|
|
832 }
|
428
|
833
|
872
|
834 if (NILP (FONT_INSTANCE_TRUENAME (f)))
|
428
|
835 {
|
3094
|
836 /* Urk, no luck. Whine about our bad luck and exit. */
|
|
837 Lisp_Object font_instance = wrap_font_instance (f);
|
|
838
|
|
839
|
|
840 maybe_signal_error (Qgui_error, "Couldn't determine font truename",
|
|
841 font_instance, Qfont, errb);
|
|
842 /* Ok, just this once, return the font name as the truename.
|
|
843 (This is only used by Fequal() right now.) */
|
|
844 return f->name;
|
|
845 }
|
442
|
846
|
3094
|
847 /* Return what we found. */
|
872
|
848 return FONT_INSTANCE_TRUENAME (f);
|
428
|
849 }
|
|
850
|
|
851 static Lisp_Object
|
440
|
852 x_font_instance_properties (Lisp_Font_Instance *f)
|
428
|
853 {
|
|
854 struct device *d = XDEVICE (f->device);
|
|
855 int i;
|
|
856 Lisp_Object result = Qnil;
|
444
|
857 Display *dpy = DEVICE_X_DISPLAY (d);
|
3094
|
858 XFontProp *props = NULL;
|
428
|
859
|
3094
|
860 /* #### really should hack Xft fonts, too
|
|
861 Strategy: fontconfig must have an iterator for this purpose. */
|
|
862 if (! FONT_INSTANCE_X_FONT (f)) return result;
|
|
863
|
|
864 props = FONT_INSTANCE_X_FONT (f)->properties;
|
428
|
865 for (i = FONT_INSTANCE_X_FONT (f)->n_properties - 1; i >= 0; i--)
|
|
866 {
|
|
867 Lisp_Object name, value;
|
|
868 Atom atom = props [i].name;
|
867
|
869 Ibyte *name_str = 0;
|
647
|
870 Bytecount name_len;
|
442
|
871 Extbyte *namestrext = XGetAtomName (dpy, atom);
|
|
872
|
|
873 if (namestrext)
|
444
|
874 TO_INTERNAL_FORMAT (C_STRING, namestrext,
|
|
875 ALLOCA, (name_str, name_len),
|
|
876 Qx_atom_name_encoding);
|
442
|
877
|
771
|
878 name = (name_str ? intern_int (name_str) : Qnil);
|
428
|
879 if (name_str &&
|
|
880 (atom == XA_FONT ||
|
|
881 atom == DEVICE_XATOM_FOUNDRY (d) ||
|
|
882 atom == DEVICE_XATOM_FAMILY_NAME (d) ||
|
|
883 atom == DEVICE_XATOM_WEIGHT_NAME (d) ||
|
|
884 atom == DEVICE_XATOM_SLANT (d) ||
|
|
885 atom == DEVICE_XATOM_SETWIDTH_NAME (d) ||
|
|
886 atom == DEVICE_XATOM_ADD_STYLE_NAME (d) ||
|
|
887 atom == DEVICE_XATOM_SPACING (d) ||
|
|
888 atom == DEVICE_XATOM_CHARSET_REGISTRY (d) ||
|
|
889 atom == DEVICE_XATOM_CHARSET_ENCODING (d) ||
|
2367
|
890 !qxestrcmp_ascii (name_str, "CHARSET_COLLECTIONS") ||
|
|
891 !qxestrcmp_ascii (name_str, "FONTNAME_REGISTRY") ||
|
|
892 !qxestrcmp_ascii (name_str, "CLASSIFICATION") ||
|
|
893 !qxestrcmp_ascii (name_str, "COPYRIGHT") ||
|
|
894 !qxestrcmp_ascii (name_str, "DEVICE_FONT_NAME") ||
|
|
895 !qxestrcmp_ascii (name_str, "FULL_NAME") ||
|
|
896 !qxestrcmp_ascii (name_str, "MONOSPACED") ||
|
|
897 !qxestrcmp_ascii (name_str, "QUALITY") ||
|
|
898 !qxestrcmp_ascii (name_str, "RELATIVE_SET") ||
|
|
899 !qxestrcmp_ascii (name_str, "RELATIVE_WEIGHT") ||
|
|
900 !qxestrcmp_ascii (name_str, "STYLE")))
|
428
|
901 {
|
442
|
902 Extbyte *val_str = XGetAtomName (dpy, props [i].card32);
|
|
903
|
|
904 value = (val_str ? build_ext_string (val_str, Qx_atom_name_encoding)
|
|
905 : Qnil);
|
428
|
906 }
|
|
907 else
|
|
908 value = make_int (props [i].card32);
|
442
|
909 if (namestrext) XFree (namestrext);
|
428
|
910 result = Fcons (Fcons (name, value), result);
|
|
911 }
|
|
912 return result;
|
|
913 }
|
|
914
|
|
915 static Lisp_Object
|
2527
|
916 x_font_list (Lisp_Object pattern, Lisp_Object device, Lisp_Object maxnumber)
|
428
|
917 {
|
444
|
918 Extbyte **names;
|
428
|
919 int count = 0;
|
1701
|
920 int max_number = MAX_FONT_COUNT;
|
428
|
921 Lisp_Object result = Qnil;
|
442
|
922 const Extbyte *patternext;
|
428
|
923
|
442
|
924 LISP_STRING_TO_EXTERNAL (pattern, patternext, Qx_font_name_encoding);
|
428
|
925
|
1701
|
926 if (!NILP(maxnumber) && INTP(maxnumber))
|
|
927 {
|
|
928 max_number = XINT(maxnumber);
|
|
929 }
|
|
930
|
428
|
931 names = XListFonts (DEVICE_X_DISPLAY (XDEVICE (device)),
|
1701
|
932 patternext, max_number, &count);
|
428
|
933 while (count--)
|
442
|
934 result = Fcons (build_ext_string (names[count], Qx_font_name_encoding),
|
|
935 result);
|
428
|
936 if (names)
|
|
937 XFreeFontNames (names);
|
|
938 return result;
|
|
939 }
|
|
940
|
|
941 #ifdef MULE
|
|
942
|
|
943 static int
|
3094
|
944 x_font_spec_matches_charset (struct device * USED_IF_XFT (d),
|
|
945 Lisp_Object charset,
|
867
|
946 const Ibyte *nonreloc, Lisp_Object reloc,
|
872
|
947 Bytecount offset, Bytecount length,
|
|
948 int stage)
|
428
|
949 {
|
872
|
950 if (stage)
|
3094
|
951 #ifdef USE_XFT
|
|
952 {
|
|
953 Display *dpy = DEVICE_X_DISPLAY (d);
|
|
954 Extbyte *extname;
|
|
955 XftFont *rf;
|
|
956 const Ibyte *the_nonreloc;
|
|
957
|
|
958 if (!NILP(reloc))
|
|
959 {
|
|
960 the_nonreloc = XSTRING_DATA (reloc);
|
|
961 LISP_STRING_TO_EXTERNAL (reloc, extname, Qx_font_name_encoding);
|
|
962 rf = xft_open_font_by_name (dpy, extname);
|
|
963 return 0; /* #### maybe this will compile and run ;) */
|
|
964 }
|
|
965 }
|
|
966 #else
|
872
|
967 return 0;
|
3094
|
968 #endif
|
872
|
969
|
428
|
970 if (UNBOUNDP (charset))
|
|
971 return 1;
|
|
972 /* Hack! Short font names don't have the registry in them,
|
|
973 so we just assume the user knows what they're doing in the
|
|
974 case of ASCII. For other charsets, you gotta give the
|
|
975 long form; sorry buster.
|
3094
|
976 #### FMH: this screws fontconfig/Xft?
|
|
977 STRATEGY: use fontconfig's ability to hack languages and character
|
|
978 sets (lang and charset properties).
|
|
979 #### Maybe we can use the fontconfig model to eliminate the difference
|
|
980 between faces and fonts? No - it looks like that would be an abuse
|
|
981 (fontconfig doesn't know about colors, although Xft does).
|
428
|
982 */
|
|
983 if (EQ (charset, Vcharset_ascii))
|
|
984 {
|
867
|
985 const Ibyte *the_nonreloc = nonreloc;
|
428
|
986 int i;
|
|
987 Bytecount the_length = length;
|
|
988
|
|
989 if (!the_nonreloc)
|
|
990 the_nonreloc = XSTRING_DATA (reloc);
|
|
991 fixup_internal_substring (nonreloc, reloc, offset, &the_length);
|
|
992 the_nonreloc += offset;
|
|
993 if (!memchr (the_nonreloc, '*', the_length))
|
|
994 {
|
|
995 for (i = 0;; i++)
|
|
996 {
|
867
|
997 const Ibyte *new_nonreloc = (const Ibyte *)
|
428
|
998 memchr (the_nonreloc, '-', the_length);
|
|
999 if (!new_nonreloc)
|
|
1000 break;
|
|
1001 new_nonreloc++;
|
|
1002 the_length -= new_nonreloc - the_nonreloc;
|
|
1003 the_nonreloc = new_nonreloc;
|
|
1004 }
|
|
1005
|
|
1006 /* If it has less than 5 dashes, it's a short font.
|
|
1007 Of course, long fonts always have 14 dashes or so, but short
|
|
1008 fonts never have more than 1 or 2 dashes, so this is some
|
|
1009 sort of reasonable heuristic. */
|
|
1010 if (i < 5)
|
|
1011 return 1;
|
|
1012 }
|
|
1013 }
|
|
1014
|
|
1015 return (fast_string_match (XCHARSET_REGISTRY (charset),
|
|
1016 nonreloc, reloc, offset, length, 1,
|
|
1017 ERROR_ME, 0) >= 0);
|
|
1018 }
|
|
1019
|
3094
|
1020 #ifdef USE_XFT
|
|
1021 /* #### debug functions: find a better place for us */
|
|
1022 const char *FcResultToString (FcResult r);
|
|
1023 const char *
|
|
1024 FcResultToString (FcResult r)
|
|
1025 {
|
|
1026 static char buffer[256];
|
|
1027 switch (r)
|
|
1028 {
|
|
1029 case FcResultMatch:
|
|
1030 return "FcResultMatch";
|
|
1031 case FcResultNoMatch:
|
|
1032 return "FcResultNoMatch";
|
|
1033 case FcResultTypeMismatch:
|
|
1034 return "FcResultTypeMismatch";
|
|
1035 case FcResultNoId:
|
|
1036 return "FcResultNoId";
|
|
1037 default:
|
|
1038 snprintf (buffer, 255, "FcResultUndocumentedValue (%d)", r);
|
|
1039 return buffer;
|
|
1040 }
|
|
1041 }
|
|
1042
|
|
1043 const char *FcTypeOfValueToString (FcValue v);
|
|
1044 const char *
|
|
1045 FcTypeOfValueToString (FcValue v)
|
|
1046 {
|
|
1047 static char buffer[256];
|
|
1048 switch (v.type)
|
|
1049 {
|
|
1050 case FcTypeMatrix:
|
|
1051 return "FcTypeMatrix";
|
|
1052 case FcTypeString:
|
|
1053 return "FcTypeString";
|
|
1054 case FcTypeVoid:
|
|
1055 return "FcTypeVoid";
|
|
1056 case FcTypeDouble:
|
|
1057 return "FcTypeDouble";
|
|
1058 case FcTypeInteger:
|
|
1059 return "FcTypeInteger";
|
|
1060 case FcTypeBool:
|
|
1061 return "FcTypeBool";
|
|
1062 case FcTypeCharSet:
|
|
1063 return "FcTypeCharSet";
|
|
1064 case FcTypeLangSet:
|
|
1065 return "FcTypeLangSet";
|
|
1066 /* #### There is no union member of this type, but there are void* and
|
|
1067 FcPattern* members, as of fontconfig.h FC_VERSION 10002 */
|
|
1068 case FcTypeFTFace:
|
|
1069 return "FcTypeFTFace";
|
|
1070 default:
|
|
1071 snprintf (buffer, 255, "FcTypeUndocumentedType (%d)", v.type);
|
|
1072 return buffer;
|
|
1073 }
|
|
1074 }
|
|
1075
|
|
1076 static FcCharSet *
|
|
1077 mule_to_fc_charset (Lisp_Object cs)
|
|
1078 {
|
|
1079 int ucode, i, j;
|
|
1080 FcCharSet *fccs;
|
|
1081
|
|
1082 CHECK_CHARSET (cs);
|
|
1083 fccs = FcCharSetCreate ();
|
|
1084 /* #### do we also need to deal with 94 vs. 96 charsets?
|
|
1085 ie, how are SP and DEL treated in ASCII? non-graphic should return -1 */
|
|
1086 if (1 == XCHARSET_DIMENSION (cs))
|
|
1087 /* Unicode tables are indexed by offsets from ASCII SP, not by ASCII */
|
|
1088 for (i = 0; i < 96; i++)
|
|
1089 {
|
|
1090 ucode = ((int *) XCHARSET_TO_UNICODE_TABLE (cs))[i];
|
|
1091 if (ucode >= 0)
|
|
1092 /* #### should check for allocation failure */
|
|
1093 FcCharSetAddChar (fccs, (FcChar32) ucode);
|
|
1094 }
|
|
1095 else if (2 == XCHARSET_DIMENSION (cs))
|
|
1096 /* Unicode tables are indexed by offsets from ASCII SP, not by ASCII */
|
|
1097 for (i = 0; i < 96; i++)
|
|
1098 for (j = 0; j < 96; j++)
|
|
1099 {
|
|
1100 ucode = ((int **) XCHARSET_TO_UNICODE_TABLE (cs))[i][j];
|
|
1101 if (ucode >= 0)
|
|
1102 /* #### should check for allocation failure */
|
|
1103 FcCharSetAddChar (fccs, (FcChar32) ucode);
|
|
1104 }
|
|
1105 else
|
|
1106 {
|
|
1107 FcCharSetDestroy (fccs);
|
|
1108 fccs = NULL;
|
|
1109 }
|
|
1110 return fccs;
|
|
1111 }
|
|
1112
|
|
1113 struct charset_reporter {
|
|
1114 Lisp_Object *charset;
|
|
1115 /* This is a debug facility, require ASCII. */
|
|
1116 Extbyte *language; /* ASCII, please */
|
|
1117 FcChar8 *rfc3066; /* ASCII, please */
|
|
1118 };
|
|
1119
|
|
1120 static struct charset_reporter charset_table[] =
|
|
1121 {
|
|
1122 /* #### It's my branch, my favorite charsets get checked first!
|
|
1123 That's a joke, Son.
|
|
1124 Ie, I don't know what I'm doing, so my charsets first is as good as
|
|
1125 any other arbitrary order. If you have a better idea, speak up! */
|
|
1126 { &Vcharset_ascii, "English", "en" },
|
|
1127 { &Vcharset_japanese_jisx0208, "Japanese", "ja" },
|
|
1128 { &Vcharset_japanese_jisx0212, "Japanese", "ja" },
|
|
1129 { &Vcharset_katakana_jisx0201, "Japanese", "ja" },
|
|
1130 { &Vcharset_latin_jisx0201, "Japanese", "ja" },
|
|
1131 { &Vcharset_japanese_jisx0208_1978, "Japanese", "ja" },
|
|
1132 { &Vcharset_greek_iso8859_7, "Greek", "el" },
|
|
1133 /* #### all the Chinese need checking
|
|
1134 Damn the blood-sucking ISO anyway. */
|
|
1135 { &Vcharset_chinese_gb2312, "simplified Chinese", "zh-CN" },
|
|
1136 { &Vcharset_korean_ksc5601, "Korean", "ko" },
|
|
1137 { &Vcharset_chinese_cns11643_1, "traditional Chinese", "zh-TW" },
|
|
1138 { &Vcharset_chinese_cns11643_2, "traditional Chinese", "zh-TW" },
|
|
1139 { &Vcharset_latin_iso8859_1, NULL, NULL },
|
|
1140 { &Vcharset_latin_iso8859_2, NULL, NULL },
|
|
1141 { &Vcharset_latin_iso8859_3, NULL, NULL },
|
|
1142 { &Vcharset_latin_iso8859_4, NULL, NULL },
|
|
1143 { &Vcharset_latin_iso8859_9, NULL, NULL },
|
|
1144 { &Vcharset_latin_iso8859_15, NULL, NULL },
|
|
1145 { &Vcharset_thai_tis620, NULL, NULL },
|
|
1146 { &Vcharset_arabic_iso8859_6, NULL, NULL },
|
|
1147 { &Vcharset_hebrew_iso8859_8, "Hebrew", "he" },
|
|
1148 { &Vcharset_cyrillic_iso8859_5, NULL, NULL },
|
|
1149 /* #### these probably are not quite right */
|
|
1150 { &Vcharset_chinese_big5_1, "traditional Chinese", "zh-TW" },
|
|
1151 { &Vcharset_chinese_big5_2, "traditional Chinese", "zh-TW" },
|
|
1152 { NULL, NULL, NULL }
|
|
1153 };
|
|
1154
|
|
1155 /* Choose appropriate font name for debug messages.
|
|
1156 Use only in the top half of next function (enforced with #undef). */
|
3097
|
1157 #define DECLARE_DEBUG_FONTNAME(__xemacs_name) \
|
|
1158 Eistring *__xemacs_name; \
|
|
1159 do \
|
|
1160 { \
|
|
1161 __xemacs_name = debug_xft > 2 ? eistr_fullname \
|
|
1162 : debug_xft > 1 ? eistr_longname \
|
|
1163 : eistr_shortname; \
|
|
1164 } while (0)
|
3094
|
1165
|
|
1166 #endif /* USE_XFT */
|
|
1167
|
428
|
1168 /* find a font spec that matches font spec FONT and also matches
|
|
1169 (the registry of) CHARSET. */
|
|
1170 static Lisp_Object
|
872
|
1171 x_find_charset_font (Lisp_Object device, Lisp_Object font, Lisp_Object charset,
|
|
1172 int stage)
|
428
|
1173 {
|
444
|
1174 Extbyte **names;
|
428
|
1175 int count = 0;
|
442
|
1176 const Extbyte *patternext;
|
3174
|
1177 Lisp_Object result = Qnil;
|
428
|
1178 int i;
|
|
1179
|
3094
|
1180 /* #### with Xft need to handle second stage here -- sjt
|
|
1181 Hm. Or maybe not. That would be cool. :-) */
|
872
|
1182 if (stage)
|
|
1183 return Qnil;
|
|
1184
|
3094
|
1185 #ifdef USE_XFT
|
|
1186 /* Fontconfig converts all FreeType names to UTF-8 before passing them
|
|
1187 back to callers---see fcfreetype.c (FcFreeTypeQuery).
|
|
1188 I don't believe this is documented. */
|
|
1189
|
|
1190 DEBUG_XFT1 (1, "confirming charset for font instance %s\n",
|
|
1191 XSTRING_DATA(font));
|
|
1192
|
|
1193 /* #### this looks like a fair amount of work, but the basic design
|
|
1194 has never been rethought, and it should be
|
|
1195
|
|
1196 what really should happen here is that we use FcFontSort (FcFontList?)
|
|
1197 to get a list of matching fonts, then pick the first (best) one that
|
|
1198 gives language or repertoire coverage.
|
|
1199 */
|
|
1200
|
|
1201 FcInit (); /* No-op if already initialized.
|
|
1202 In fontconfig 2.3.2, this cannot return
|
|
1203 failure, but that looks like a bug. We
|
|
1204 check for it with FcGetCurrentConfig(),
|
|
1205 which *can* fail. */
|
|
1206 if (!FcConfigGetCurrent()) /* #### We should expose FcInit* interfaces
|
|
1207 to LISP and decide when to reinitialize
|
|
1208 intelligently. */
|
|
1209 stderr_out ("Failed fontconfig initialization\n");
|
|
1210 else
|
|
1211 {
|
|
1212 FcPattern *fontxft; /* long-lived, freed at end of this block */
|
|
1213 FcResult fcresult;
|
|
1214 FcConfig *fcc;
|
|
1215 FcChar8 *lang = "en"; /* #### fix this bogus hack! */
|
|
1216 FcCharSet *fccs = NULL;
|
|
1217 DECLARE_EISTRING (eistr_shortname); /* user-friendly nickname */
|
|
1218 DECLARE_EISTRING (eistr_longname); /* omit FC_LANG and FC_CHARSET */
|
|
1219 DECLARE_EISTRING (eistr_fullname); /* everything */
|
|
1220
|
|
1221 LISP_STRING_TO_EXTERNAL (font, patternext, Qxft_font_name_encoding);
|
|
1222 fcc = FcConfigGetCurrent ();
|
|
1223
|
|
1224 /* parse the name, do the substitutions, and match the font */
|
|
1225
|
|
1226 {
|
|
1227 FcPattern *p = FcNameParse (patternext);
|
|
1228 PRINT_XFT_PATTERN (3, "FcNameParse'ed name is %s\n", p);
|
|
1229 /* #### Next two return FcBool, but what does the return mean? */
|
|
1230 /* The order is correct according the fontconfig docs. */
|
|
1231 FcConfigSubstitute (fcc, p, FcMatchPattern);
|
|
1232 PRINT_XFT_PATTERN (2, "FcConfigSubstitute'ed name is %s\n", p);
|
|
1233 FcDefaultSubstitute (p);
|
|
1234 PRINT_XFT_PATTERN (3, "FcDefaultSubstitute'ed name is %s\n", p);
|
|
1235 /* #### check fcresult of following match? */
|
|
1236 fontxft = FcFontMatch (fcc, p, &fcresult);
|
|
1237 /* this prints the long fontconfig name */
|
|
1238 PRINT_XFT_PATTERN (1, "FcFontMatch'ed name is %s\n", fontxft);
|
|
1239 FcPatternDestroy (p);
|
|
1240 }
|
|
1241
|
|
1242 /* heuristic to give reasonable-length names for debug reports
|
|
1243
|
|
1244 I considered #ifdef SUPPORT_FULL_FONTCONFIG_NAME etc but that's
|
|
1245 pointless. We're just going to remove this code once the font/
|
|
1246 face refactoring is done, but until then it could be very useful.
|
|
1247 */
|
|
1248 {
|
|
1249 FcPattern *p = FcFontRenderPrepare (fcc, fontxft, fontxft);
|
|
1250 FcChar8 *name;
|
|
1251
|
|
1252 /* full name, including language coverage and repertoire */
|
|
1253 name = FcNameUnparse (p);
|
|
1254 eicpy_ext (eistr_fullname, name, Qxft_font_name_encoding);
|
|
1255 free (name);
|
|
1256
|
|
1257 /* long name, omitting coverage and repertoire, plus a number
|
|
1258 of rarely useful properties */
|
|
1259 FcPatternDel (p, FC_CHARSET);
|
|
1260 FcPatternDel (p, FC_LANG);
|
|
1261 FcPatternDel (p, FC_WIDTH);
|
|
1262 FcPatternDel (p, FC_SPACING);
|
|
1263 FcPatternDel (p, FC_HINTING);
|
|
1264 FcPatternDel (p, FC_VERTICAL_LAYOUT);
|
|
1265 FcPatternDel (p, FC_AUTOHINT);
|
|
1266 FcPatternDel (p, FC_GLOBAL_ADVANCE);
|
|
1267 FcPatternDel (p, FC_INDEX);
|
|
1268 FcPatternDel (p, FC_SCALE);
|
|
1269 FcPatternDel (p, FC_FONTVERSION);
|
|
1270 name = FcNameUnparse (p);
|
|
1271 eicpy_ext (eistr_longname, name, Qxft_font_name_encoding);
|
|
1272 free (name);
|
|
1273
|
|
1274 /* nickname, just family and size, but
|
|
1275 "family" names usually have style, slant, and weight */
|
|
1276 FcPatternDel (p, FC_FOUNDRY);
|
|
1277 FcPatternDel (p, FC_STYLE);
|
|
1278 FcPatternDel (p, FC_SLANT);
|
|
1279 FcPatternDel (p, FC_WEIGHT);
|
|
1280 FcPatternDel (p, FC_PIXEL_SIZE);
|
|
1281 FcPatternDel (p, FC_OUTLINE);
|
|
1282 FcPatternDel (p, FC_SCALABLE);
|
|
1283 FcPatternDel (p, FC_DPI);
|
|
1284 name = FcNameUnparse (p);
|
|
1285 eicpy_ext (eistr_shortname, name, Qxft_font_name_encoding);
|
|
1286 free (name);
|
|
1287
|
|
1288 FcPatternDestroy (p);
|
|
1289 }
|
|
1290
|
|
1291 /* The language approach may better in the long run, but we can't use
|
|
1292 it based on Mule charsets; fontconfig doesn't provide a way to test
|
|
1293 for unions of languages, etc. That will require support from the
|
|
1294 text module.
|
|
1295
|
|
1296 Optimization: cache the generated FcCharSet in the Mule charset.
|
|
1297 Don't forget to destroy it if the Mule charset gets deallocated. */
|
|
1298
|
|
1299 struct charset_reporter *cr;
|
|
1300 for (cr = charset_table;
|
|
1301 cr->charset && !EQ (*(cr->charset), charset);
|
|
1302 cr++)
|
|
1303 ;
|
|
1304
|
|
1305 if (cr->rfc3066)
|
|
1306 {
|
3097
|
1307 DECLARE_DEBUG_FONTNAME (name);
|
|
1308 CHECKING_LANG (0, eidata(name), cr->language);
|
3094
|
1309 lang = cr->rfc3066;
|
|
1310 }
|
|
1311 else if (cr->charset)
|
|
1312 {
|
|
1313 /* what the hey, build 'em on the fly */
|
|
1314 /* #### in the case of error this could return NULL! */
|
|
1315 fccs = mule_to_fc_charset (charset);
|
|
1316 lang = XSTRING_DATA (XSYMBOL (XCHARSET_NAME (charset))-> name);
|
|
1317 }
|
|
1318 else
|
|
1319 {
|
|
1320 /* OK, we fell off the end of the table */
|
|
1321 warn_when_safe_lispobj (intern ("xft"), intern ("alert"),
|
|
1322 list2 (build_string ("unchecked charset"),
|
|
1323 charset));
|
|
1324 /* default to "en"
|
|
1325 #### THIS IS WRONG, WRONG, WRONG!!
|
|
1326 It is why we never fall through to XLFD-checking. */
|
|
1327 }
|
|
1328
|
|
1329 ASSERT_ASCTEXT_ASCII(lang);
|
|
1330
|
|
1331 if (fccs)
|
|
1332 {
|
|
1333 /* check for character set coverage */
|
|
1334 int i = 0;
|
|
1335 FcCharSet *v;
|
|
1336 FcResult r = FcPatternGetCharSet (fontxft, FC_CHARSET, i, &v);
|
|
1337
|
|
1338 if (r == FcResultTypeMismatch)
|
|
1339 {
|
|
1340 DEBUG_XFT0 (0, "Unexpected type return in charset value\n");
|
|
1341 result = Qnil;
|
|
1342 }
|
|
1343 else if (r == FcResultMatch && FcCharSetIsSubset (fccs, v))
|
|
1344 {
|
|
1345 /* The full pattern with the bitmap coverage is massively
|
|
1346 unwieldy, but the shorter names are's just *wrong*. We
|
|
1347 should have the full thing internally as truename, and
|
|
1348 filter stuff the client doesn't want to see on output.
|
|
1349 Should we just store it into the truename right here? */
|
3097
|
1350 DECLARE_DEBUG_FONTNAME (name);
|
|
1351 DEBUG_XFT2 (0, "Xft font %s supports %s\n",
|
|
1352 eidata(name), lang);
|
3094
|
1353 #ifdef RETURN_LONG_FONTCONFIG_NAMES
|
|
1354 result = eimake_string(eistr_fullname);
|
|
1355 #else
|
|
1356 result = eimake_string(eistr_longname);
|
|
1357 #endif
|
|
1358 }
|
|
1359 else
|
|
1360 {
|
3097
|
1361 DECLARE_DEBUG_FONTNAME (name);
|
|
1362 DEBUG_XFT2 (0, "Xft font %s doesn't support %s\n",
|
|
1363 eidata(name), lang);
|
3094
|
1364 result = Qnil;
|
|
1365 }
|
|
1366
|
|
1367 /* clean up */
|
|
1368 FcCharSetDestroy (fccs);
|
|
1369 }
|
|
1370 else
|
|
1371 {
|
|
1372 /* check for language coverage */
|
|
1373 int i = 0;
|
|
1374 FcValue v;
|
|
1375 /* the main event */
|
|
1376 FcResult r = FcPatternGet (fontxft, FC_LANG, i, &v);
|
|
1377
|
|
1378 if (r == FcResultMatch)
|
|
1379 {
|
|
1380 if (v.type != FcTypeLangSet) /* excessive paranoia */
|
|
1381 {
|
|
1382 ASSERT_ASCTEXT_ASCII(FcTypeOfValueToString(v));
|
|
1383 /* Urk! Fall back and punt to core font. */
|
|
1384 DEBUG_XFT1 (0, "Unexpected type of lang value (%s)\n",
|
|
1385 FcTypeOfValueToString (v));
|
|
1386 result = Qnil;
|
|
1387 }
|
|
1388 else if (FcLangSetHasLang (v.u.l, lang) != FcLangDifferentLang)
|
|
1389 {
|
3097
|
1390 DECLARE_DEBUG_FONTNAME (name);
|
|
1391 DEBUG_XFT2 (0, "Xft font %s supports %s\n",
|
|
1392 eidata(name), lang);
|
3094
|
1393 #ifdef RETURN_LONG_FONTCONFIG_NAMES
|
|
1394 result = eimake_string(eistr_fullname);
|
|
1395 #else
|
|
1396 result = eimake_string(eistr_longname);
|
|
1397 #endif
|
|
1398 }
|
|
1399 else
|
|
1400 {
|
3097
|
1401 DECLARE_DEBUG_FONTNAME (name);
|
|
1402 DEBUG_XFT2 (0, "Xft font %s doesn't support %s\n",
|
|
1403 eidata(name), lang);
|
3094
|
1404 result = Qnil;
|
|
1405 }
|
|
1406 }
|
|
1407 else
|
|
1408 {
|
|
1409 ASSERT_ASCTEXT_ASCII(FcResultToString(r));
|
|
1410 DEBUG_XFT1 (0, "Getting lang: unexpected result=%s\n",
|
|
1411 FcResultToString (r));
|
|
1412 result = Qnil;
|
|
1413 }
|
|
1414 }
|
|
1415
|
|
1416 /* clean up and maybe return */
|
|
1417 FcPatternDestroy (fontxft);
|
|
1418 if (!UNBOUNDP (result))
|
|
1419 return result;
|
|
1420 }
|
|
1421
|
|
1422 DEBUG_XFT1 (0, "shit happens, try X11 charset match for %s\n",
|
|
1423 XSTRING_DATA(font));
|
3097
|
1424 #undef DECLARE_DEBUG_FONTNAME
|
3094
|
1425 #endif /* USE_XFT */
|
|
1426
|
442
|
1427 LISP_STRING_TO_EXTERNAL (font, patternext, Qx_font_name_encoding);
|
428
|
1428 names = XListFonts (DEVICE_X_DISPLAY (XDEVICE (device)),
|
|
1429 patternext, MAX_FONT_COUNT, &count);
|
440
|
1430 /* #### This code seems awfully bogus -- mrb */
|
3094
|
1431 /* #### fontconfig does it better -- sjt */
|
428
|
1432 for (i = 0; i < count; i ++)
|
|
1433 {
|
867
|
1434 const Ibyte *intname;
|
444
|
1435 Bytecount intlen;
|
428
|
1436
|
444
|
1437 TO_INTERNAL_FORMAT (C_STRING, names[i],
|
|
1438 ALLOCA, (intname, intlen),
|
|
1439 Qx_font_name_encoding);
|
428
|
1440 if (x_font_spec_matches_charset (XDEVICE (device), charset,
|
872
|
1441 intname, Qnil, 0, -1, 0))
|
428
|
1442 {
|
3209
|
1443 result = build_ext_string ((const Extbyte *) intname,
|
|
1444 Qx_font_name_encoding);
|
428
|
1445 break;
|
|
1446 }
|
|
1447 }
|
|
1448
|
|
1449 if (names)
|
|
1450 XFreeFontNames (names);
|
|
1451
|
|
1452 /* Check for a short font name. */
|
|
1453 if (NILP (result)
|
|
1454 && x_font_spec_matches_charset (XDEVICE (device), charset, 0,
|
872
|
1455 font, 0, -1, 0))
|
428
|
1456 return font;
|
|
1457
|
|
1458 return result;
|
|
1459 }
|
|
1460
|
|
1461 #endif /* MULE */
|
|
1462
|
|
1463
|
|
1464 /************************************************************************/
|
|
1465 /* initialization */
|
|
1466 /************************************************************************/
|
|
1467
|
|
1468 void
|
|
1469 syms_of_objects_x (void)
|
|
1470 {
|
|
1471 }
|
|
1472
|
|
1473 void
|
|
1474 console_type_create_objects_x (void)
|
|
1475 {
|
|
1476 /* object methods */
|
|
1477
|
|
1478 CONSOLE_HAS_METHOD (x, initialize_color_instance);
|
|
1479 CONSOLE_HAS_METHOD (x, print_color_instance);
|
|
1480 CONSOLE_HAS_METHOD (x, finalize_color_instance);
|
|
1481 CONSOLE_HAS_METHOD (x, color_instance_equal);
|
|
1482 CONSOLE_HAS_METHOD (x, color_instance_hash);
|
|
1483 CONSOLE_HAS_METHOD (x, color_instance_rgb_components);
|
|
1484 CONSOLE_HAS_METHOD (x, valid_color_name_p);
|
2527
|
1485 CONSOLE_HAS_METHOD (x, color_list);
|
428
|
1486
|
|
1487 CONSOLE_HAS_METHOD (x, initialize_font_instance);
|
|
1488 CONSOLE_HAS_METHOD (x, print_font_instance);
|
|
1489 CONSOLE_HAS_METHOD (x, finalize_font_instance);
|
|
1490 CONSOLE_HAS_METHOD (x, font_instance_truename);
|
|
1491 CONSOLE_HAS_METHOD (x, font_instance_properties);
|
2527
|
1492 CONSOLE_HAS_METHOD (x, font_list);
|
428
|
1493 #ifdef MULE
|
|
1494 CONSOLE_HAS_METHOD (x, find_charset_font);
|
|
1495 CONSOLE_HAS_METHOD (x, font_spec_matches_charset);
|
|
1496 #endif
|
|
1497 }
|
|
1498
|
|
1499 void
|
|
1500 vars_of_objects_x (void)
|
|
1501 {
|
|
1502 DEFVAR_BOOL ("x-handle-non-fully-specified-fonts",
|
|
1503 &x_handle_non_fully_specified_fonts /*
|
|
1504 If this is true then fonts which do not have all characters specified
|
|
1505 will be considered to be proportional width even if they are actually
|
|
1506 fixed-width. If this is not done then characters which are supposed to
|
|
1507 have 0 width may appear to actually have some width.
|
|
1508
|
|
1509 Note: While setting this to t guarantees correct output in all
|
|
1510 circumstances, it also causes a noticeable performance hit when using
|
|
1511 fixed-width fonts. Since most people don't use characters which could
|
|
1512 cause problems this is set to nil by default.
|
|
1513 */ );
|
|
1514 x_handle_non_fully_specified_fonts = 0;
|
3094
|
1515
|
|
1516 #ifdef USE_XFT
|
|
1517 Fprovide (intern ("xft-fonts"));
|
|
1518 #endif
|
428
|
1519 }
|
|
1520
|
|
1521 void
|
|
1522 Xatoms_of_objects_x (struct device *d)
|
|
1523 {
|
|
1524 Display *D = DEVICE_X_DISPLAY (d);
|
|
1525
|
|
1526 DEVICE_XATOM_FOUNDRY (d) = XInternAtom (D, "FOUNDRY", False);
|
|
1527 DEVICE_XATOM_FAMILY_NAME (d) = XInternAtom (D, "FAMILY_NAME", False);
|
|
1528 DEVICE_XATOM_WEIGHT_NAME (d) = XInternAtom (D, "WEIGHT_NAME", False);
|
|
1529 DEVICE_XATOM_SLANT (d) = XInternAtom (D, "SLANT", False);
|
|
1530 DEVICE_XATOM_SETWIDTH_NAME (d) = XInternAtom (D, "SETWIDTH_NAME", False);
|
|
1531 DEVICE_XATOM_ADD_STYLE_NAME (d) = XInternAtom (D, "ADD_STYLE_NAME", False);
|
|
1532 DEVICE_XATOM_PIXEL_SIZE (d) = XInternAtom (D, "PIXEL_SIZE", False);
|
|
1533 DEVICE_XATOM_POINT_SIZE (d) = XInternAtom (D, "POINT_SIZE", False);
|
|
1534 DEVICE_XATOM_RESOLUTION_X (d) = XInternAtom (D, "RESOLUTION_X", False);
|
|
1535 DEVICE_XATOM_RESOLUTION_Y (d) = XInternAtom (D, "RESOLUTION_Y", False);
|
|
1536 DEVICE_XATOM_SPACING (d) = XInternAtom (D, "SPACING", False);
|
|
1537 DEVICE_XATOM_AVERAGE_WIDTH (d) = XInternAtom (D, "AVERAGE_WIDTH", False);
|
|
1538 DEVICE_XATOM_CHARSET_REGISTRY(d) = XInternAtom (D, "CHARSET_REGISTRY",False);
|
|
1539 DEVICE_XATOM_CHARSET_ENCODING(d) = XInternAtom (D, "CHARSET_ENCODING",False);
|
|
1540 }
|