3659
+ − 1 /* Shared object code between X and GTK -- include file.
+ − 2 Copyright (C) 1991-5, 1997 Free Software Foundation, Inc.
+ − 3 Copyright (C) 1995 Sun Microsystems, Inc.
+ − 4 Copyright (C) 1996, 2001, 2002, 2003 Ben Wing.
+ − 5
+ − 6 This file is part of XEmacs.
+ − 7
+ − 8 XEmacs is free software; you can redistribute it and/or modify it
+ − 9 under the terms of the GNU General Public License as published by the
+ − 10 Free Software Foundation; either version 2, or (at your option) any
+ − 11 later version.
+ − 12
+ − 13 XEmacs is distributed in the hope that it will be useful, but WITHOUT
+ − 14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ − 15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ − 16 for more details.
+ − 17
+ − 18 You should have received a copy of the GNU General Public License
+ − 19 along with XEmacs; see the file COPYING. If not, write to
+ − 20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ − 21 Boston, MA 02111-1307, USA. */
+ − 22
+ − 23 /* Synched up with: Not in FSF. */
+ − 24
+ − 25 /* Pango is ready for prime-time now, as far as I understand it. The GTK
+ − 26 people should be using that. Oh well. (Aidan Kehoe, Sat Nov 4 12:41:12
+ − 27 CET 2006) */
+ − 28
+ − 29 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)
+ − 30
+ − 31 #ifdef DEBUG_XEMACS
+ − 32 # define DEBUG_OBJECTS(FORMAT, ...) \
+ − 33 do { if (debug_x_objects) stderr_out(FORMAT, __VA_ARGS__); } while (0)
+ − 34 #else /* DEBUG_XEMACS */
+ − 35 # define DEBUG_OBJECTS(format, ...)
+ − 36 #endif /* DEBUG_XEMACS */
+ − 37
+ − 38 #elif defined(__GNUC__)
+ − 39
+ − 40 #ifdef DEBUG_XEMACS
+ − 41 # define DEBUG_OBJECTS(format, args...) \
+ − 42 do { if (debug_x_objects) stderr_out(format, args ); } while (0)
+ − 43 #else /* DEBUG_XEMACS */
+ − 44 # define DEBUG_OBJECTS(format, args...)
+ − 45 #endif /* DEBUG_XEMACS */
+ − 46
+ − 47 #else /* defined(__STDC_VERSION__) [...] */
+ − 48 # define DEBUG_OBJECTS (void)
+ − 49 #endif
+ − 50
+ − 51 #ifdef MULE
+ − 52
+ − 53 /* For some code it's reasonable to have only one copy and conditionalize
+ − 54 at run-time. For other code it isn't. */
+ − 55
+ − 56 static int
+ − 57 count_hyphens(const Ibyte *str, Bytecount length, Ibyte **last_hyphen)
+ − 58 {
+ − 59 int hyphen_count = 0;
+ − 60 const Ibyte *hyphening = str;
+ − 61 const Ibyte *new_hyphening;
+ − 62
+ − 63 for (hyphen_count = 0;
+ − 64 NULL != (new_hyphening = memchr((const void *)hyphening, '-', length));
+ − 65 hyphen_count++)
+ − 66 {
+ − 67 ++new_hyphening;
+ − 68 length -= new_hyphening - hyphening;
+ − 69 hyphening = new_hyphening;
+ − 70 }
+ − 71
+ − 72 if (NULL != last_hyphen)
+ − 73 {
+ − 74 *last_hyphen = (Ibyte *)hyphening;
+ − 75 }
+ − 76
+ − 77 return hyphen_count;
+ − 78 }
+ − 79
+ − 80 static int
+ − 81 #ifdef THIS_IS_GTK
+ − 82 gtk_font_spec_matches_charset (struct device * USED_IF_XFT (d),
+ − 83 Lisp_Object charset,
+ − 84 const Ibyte *nonreloc, Lisp_Object reloc,
+ − 85 Bytecount offset, Bytecount length,
+ − 86 enum font_specifier_matchspec_stages stage)
+ − 87 #else
+ − 88 x_font_spec_matches_charset (struct device * USED_IF_XFT (d),
+ − 89 Lisp_Object charset,
+ − 90 const Ibyte *nonreloc, Lisp_Object reloc,
+ − 91 Bytecount offset, Bytecount length,
+ − 92 enum font_specifier_matchspec_stages stage)
+ − 93 #endif
+ − 94 {
+ − 95 Lisp_Object registries = Qnil;
+ − 96 long i, registries_len;
+ − 97 const Ibyte *the_nonreloc;
+ − 98 Bytecount the_length;
+ − 99
+ − 100 the_nonreloc = nonreloc;
+ − 101 the_length = length;
+ − 102
+ − 103 if (!the_nonreloc)
+ − 104 the_nonreloc = XSTRING_DATA (reloc);
+ − 105 fixup_internal_substring (nonreloc, reloc, offset, &the_length);
+ − 106 the_nonreloc += offset;
+ − 107
+ − 108 #ifdef USE_XFT
+ − 109 if (stage)
+ − 110 {
+ − 111 Display *dpy = DEVICE_X_DISPLAY (d);
+ − 112 Extbyte *extname;
+ − 113 XftFont *rf;
+ − 114 const Ibyte *the_nonreloc;
+ − 115
+ − 116 if (!NILP(reloc))
+ − 117 {
+ − 118 the_nonreloc = XSTRING_DATA (reloc);
+ − 119 LISP_STRING_TO_EXTERNAL (reloc, extname, Qx_font_name_encoding);
+ − 120 rf = xft_open_font_by_name (dpy, extname);
+ − 121 return 0; /* #### maybe this will compile and run ;) */
+ − 122 /* Jesus, Stephen, what the fuck? */
+ − 123 }
+ − 124 }
+ − 125 #endif
+ − 126
+ − 127 /* Hmm, this smells bad. */
+ − 128 if (UNBOUNDP (charset))
+ − 129 return 1;
+ − 130
+ − 131 /* Hack! Short font names don't have the registry in them,
+ − 132 so we just assume the user knows what they're doing in the
+ − 133 case of ASCII. For other charsets, you gotta give the
+ − 134 long form; sorry buster.
+ − 135 #### FMH: this screws fontconfig/Xft?
+ − 136 STRATEGY: use fontconfig's ability to hack languages and character
+ − 137 sets (lang and charset properties).
+ − 138 #### Maybe we can use the fontconfig model to eliminate the difference
+ − 139 between faces and fonts? No - it looks like that would be an abuse
+ − 140 (fontconfig doesn't know about colors, although Xft does).
+ − 141 */
+ − 142 if (EQ (charset, Vcharset_ascii) &&
+ − 143 (!memchr (the_nonreloc, '*', the_length))
+ − 144 && (5 > (count_hyphens(the_nonreloc, the_length, NULL))))
+ − 145 {
+ − 146 return 1;
+ − 147 }
+ − 148
+ − 149 if (final == stage)
+ − 150 {
+ − 151 registries = Qunicode_registries;
+ − 152 }
+ − 153 else if (initial == stage)
+ − 154 {
+ − 155 registries = XCHARSET_REGISTRIES (charset);
+ − 156 if (NILP(registries))
+ − 157 {
+ − 158 return 0;
+ − 159 }
+ − 160 }
+ − 161 else assert(0);
+ − 162
+ − 163 CHECK_VECTOR (registries);
+ − 164 registries_len = XVECTOR_LENGTH(registries);
+ − 165
+ − 166 for (i = 0; i < registries_len; ++i)
+ − 167 {
+ − 168 if (!(STRINGP(XVECTOR_DATA(registries)[i]))
+ − 169 || (XSTRING_LENGTH(XVECTOR_DATA(registries)[i]) > the_length))
+ − 170 {
+ − 171 continue;
+ − 172 }
+ − 173
+ − 174 /* Check if the font spec ends in the registry specified. X11 says
+ − 175 this comparison is case insensitive: XLFD, section 3.11:
+ − 176
+ − 177 "Alphabetic case distinctions are allowed but are for human
+ − 178 readability concerns only. Conforming X servers will perform
+ − 179 matching on font name query or open requests independent of case." */
+ − 180 if (0 == qxestrcasecmp(XSTRING_DATA(XVECTOR_DATA(registries)[i]),
+ − 181 the_nonreloc + (the_length -
+ − 182 XSTRING_LENGTH
+ − 183 (XVECTOR_DATA(registries)[i]))))
+ − 184 {
+ − 185 return 1;
+ − 186 }
+ − 187 }
+ − 188 return 0;
+ − 189 }
+ − 190
+ − 191 static Lisp_Object
+ − 192 xlistfonts_checking_charset (Lisp_Object device, const Extbyte *xlfd,
+ − 193 Lisp_Object charset,
+ − 194 enum font_specifier_matchspec_stages stage)
+ − 195 {
+ − 196 Extbyte **names;
+ − 197 Lisp_Object result = Qnil;
+ − 198 int count = 0, i;
+ − 199 DECLARE_EISTRING(ei_single_result);
+ − 200
+ − 201 names = XListFonts (
+ − 202 #ifdef THIS_IS_GTK
+ − 203 GDK_DISPLAY (),
+ − 204 #else
+ − 205 DEVICE_X_DISPLAY (XDEVICE (device)),
+ − 206 #endif
+ − 207 xlfd, MAX_FONT_COUNT, &count);
+ − 208
+ − 209 for (i = 0; i < count; ++i)
+ − 210 {
+ − 211 eireset(ei_single_result);
+ − 212 eicpy_ext(ei_single_result, names[i], Qx_font_name_encoding);
+ − 213
+ − 214 if (DEVMETH_OR_GIVEN(XDEVICE (device), font_spec_matches_charset,
+ − 215 (XDEVICE (device), charset,
+ − 216 eidata(ei_single_result), Qnil, 0,
+ − 217 -1, stage), 0))
+ − 218 {
+ − 219 result = eimake_string(ei_single_result);
+ − 220 DEBUG_OBJECTS ("in xlistfonts_checking_charset, returning %s\n",
+ − 221 eidata(ei_single_result));
+ − 222 break;
+ − 223 }
+ − 224 }
+ − 225
+ − 226 if (names)
+ − 227 {
+ − 228 XFreeFontNames (names);
+ − 229 }
+ − 230
+ − 231 return result;
+ − 232 }
+ − 233
+ − 234 #ifdef USE_XFT
+ − 235 /* #### debug functions: find a better place for us */
+ − 236 const char *FcResultToString (FcResult r);
+ − 237 const char *
+ − 238 FcResultToString (FcResult r)
+ − 239 {
+ − 240 static char buffer[256];
+ − 241 switch (r)
+ − 242 {
+ − 243 case FcResultMatch:
+ − 244 return "FcResultMatch";
+ − 245 case FcResultNoMatch:
+ − 246 return "FcResultNoMatch";
+ − 247 case FcResultTypeMismatch:
+ − 248 return "FcResultTypeMismatch";
+ − 249 case FcResultNoId:
+ − 250 return "FcResultNoId";
+ − 251 default:
+ − 252 snprintf (buffer, 255, "FcResultUndocumentedValue (%d)", r);
+ − 253 return buffer;
+ − 254 }
+ − 255 }
+ − 256
+ − 257 const char *FcTypeOfValueToString (FcValue v);
+ − 258 const char *
+ − 259 FcTypeOfValueToString (FcValue v)
+ − 260 {
+ − 261 static char buffer[256];
+ − 262 switch (v.type)
+ − 263 {
+ − 264 case FcTypeMatrix:
+ − 265 return "FcTypeMatrix";
+ − 266 case FcTypeString:
+ − 267 return "FcTypeString";
+ − 268 case FcTypeVoid:
+ − 269 return "FcTypeVoid";
+ − 270 case FcTypeDouble:
+ − 271 return "FcTypeDouble";
+ − 272 case FcTypeInteger:
+ − 273 return "FcTypeInteger";
+ − 274 case FcTypeBool:
+ − 275 return "FcTypeBool";
+ − 276 case FcTypeCharSet:
+ − 277 return "FcTypeCharSet";
+ − 278 case FcTypeLangSet:
+ − 279 return "FcTypeLangSet";
+ − 280 /* #### There is no union member of this type, but there are void* and
+ − 281 FcPattern* members, as of fontconfig.h FC_VERSION 10002 */
+ − 282 case FcTypeFTFace:
+ − 283 return "FcTypeFTFace";
+ − 284 default:
+ − 285 snprintf (buffer, 255, "FcTypeUndocumentedType (%d)", v.type);
+ − 286 return buffer;
+ − 287 }
+ − 288 }
+ − 289
+ − 290 static FcCharSet *
+ − 291 mule_to_fc_charset (Lisp_Object cs)
+ − 292 {
+ − 293 int ucode, i, j;
+ − 294 FcCharSet *fccs;
+ − 295
+ − 296 CHECK_CHARSET (cs);
+ − 297 fccs = FcCharSetCreate ();
+ − 298 /* #### do we also need to deal with 94 vs. 96 charsets?
+ − 299 ie, how are SP and DEL treated in ASCII? non-graphic should return -1 */
+ − 300 if (1 == XCHARSET_DIMENSION (cs))
+ − 301 /* Unicode tables are indexed by offsets from ASCII SP, not by ASCII */
+ − 302 for (i = 0; i < 96; i++)
+ − 303 {
+ − 304 ucode = ((int *) XCHARSET_TO_UNICODE_TABLE (cs))[i];
+ − 305 if (ucode >= 0)
+ − 306 /* #### should check for allocation failure */
+ − 307 FcCharSetAddChar (fccs, (FcChar32) ucode);
+ − 308 }
+ − 309 else if (2 == XCHARSET_DIMENSION (cs))
+ − 310 /* Unicode tables are indexed by offsets from ASCII SP, not by ASCII */
+ − 311 for (i = 0; i < 96; i++)
+ − 312 for (j = 0; j < 96; j++)
+ − 313 {
+ − 314 ucode = ((int **) XCHARSET_TO_UNICODE_TABLE (cs))[i][j];
+ − 315 if (ucode >= 0)
+ − 316 /* #### should check for allocation failure */
+ − 317 FcCharSetAddChar (fccs, (FcChar32) ucode);
+ − 318 }
+ − 319 else
+ − 320 {
+ − 321 FcCharSetDestroy (fccs);
+ − 322 fccs = NULL;
+ − 323 }
+ − 324 return fccs;
+ − 325 }
+ − 326
+ − 327 struct charset_reporter {
+ − 328 Lisp_Object *charset;
+ − 329 /* This is a debug facility, require ASCII. */
+ − 330 Extbyte *language; /* ASCII, please */
+ − 331 /* Technically this is FcChar8, but fsckin' GCC 4 bitches. */
+ − 332 Extbyte *rfc3066; /* ASCII, please */
+ − 333 };
+ − 334
+ − 335 static struct charset_reporter charset_table[] =
+ − 336 {
+ − 337 /* #### It's my branch, my favorite charsets get checked first!
+ − 338 That's a joke, Son.
+ − 339 Ie, I don't know what I'm doing, so my charsets first is as good as
+ − 340 any other arbitrary order. If you have a better idea, speak up! */
+ − 341 { &Vcharset_ascii, "English", "en" },
+ − 342 { &Vcharset_japanese_jisx0208, "Japanese", "ja" },
+ − 343 { &Vcharset_japanese_jisx0212, "Japanese", "ja" },
+ − 344 { &Vcharset_katakana_jisx0201, "Japanese", "ja" },
+ − 345 { &Vcharset_latin_jisx0201, "Japanese", "ja" },
+ − 346 { &Vcharset_japanese_jisx0208_1978, "Japanese", "ja" },
+ − 347 { &Vcharset_greek_iso8859_7, "Greek", "el" },
+ − 348 /* #### all the Chinese need checking
+ − 349 Damn the blood-sucking ISO anyway. */
+ − 350 { &Vcharset_chinese_gb2312, "simplified Chinese", "zh-CN" },
+ − 351 { &Vcharset_korean_ksc5601, "Korean", "ko" },
+ − 352 { &Vcharset_chinese_cns11643_1, "traditional Chinese", "zh-TW" },
+ − 353 { &Vcharset_chinese_cns11643_2, "traditional Chinese", "zh-TW" },
+ − 354 { &Vcharset_latin_iso8859_1, NULL, NULL },
+ − 355 { &Vcharset_latin_iso8859_2, NULL, NULL },
+ − 356 { &Vcharset_latin_iso8859_3, NULL, NULL },
+ − 357 { &Vcharset_latin_iso8859_4, NULL, NULL },
+ − 358 { &Vcharset_latin_iso8859_9, NULL, NULL },
+ − 359 { &Vcharset_latin_iso8859_15, NULL, NULL },
+ − 360 { &Vcharset_thai_tis620, NULL, NULL },
+ − 361 { &Vcharset_arabic_iso8859_6, NULL, NULL },
+ − 362 { &Vcharset_hebrew_iso8859_8, "Hebrew", "he" },
+ − 363 { &Vcharset_cyrillic_iso8859_5, NULL, NULL },
+ − 364 /* #### these probably are not quite right */
+ − 365 { &Vcharset_chinese_big5_1, "traditional Chinese", "zh-TW" },
+ − 366 { &Vcharset_chinese_big5_2, "traditional Chinese", "zh-TW" },
+ − 367 { NULL, NULL, NULL }
+ − 368 };
+ − 369
+ − 370 /* Choose appropriate font name for debug messages.
+ − 371 Use only in the top half of next function (enforced with #undef). */
+ − 372 #define DECLARE_DEBUG_FONTNAME(__xemacs_name) \
+ − 373 Eistring *__xemacs_name; \
+ − 374 do \
+ − 375 { \
+ − 376 __xemacs_name = debug_xft > 2 ? eistr_fullname \
+ − 377 : debug_xft > 1 ? eistr_longname \
+ − 378 : eistr_shortname; \
+ − 379 } while (0)
+ − 380
+ − 381 static Lisp_Object
+ − 382 xft_find_charset_font (Lisp_Object font, Lisp_Object charset,
+ − 383 enum font_specifier_matchspec_stages stage)
+ − 384 {
+ − 385 const Extbyte *patternext;
+ − 386 Lisp_Object result = Qnil;
+ − 387
+ − 388 /* #### with Xft need to handle second stage here -- sjt
+ − 389 Hm. Or maybe not. That would be cool. :-) */
+ − 390 if (stage)
+ − 391 return Qnil;
+ − 392
+ − 393 /* Fontconfig converts all FreeType names to UTF-8 before passing them
+ − 394 back to callers---see fcfreetype.c (FcFreeTypeQuery).
+ − 395 I don't believe this is documented. */
+ − 396
+ − 397 DEBUG_XFT1 (1, "confirming charset for font instance %s\n",
+ − 398 XSTRING_DATA(font));
+ − 399
+ − 400 /* #### this looks like a fair amount of work, but the basic design
+ − 401 has never been rethought, and it should be
+ − 402
+ − 403 what really should happen here is that we use FcFontSort (FcFontList?)
+ − 404 to get a list of matching fonts, then pick the first (best) one that
+ − 405 gives language or repertoire coverage.
+ − 406 */
+ − 407
+ − 408 FcInit (); /* No-op if already initialized.
+ − 409 In fontconfig 2.3.2, this cannot return
+ − 410 failure, but that looks like a bug. We
+ − 411 check for it with FcGetCurrentConfig(),
+ − 412 which *can* fail. */
+ − 413 if (!FcConfigGetCurrent()) /* #### We should expose FcInit* interfaces
+ − 414 to LISP and decide when to reinitialize
+ − 415 intelligently. */
+ − 416 stderr_out ("Failed fontconfig initialization\n");
+ − 417 else
+ − 418 {
+ − 419 FcPattern *fontxft; /* long-lived, freed at end of this block */
+ − 420 FcResult fcresult;
+ − 421 FcConfig *fcc;
+ − 422 FcChar8 *lang = (FcChar8 *) "en"; /* #### fix this bogus hack! */
+ − 423 FcCharSet *fccs = NULL;
+ − 424 DECLARE_EISTRING (eistr_shortname); /* user-friendly nickname */
+ − 425 DECLARE_EISTRING (eistr_longname); /* omit FC_LANG and FC_CHARSET */
+ − 426 DECLARE_EISTRING (eistr_fullname); /* everything */
+ − 427
+ − 428 LISP_STRING_TO_EXTERNAL (font, patternext, Qfc_font_name_encoding);
+ − 429 fcc = FcConfigGetCurrent ();
+ − 430
+ − 431 /* parse the name, do the substitutions, and match the font */
+ − 432
+ − 433 {
+ − 434 FcPattern *p = FcNameParse ((FcChar8 *) patternext);
+ − 435 PRINT_XFT_PATTERN (3, "FcNameParse'ed name is %s\n", p);
+ − 436 /* #### Next two return FcBool, but what does the return mean? */
+ − 437 /* The order is correct according the fontconfig docs. */
+ − 438 FcConfigSubstitute (fcc, p, FcMatchPattern);
+ − 439 PRINT_XFT_PATTERN (2, "FcConfigSubstitute'ed name is %s\n", p);
+ − 440 FcDefaultSubstitute (p);
+ − 441 PRINT_XFT_PATTERN (3, "FcDefaultSubstitute'ed name is %s\n", p);
+ − 442 /* #### check fcresult of following match? */
+ − 443 fontxft = FcFontMatch (fcc, p, &fcresult);
+ − 444 /* this prints the long fontconfig name */
+ − 445 PRINT_XFT_PATTERN (1, "FcFontMatch'ed name is %s\n", fontxft);
+ − 446 FcPatternDestroy (p);
+ − 447 }
+ − 448
+ − 449 /* heuristic to give reasonable-length names for debug reports
+ − 450
+ − 451 I considered #ifdef SUPPORT_FULL_FONTCONFIG_NAME etc but that's
+ − 452 pointless. We're just going to remove this code once the font/
+ − 453 face refactoring is done, but until then it could be very useful.
+ − 454 */
+ − 455 {
+ − 456 FcPattern *p = FcFontRenderPrepare (fcc, fontxft, fontxft);
+ − 457 FcChar8 *name;
+ − 458
+ − 459 /* full name, including language coverage and repertoire */
+ − 460 name = FcNameUnparse (p);
+ − 461 eicpy_ext (eistr_fullname, (Extbyte *) name, Qfc_font_name_encoding);
+ − 462 free (name);
+ − 463
+ − 464 /* long name, omitting coverage and repertoire, plus a number
+ − 465 of rarely useful properties */
+ − 466 FcPatternDel (p, FC_CHARSET);
+ − 467 FcPatternDel (p, FC_LANG);
+ − 468 FcPatternDel (p, FC_WIDTH);
+ − 469 FcPatternDel (p, FC_SPACING);
+ − 470 FcPatternDel (p, FC_HINTING);
+ − 471 FcPatternDel (p, FC_VERTICAL_LAYOUT);
+ − 472 FcPatternDel (p, FC_AUTOHINT);
+ − 473 FcPatternDel (p, FC_GLOBAL_ADVANCE);
+ − 474 FcPatternDel (p, FC_INDEX);
+ − 475 FcPatternDel (p, FC_SCALE);
+ − 476 FcPatternDel (p, FC_FONTVERSION);
+ − 477 name = FcNameUnparse (p);
+ − 478 eicpy_ext (eistr_longname, (Extbyte *) name, Qfc_font_name_encoding);
+ − 479 free (name);
+ − 480
+ − 481 /* nickname, just family and size, but
+ − 482 "family" names usually have style, slant, and weight */
+ − 483 FcPatternDel (p, FC_FOUNDRY);
+ − 484 FcPatternDel (p, FC_STYLE);
+ − 485 FcPatternDel (p, FC_SLANT);
+ − 486 FcPatternDel (p, FC_WEIGHT);
+ − 487 FcPatternDel (p, FC_PIXEL_SIZE);
+ − 488 FcPatternDel (p, FC_OUTLINE);
+ − 489 FcPatternDel (p, FC_SCALABLE);
+ − 490 FcPatternDel (p, FC_DPI);
+ − 491 name = FcNameUnparse (p);
+ − 492 eicpy_ext (eistr_shortname, (Extbyte *) name, Qfc_font_name_encoding);
+ − 493 free (name);
+ − 494
+ − 495 FcPatternDestroy (p);
+ − 496 }
+ − 497
+ − 498 /* The language approach may better in the long run, but we can't use
+ − 499 it based on Mule charsets; fontconfig doesn't provide a way to test
+ − 500 for unions of languages, etc. That will require support from the
+ − 501 text module.
+ − 502
+ − 503 Optimization: cache the generated FcCharSet in the Mule charset.
+ − 504 Don't forget to destroy it if the Mule charset gets deallocated. */
+ − 505
+ − 506 {
+ − 507 /* This block possibly should be a function, but it generates
+ − 508 multiple values. I find the "pass an address to return the
+ − 509 value in" idiom opaque, so prefer a block. */
+ − 510 struct charset_reporter *cr;
+ − 511 for (cr = charset_table;
+ − 512 cr->charset && !EQ (*(cr->charset), charset);
+ − 513 cr++)
+ − 514 ;
+ − 515
+ − 516 if (cr->rfc3066)
+ − 517 {
+ − 518 DECLARE_DEBUG_FONTNAME (name);
+ − 519 CHECKING_LANG (0, eidata(name), cr->language);
+ − 520 lang = (FcChar8 *) cr->rfc3066;
+ − 521 }
+ − 522 else if (cr->charset)
+ − 523 {
+ − 524 /* what the hey, build 'em on the fly */
+ − 525 /* #### in the case of error this could return NULL! */
+ − 526 fccs = mule_to_fc_charset (charset);
+ − 527 lang = (FcChar8 *) XSTRING_DATA (XSYMBOL
+ − 528 (XCHARSET_NAME (charset))-> name);
+ − 529 }
+ − 530 else
+ − 531 {
+ − 532 /* OK, we fell off the end of the table */
+ − 533 warn_when_safe_lispobj (intern ("xft"), intern ("alert"),
+ − 534 list2 (build_string ("unchecked charset"),
+ − 535 charset));
+ − 536 /* default to "en"
+ − 537 #### THIS IS WRONG, WRONG, WRONG!!
+ − 538 It is why we never fall through to XLFD-checking. */
+ − 539 }
+ − 540
+ − 541 ASSERT_ASCTEXT_ASCII((Extbyte *) lang);
+ − 542
+ − 543 if (fccs)
+ − 544 {
+ − 545 /* check for character set coverage */
+ − 546 int i = 0;
+ − 547 FcCharSet *v;
+ − 548 FcResult r = FcPatternGetCharSet (fontxft, FC_CHARSET, i, &v);
+ − 549
+ − 550 if (r == FcResultTypeMismatch)
+ − 551 {
+ − 552 DEBUG_XFT0 (0, "Unexpected type return in charset value\n");
+ − 553 result = Qnil;
+ − 554 }
+ − 555 else if (r == FcResultMatch && FcCharSetIsSubset (fccs, v))
+ − 556 {
+ − 557 /* The full pattern with the bitmap coverage is massively
+ − 558 unwieldy, but the shorter names are just *wrong*. We
+ − 559 should have the full thing internally as truename, and
+ − 560 filter stuff the client doesn't want to see on output.
+ − 561 Should we just store it into the truename right here? */
+ − 562 DECLARE_DEBUG_FONTNAME (name);
+ − 563 DEBUG_XFT2 (0, "Xft font %s supports %s\n",
+ − 564 eidata(name), lang);
+ − 565 #ifdef RETURN_LONG_FONTCONFIG_NAMES
+ − 566 result = eimake_string(eistr_fullname);
+ − 567 #else
+ − 568 result = eimake_string(eistr_longname);
+ − 569 #endif
+ − 570 }
+ − 571 else
+ − 572 {
+ − 573 DECLARE_DEBUG_FONTNAME (name);
+ − 574 DEBUG_XFT2 (0, "Xft font %s doesn't support %s\n",
+ − 575 eidata(name), lang);
+ − 576 result = Qnil;
+ − 577 }
+ − 578
+ − 579 /* clean up */
+ − 580 FcCharSetDestroy (fccs);
+ − 581 }
+ − 582 else
+ − 583 {
+ − 584 /* check for language coverage */
+ − 585 int i = 0;
+ − 586 FcValue v;
+ − 587 /* the main event */
+ − 588 FcResult r = FcPatternGet (fontxft, FC_LANG, i, &v);
+ − 589
+ − 590 if (r == FcResultMatch)
+ − 591 {
+ − 592 if (v.type != FcTypeLangSet) /* excessive paranoia */
+ − 593 {
+ − 594 ASSERT_ASCTEXT_ASCII(FcTypeOfValueToString(v));
+ − 595 /* Urk! Fall back and punt to core font. */
+ − 596 DEBUG_XFT1 (0, "Unexpected type of lang value (%s)\n",
+ − 597 FcTypeOfValueToString (v));
+ − 598 result = Qnil;
+ − 599 }
+ − 600 else if (FcLangSetHasLang (v.u.l, lang) != FcLangDifferentLang)
+ − 601 {
+ − 602 DECLARE_DEBUG_FONTNAME (name);
+ − 603 DEBUG_XFT2 (0, "Xft font %s supports %s\n",
+ − 604 eidata(name), lang);
+ − 605 #ifdef RETURN_LONG_FONTCONFIG_NAMES
+ − 606 result = eimake_string(eistr_fullname);
+ − 607 #else
+ − 608 result = eimake_string(eistr_longname);
+ − 609 #endif
+ − 610 }
+ − 611 else
+ − 612 {
+ − 613 DECLARE_DEBUG_FONTNAME (name);
+ − 614 DEBUG_XFT2 (0, "Xft font %s doesn't support %s\n",
+ − 615 eidata(name), lang);
+ − 616 result = Qnil;
+ − 617 }
+ − 618 }
+ − 619 else
+ − 620 {
+ − 621 ASSERT_ASCTEXT_ASCII(FcResultToString(r));
+ − 622 DEBUG_XFT1 (0, "Getting lang: unexpected result=%s\n",
+ − 623 FcResultToString (r));
+ − 624 result = Qnil;
+ − 625 }
+ − 626 }
+ − 627
+ − 628 /* clean up and maybe return */
+ − 629 FcPatternDestroy (fontxft);
+ − 630 if (!UNBOUNDP (result))
+ − 631 return result;
+ − 632 }
+ − 633 }
+ − 634 return Qnil;
+ − 635 }
+ − 636 #undef DECLARE_DEBUG_FONTNAME
+ − 637
+ − 638 #endif /* USE_XFT */
+ − 639
+ − 640 /* find a font spec that matches font spec FONT and also matches
+ − 641 (the registry of) CHARSET. */
+ − 642 static Lisp_Object
+ − 643 #ifdef THIS_IS_GTK
+ − 644 gtk_find_charset_font (Lisp_Object device, Lisp_Object font,
+ − 645 Lisp_Object charset,
+ − 646 enum font_specifier_matchspec_stages stage)
+ − 647 #else
+ − 648 x_find_charset_font (Lisp_Object device, Lisp_Object font, Lisp_Object charset,
+ − 649 enum font_specifier_matchspec_stages stage)
+ − 650 #endif
+ − 651 {
+ − 652 Lisp_Object result = Qnil, registries = Qnil;
+ − 653 int j, hyphen_count, registries_len = 0;
+ − 654 Ibyte *hyphening, *new_hyphening;
+ − 655 Bytecount xlfd_length;
+ − 656
+ − 657 DECLARE_EISTRING(ei_xlfd_without_registry);
+ − 658 DECLARE_EISTRING(ei_xlfd);
+ − 659
+ − 660 #ifdef USE_XFT
+ − 661 result = xft_find_charset_font(font, charset, stage);
+ − 662 if (!NILP(result))
+ − 663 {
+ − 664 return result;
+ − 665 }
+ − 666 #endif
+ − 667
+ − 668 switch (stage)
+ − 669 {
+ − 670 case initial:
+ − 671 {
+ − 672 if (!(NILP(XCHARSET_REGISTRIES(charset)))
+ − 673 && VECTORP(XCHARSET_REGISTRIES(charset)))
+ − 674 {
+ − 675 registries_len = XVECTOR_LENGTH(XCHARSET_REGISTRIES(charset));
+ − 676 registries = XCHARSET_REGISTRIES(charset);
+ − 677 }
+ − 678 break;
+ − 679 }
+ − 680 case final:
+ − 681 {
+ − 682 registries_len = 1;
+ − 683 registries = Qunicode_registries;
+ − 684 break;
+ − 685 }
+ − 686 default:
+ − 687 {
+ − 688 assert(0);
+ − 689 break;
+ − 690 }
+ − 691 }
+ − 692
+ − 693 eicpy_lstr(ei_xlfd, font);
+ − 694 hyphening = eidata(ei_xlfd);
+ − 695 xlfd_length = eilen(ei_xlfd);
+ − 696
+ − 697 /* Count the hyphens in the string, moving new_hyphening to just after the
+ − 698 last one. */
+ − 699 hyphen_count = count_hyphens(hyphening, xlfd_length, &new_hyphening);
+ − 700
+ − 701 if (0 == registries_len || (5 > hyphen_count &&
+ − 702 !(1 == xlfd_length && '*' == *hyphening)))
+ − 703 {
+ − 704 /* No proper XLFD specified, or we can't modify the pattern to change
+ − 705 the registry and encoding to match what we want, or we have no
+ − 706 information on the registry needed. */
+ − 707 eito_external(ei_xlfd, Qx_font_name_encoding);
+ − 708 DEBUG_OBJECTS ("about to xlistfonts_checking_charset, XLFD %s\n",
+ − 709 eidata(ei_xlfd));
+ − 710 result = xlistfonts_checking_charset (device, eiextdata(ei_xlfd),
+ − 711 charset, stage);
+ − 712 /* No need to loop through the available registries; return
+ − 713 immediately. */
+ − 714 return result;
+ − 715 }
+ − 716 else if (1 == xlfd_length && '*' == *hyphening)
+ − 717 {
+ − 718 /* It's a single asterisk. We can add the registry directly to the
+ − 719 end. */
+ − 720 eicpy_ch(ei_xlfd_without_registry, '*');
+ − 721 }
+ − 722 else
+ − 723 {
+ − 724 /* It's a fully-specified XLFD. Work out where the registry and
+ − 725 encoding are, and initialise ei_xlfd_without_registry to the string
+ − 726 without them. */
+ − 727
+ − 728 /* count_hyphens has set new_hyphening to just after the last
+ − 729 hyphen. Move back to just after the hyphen before it. */
+ − 730
+ − 731 for (new_hyphening -= 2; new_hyphening > hyphening
+ − 732 && '-' != *new_hyphening; --new_hyphening)
+ − 733 ;
+ − 734 ++new_hyphening;
+ − 735
+ − 736 eicpy_ei(ei_xlfd_without_registry, ei_xlfd);
+ − 737
+ − 738 /* Manipulate ei_xlfd_without_registry, using the information about
+ − 739 ei_xlfd, to which it's identical. */
+ − 740 eidel(ei_xlfd_without_registry, new_hyphening - hyphening, -1,
+ − 741 eilen(ei_xlfd) - (new_hyphening - hyphening), -1);
+ − 742
+ − 743 }
+ − 744
+ − 745 /* Now, loop through the registries and encodings defined for this
+ − 746 charset, doing an XListFonts each time with the pattern modified to
+ − 747 specify the regisry and encoding. This avoids huge amounts of IPC and
+ − 748 duplicated searching; now we use the searching the X server was doing
+ − 749 anyway, where before the X server did its search, transferred huge
+ − 750 amounts of data, and then we proceeded to do a regexp search on that
+ − 751 data. */
+ − 752 for (j = 0; j < registries_len && NILP(result); ++j)
+ − 753 {
+ − 754 eireset(ei_xlfd);
+ − 755 eicpy_ei(ei_xlfd, ei_xlfd_without_registry);
+ − 756
+ − 757 eicat_lstr(ei_xlfd, XVECTOR_DATA(registries)[j]);
+ − 758
+ − 759 eito_external(ei_xlfd, Qx_font_name_encoding);
+ − 760
+ − 761 DEBUG_OBJECTS ("about to xlistfonts_checking_charset, XLFD %s\n",
+ − 762 eidata(ei_xlfd));
+ − 763 result = xlistfonts_checking_charset (device, eiextdata(ei_xlfd),
+ − 764 charset, stage);
+ − 765 }
+ − 766
3676
+ − 767 /* In the event that the charset is ASCII and we haven't matched
+ − 768 anything up to now, even with a pattern of "*", add "iso8859-1"
+ − 769 to the charset's registry and try again. Not returning a result
+ − 770 for ASCII means our frame geometry calculations are
+ − 771 inconsistent, and that we may crash. */
+ − 772
+ − 773 if (1 == xlfd_length && EQ(charset, Vcharset_ascii) && NILP(result)
+ − 774 && ('*' == eigetch(ei_xlfd_without_registry, 0)))
+ − 775
+ − 776 {
+ − 777 int have_latin1 = 0;
+ − 778
+ − 779 /* Set this to, for example, is08859-1 if you want to see the
+ − 780 error behaviour. */
+ − 781
+ − 782 #define FALLBACK_ASCII_REGISTRY "iso8859-1"
+ − 783
+ − 784 for (j = 0; j < registries_len; ++j)
+ − 785 {
+ − 786 if (0 == qxestrcasecmp(XSTRING_DATA(XVECTOR_DATA(registries)[j]),
+ − 787 FALLBACK_ASCII_REGISTRY))
+ − 788 {
+ − 789 have_latin1 = 1;
+ − 790 break;
+ − 791 }
+ − 792 }
+ − 793
+ − 794 if (!have_latin1)
+ − 795 {
+ − 796 Lisp_Object new_registries = make_vector(registries_len + 1, Qnil);
+ − 797
+ − 798 XVECTOR_DATA(new_registries)[0]
+ − 799 = build_string(FALLBACK_ASCII_REGISTRY);
+ − 800
+ − 801 memcpy(XVECTOR_DATA(new_registries) + 1,
+ − 802 XVECTOR_DATA(registries),
+ − 803 sizeof XVECTOR_DATA(registries)[0] *
+ − 804 XVECTOR_LENGTH(registries));
+ − 805
+ − 806 /* Calling set_charset_registries instead of overwriting the
+ − 807 value directly, to allow the charset font caches to be
+ − 808 invalidated and a change to the default face to be
+ − 809 noted. */
+ − 810 set_charset_registries(charset, new_registries);
+ − 811
3680
+ − 812 warn_when_safe (Qface, Qwarning,
+ − 813 "Your ASCII charset registries contain nothing "
+ − 814 "sensible. Adding `" FALLBACK_ASCII_REGISTRY "'.");
+ − 815
3676
+ − 816 /* And recurse. */
+ − 817 result =
+ − 818 DEVMETH_OR_GIVEN (XDEVICE (device), find_charset_font,
+ − 819 (device, font, charset, stage),
+ − 820 result);
+ − 821 }
+ − 822 else
+ − 823 {
+ − 824 DECLARE_EISTRING (ei_connection_name);
+ − 825
+ − 826 /* We preserve a copy of the connection name for the error message
+ − 827 after the device is deleted. */
+ − 828 eicpy_lstr (ei_connection_name,
+ − 829 DEVICE_CONNECTION (XDEVICE(device)));
+ − 830
+ − 831 stderr_out ("Cannot find a font for ASCII, deleting device on %s\n",
+ − 832 eidata (ei_connection_name));
+ − 833
+ − 834 io_error_delete_device (device);
+ − 835
+ − 836 /* Do a normal warning in the event that we have other, non-X
+ − 837 frames available. (If we don't, io_error_delete_device will
+ − 838 have exited.) */
+ − 839 warn_when_safe
+ − 840 (Qface, Qerror,
+ − 841 "Cannot find a font for ASCII, deleting device on %s.\n"
+ − 842 "\n"
+ − 843 "Your X server fonts appear to be inconsistent; fix them, or\n"
+ − 844 "the next frame you create on that DISPLAY will crash this\n"
+ − 845 "XEmacs. At a minimum, provide one font with an XLFD ending\n"
+ − 846 "in `" FALLBACK_ASCII_REGISTRY "', so we can work out what size\n"
+ − 847 "a frame should be. ",
+ − 848 eidata (ei_connection_name));
+ − 849 }
+ − 850
+ − 851 }
+ − 852
3659
+ − 853 /* This function used to return the font spec, in the case where a font
+ − 854 didn't exist on the X server but it did match the charset. We're not
+ − 855 doing that any more, because none of the other platform code does, and
+ − 856 the old behaviour was badly-judged in other respects, so I don't trust
+ − 857 the original author to have had a good reason for it. */
+ − 858
+ − 859 return result;
+ − 860 }
+ − 861
+ − 862 #endif /* MULE */