Font.c revision dac667f7
1/* 2 3Copyright 1986, 1998 The Open Group 4Copyright (c) 2000 The XFree86 Project, Inc. 5 6Permission to use, copy, modify, distribute, and sell this software and its 7documentation for any purpose is hereby granted without fee, provided that 8the above copyright notice appear in all copies and that both that 9copyright notice and this permission notice appear in supporting 10documentation. 11 12The above copyright notice and this permission notice shall be included in 13all copies or substantial portions of the Software. 14 15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18X CONSORTIUM OR THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21SOFTWARE. 22 23Except as contained in this notice, the name of the X Consortium or of the 24XFree86 Project shall not be used in advertising or otherwise to promote the 25sale, use or other dealings in this Software without prior written 26authorization from the X Consortium and the XFree86 Project. 27 28*/ 29 30#ifdef HAVE_CONFIG_H 31#include <config.h> 32#endif 33#include "Xlibint.h" 34#include <limits.h> 35 36#if defined(XF86BIGFONT) 37#define USE_XF86BIGFONT 38#endif 39#ifdef USE_XF86BIGFONT 40#include <sys/types.h> 41#ifdef HAS_SHM 42#include <sys/ipc.h> 43#include <sys/shm.h> 44#endif 45 46#include <stdio.h> 47#include <stdlib.h> 48#include <X11/extensions/xf86bigfproto.h> 49#endif 50 51#include "Xlcint.h" 52#include "XlcPubI.h" 53 54 55static XFontStruct *_XQueryFont( 56 Display* /* dpy */, 57 Font /* fid */, 58 unsigned long /* seq */ 59); 60 61#ifdef USE_XF86BIGFONT 62 63/* Private data for this extension. */ 64typedef struct { 65 XExtCodes *codes; 66 CARD32 serverSignature; 67 CARD32 serverCapabilities; 68} XF86BigfontCodes; 69 70/* Additional bit masks that can be set in serverCapabilities */ 71#define CAP_VerifiedLocal 256 72 73static XF86BigfontCodes *_XF86BigfontCodes( 74 Display* /* dpy */ 75); 76 77static XFontStruct *_XF86BigfontQueryFont( 78 Display* /* dpy */, 79 XF86BigfontCodes* /* extcodes */, 80 Font /* fid */, 81 unsigned long /* seq */ 82); 83 84void _XF86BigfontFreeFontMetrics( 85 XFontStruct* /* fs */ 86); 87 88#endif /* USE_XF86BIGFONT */ 89 90 91XFontStruct *XLoadQueryFont( 92 register Display *dpy, 93 _Xconst char *name) 94{ 95 XFontStruct *font_result; 96 register long nbytes; 97 Font fid; 98 xOpenFontReq *req; 99 unsigned long seq; 100#ifdef USE_XF86BIGFONT 101 XF86BigfontCodes *extcodes = _XF86BigfontCodes(dpy); 102#endif 103 104 if (_XF86LoadQueryLocaleFont(dpy, name, &font_result, (Font *)0)) 105 return font_result; 106 LockDisplay(dpy); 107 GetReq(OpenFont, req); 108 seq = dpy->request; /* Can't use extended sequence number here */ 109 nbytes = req->nbytes = name ? strlen(name) : 0; 110 req->fid = fid = XAllocID(dpy); 111 req->length += (nbytes+3)>>2; 112 Data (dpy, name, nbytes); 113 font_result = NULL; 114#ifdef USE_XF86BIGFONT 115 if (extcodes) { 116 font_result = _XF86BigfontQueryFont(dpy, extcodes, fid, seq); 117 seq = 0; 118 } 119#endif 120 if (!font_result) 121 font_result = _XQueryFont(dpy, fid, seq); 122 UnlockDisplay(dpy); 123 SyncHandle(); 124 return font_result; 125} 126 127XFontStruct *XQueryFont ( 128 register Display *dpy, 129 Font fid) 130{ 131 XFontStruct *font_result; 132#ifdef USE_XF86BIGFONT 133 XF86BigfontCodes *extcodes = _XF86BigfontCodes(dpy); 134#endif 135 136 LockDisplay(dpy); 137 font_result = NULL; 138#ifdef USE_XF86BIGFONT 139 if (extcodes) { 140 font_result = _XF86BigfontQueryFont(dpy, extcodes, fid, 0L); 141 } 142#endif 143 if (!font_result) 144 font_result = _XQueryFont(dpy, fid, 0L); 145 UnlockDisplay(dpy); 146 SyncHandle(); 147 return font_result; 148} 149 150int 151XFreeFont( 152 register Display *dpy, 153 XFontStruct *fs) 154{ 155 register xResourceReq *req; 156 register _XExtension *ext; 157 158 LockDisplay(dpy); 159 /* call out to any extensions interested */ 160 for (ext = dpy->ext_procs; ext; ext = ext->next) 161 if (ext->free_Font) (*ext->free_Font)(dpy, fs, &ext->codes); 162 GetResReq (CloseFont, fs->fid, req); 163 UnlockDisplay(dpy); 164 SyncHandle(); 165 if (fs->per_char) { 166#ifdef USE_XF86BIGFONT 167 _XF86BigfontFreeFontMetrics(fs); 168#else 169 Xfree (fs->per_char); 170#endif 171 } 172 _XFreeExtData(fs->ext_data); 173 174 Xfree (fs->properties); 175 Xfree (fs); 176 return 1; 177} 178 179 180static XFontStruct * 181_XQueryFont ( 182 register Display *dpy, 183 Font fid, 184 unsigned long seq) 185{ 186 register XFontStruct *fs; 187 unsigned long nbytes; 188 unsigned long reply_left; /* unused data words left in reply buffer */ 189 xQueryFontReply reply; 190 register xResourceReq *req; 191 register _XExtension *ext; 192 _XAsyncHandler async; 193 _XAsyncErrorState async_state; 194 195 if (seq) { 196 async_state.min_sequence_number = seq; 197 async_state.max_sequence_number = seq; 198 async_state.error_code = BadName; 199 async_state.major_opcode = X_OpenFont; 200 async_state.minor_opcode = 0; 201 async_state.error_count = 0; 202 async.next = dpy->async_handlers; 203 async.handler = _XAsyncErrorHandler; 204 async.data = (XPointer)&async_state; 205 dpy->async_handlers = &async; 206 } 207 GetResReq(QueryFont, fid, req); 208 if (!_XReply (dpy, (xReply *) &reply, 209 ((SIZEOF(xQueryFontReply) - SIZEOF(xReply)) >> 2), xFalse)) { 210 if (seq) 211 DeqAsyncHandler(dpy, &async); 212 return (XFontStruct *)NULL; 213 } 214 if (seq) 215 DeqAsyncHandler(dpy, &async); 216 reply_left = reply.length - 217 ((SIZEOF(xQueryFontReply) - SIZEOF(xReply)) >> 2); 218 if (! (fs = Xmalloc (sizeof (XFontStruct)))) { 219 _XEatDataWords(dpy, reply_left); 220 return (XFontStruct *)NULL; 221 } 222 fs->ext_data = NULL; 223 fs->fid = fid; 224 fs->direction = reply.drawDirection; 225 fs->min_char_or_byte2 = reply.minCharOrByte2; 226 fs->max_char_or_byte2 = reply.maxCharOrByte2; 227 fs->min_byte1 = reply.minByte1; 228 fs->max_byte1 = reply.maxByte1; 229 fs->default_char = reply.defaultChar; 230 fs->all_chars_exist = reply.allCharsExist; 231 fs->ascent = cvtINT16toInt (reply.fontAscent); 232 fs->descent = cvtINT16toInt (reply.fontDescent); 233 234 /* XXX the next two statements won't work if short isn't 16 bits */ 235 fs->min_bounds = * (XCharStruct *) &reply.minBounds; 236 fs->max_bounds = * (XCharStruct *) &reply.maxBounds; 237 238 fs->n_properties = reply.nFontProps; 239 /* 240 * if no properties defined for the font, then it is bad 241 * font, but shouldn't try to read nothing. 242 */ 243 fs->properties = NULL; 244 if (fs->n_properties > 0) { 245 /* nFontProps is a CARD16 */ 246 nbytes = reply.nFontProps * SIZEOF(xFontProp); 247 if ((nbytes >> 2) <= reply_left) { 248 size_t pbytes = reply.nFontProps * sizeof(XFontProp); 249 fs->properties = Xmalloc (pbytes); 250 } 251 if (! fs->properties) { 252 Xfree(fs); 253 _XEatDataWords(dpy, reply_left); 254 return (XFontStruct *)NULL; 255 } 256 _XRead32 (dpy, (long *)fs->properties, nbytes); 257 reply_left -= (nbytes >> 2); 258 } 259 /* 260 * If no characters in font, then it is a bad font, but 261 * shouldn't try to read nothing. 262 */ 263 fs->per_char = NULL; 264 if (reply.nCharInfos > 0){ 265 /* nCharInfos is a CARD32 */ 266 if (reply.nCharInfos < (INT_MAX / sizeof(XCharStruct))) { 267 nbytes = reply.nCharInfos * SIZEOF(xCharInfo); 268 if ((nbytes >> 2) <= reply_left) { 269 size_t cibytes = reply.nCharInfos * sizeof(XCharStruct); 270 fs->per_char = Xmalloc (cibytes); 271 } 272 } 273 if (! fs->per_char) { 274 Xfree(fs->properties); 275 Xfree(fs); 276 _XEatDataWords(dpy, reply_left); 277 return (XFontStruct *)NULL; 278 } 279 280 _XRead16 (dpy, (char *)fs->per_char, nbytes); 281 } 282 283 /* call out to any extensions interested */ 284 for (ext = dpy->ext_procs; ext; ext = ext->next) 285 if (ext->create_Font) (*ext->create_Font)(dpy, fs, &ext->codes); 286 return fs; 287} 288 289#ifdef USE_XF86BIGFONT 290 291/* Magic cookie for finding the right XExtData structure on the display's 292 extension list. */ 293static int XF86BigfontNumber = 1040697125; 294 295static int 296_XF86BigfontFreeCodes ( 297 XExtData *extension) 298{ 299 /* Don't Xfree(extension->private_data) because it is on the same malloc 300 chunk as extension. */ 301 /* Don't Xfree(extension->private_data->codes) because this is shared with 302 the display's ext_procs list. */ 303 return 0; 304} 305 306static XF86BigfontCodes * 307_XF86BigfontCodes ( 308 register Display *dpy) 309{ 310 XEDataObject dpy_union; 311 XExtData *pData; 312 XF86BigfontCodes *pCodes; 313 char *envval; 314 315 dpy_union.display = dpy; 316 317 /* If the server is known to support the XF86Bigfont extension, 318 * return the extension codes. If the server is known to not support 319 * the extension, don't bother checking again. 320 */ 321 pData = XFindOnExtensionList(XEHeadOfExtensionList(dpy_union), 322 XF86BigfontNumber); 323 if (pData) 324 return (XF86BigfontCodes *) pData->private_data; 325 326 pData = Xmalloc(sizeof(XExtData) + sizeof(XF86BigfontCodes)); 327 if (!pData) { 328 /* Out of luck. */ 329 return (XF86BigfontCodes *) NULL; 330 } 331 332 /* See if the server supports the XF86Bigfont extension. */ 333 envval = getenv("XF86BIGFONT_DISABLE"); /* Let the user disable it. */ 334 if (envval != NULL && envval[0] != '\0') 335 pCodes = NULL; 336 else { 337 XExtCodes *codes = XInitExtension(dpy, XF86BIGFONTNAME); 338 if (codes == NULL) 339 pCodes = NULL; 340 else { 341 pCodes = (XF86BigfontCodes *) &pData[1]; 342 pCodes->codes = codes; 343 } 344 } 345 pData->number = XF86BigfontNumber; 346 pData->private_data = (XPointer) pCodes; 347 pData->free_private = _XF86BigfontFreeCodes; 348 XAddToExtensionList(XEHeadOfExtensionList(dpy_union), pData); 349 if (pCodes) { 350 int result; 351 352 /* See if the server supports the XF86BigfontQueryFont request. */ 353 xXF86BigfontQueryVersionReply reply; 354 register xXF86BigfontQueryVersionReq *req; 355 356 LockDisplay(dpy); 357 358 GetReq(XF86BigfontQueryVersion, req); 359 req->reqType = pCodes->codes->major_opcode; 360 req->xf86bigfontReqType = X_XF86BigfontQueryVersion; 361 362 result = _XReply (dpy, (xReply *) &reply, 363 (SIZEOF(xXF86BigfontQueryVersionReply) - SIZEOF(xReply)) >> 2, 364 xFalse); 365 366 UnlockDisplay(dpy); 367 SyncHandle(); 368 369 if(!result) 370 goto ignore_extension; 371 372 /* No need to provide backward compatibility with version 1.0. It 373 was never widely distributed. */ 374 if (!(reply.majorVersion > 1 375 || (reply.majorVersion == 1 && reply.minorVersion >= 1))) 376 goto ignore_extension; 377 378 pCodes->serverSignature = reply.signature; 379 pCodes->serverCapabilities = reply.capabilities; 380 } 381 return pCodes; 382 383 ignore_extension: 384 /* No need to Xfree(pCodes) or Xfree(pCodes->codes), see 385 _XF86BigfontFreeCodes comment. */ 386 pCodes = (XF86BigfontCodes *) NULL; 387 pData->private_data = (XPointer) pCodes; 388 return pCodes; 389} 390 391static int 392_XF86BigfontFreeNop ( 393 XExtData *extension) 394{ 395 return 0; 396} 397 398static XFontStruct * 399_XF86BigfontQueryFont ( 400 register Display *dpy, 401 XF86BigfontCodes *extcodes, 402 Font fid, 403 unsigned long seq) 404{ 405 register XFontStruct *fs; 406 unsigned long nbytes; 407 unsigned long reply_left; /* unused data left in reply buffer */ 408 xXF86BigfontQueryFontReply reply; 409 register xXF86BigfontQueryFontReq *req; 410 register _XExtension *ext; 411 _XAsyncHandler async1; 412 _XAsyncErrorState async1_state; 413 _XAsyncHandler async2; 414 _XAsyncErrorState async2_state; 415 416 if (seq) { 417 async1_state.min_sequence_number = seq; 418 async1_state.max_sequence_number = seq; 419 async1_state.error_code = BadName; 420 async1_state.major_opcode = X_OpenFont; 421 async1_state.minor_opcode = 0; 422 async1_state.error_count = 0; 423 async1.next = dpy->async_handlers; 424 async1.handler = _XAsyncErrorHandler; 425 async1.data = (XPointer)&async1_state; 426 dpy->async_handlers = &async1; 427 } 428 429 GetReq(XF86BigfontQueryFont, req); 430 req->reqType = extcodes->codes->major_opcode; 431 req->xf86bigfontReqType = X_XF86BigfontQueryFont; 432 req->id = fid; 433 req->flags = (extcodes->serverCapabilities & XF86Bigfont_CAP_LocalShm 434 ? XF86Bigfont_FLAGS_Shm : 0); 435 436 /* The function _XQueryFont benefits from a "magic" error handler for 437 BadFont coming from a X_QueryFont request. (See function _XReply.) 438 We have to establish an error handler ourselves. */ 439 async2_state.min_sequence_number = dpy->request; 440 async2_state.max_sequence_number = dpy->request; 441 async2_state.error_code = BadFont; 442 async2_state.major_opcode = extcodes->codes->major_opcode; 443 async2_state.minor_opcode = X_XF86BigfontQueryFont; 444 async2_state.error_count = 0; 445 async2.next = dpy->async_handlers; 446 async2.handler = _XAsyncErrorHandler; 447 async2.data = (XPointer)&async2_state; 448 dpy->async_handlers = &async2; 449 450 if (!_XReply (dpy, (xReply *) &reply, 451 ((SIZEOF(xXF86BigfontQueryFontReply) - SIZEOF(xReply)) >> 2), xFalse)) { 452 DeqAsyncHandler(dpy, &async2); 453 if (seq) 454 DeqAsyncHandler(dpy, &async1); 455 return (XFontStruct *)NULL; 456 } 457 DeqAsyncHandler(dpy, &async2); 458 if (seq) 459 DeqAsyncHandler(dpy, &async1); 460 reply_left = reply.length - 461 ((SIZEOF(xXF86BigfontQueryFontReply) - SIZEOF(xReply)) >> 2); 462 if (! (fs = Xmalloc (sizeof (XFontStruct)))) { 463 _XEatDataWords(dpy, reply_left); 464 return (XFontStruct *)NULL; 465 } 466 fs->ext_data = NULL; 467 fs->fid = fid; 468 fs->direction = reply.drawDirection; 469 fs->min_char_or_byte2 = reply.minCharOrByte2; 470 fs->max_char_or_byte2 = reply.maxCharOrByte2; 471 fs->min_byte1 = reply.minByte1; 472 fs->max_byte1 = reply.maxByte1; 473 fs->default_char = reply.defaultChar; 474 fs->all_chars_exist = reply.allCharsExist; 475 fs->ascent = cvtINT16toInt (reply.fontAscent); 476 fs->descent = cvtINT16toInt (reply.fontDescent); 477 478 /* XXX the next two statements won't work if short isn't 16 bits */ 479 fs->min_bounds = * (XCharStruct *) &reply.minBounds; 480 fs->max_bounds = * (XCharStruct *) &reply.maxBounds; 481 482 fs->n_properties = reply.nFontProps; 483 /* 484 * if no properties defined for the font, then it is bad 485 * font, but shouldn't try to read nothing. 486 */ 487 fs->properties = NULL; 488 if (fs->n_properties > 0) { 489 /* nFontProps is a CARD16 */ 490 nbytes = reply.nFontProps * SIZEOF(xFontProp); 491 if ((nbytes >> 2) <= reply_left) { 492 size_t pbytes = reply.nFontProps * sizeof(XFontProp); 493 fs->properties = Xmalloc (pbytes); 494 } 495 if (! fs->properties) { 496 Xfree(fs); 497 _XEatDataWords(dpy, reply_left); 498 return (XFontStruct *)NULL; 499 } 500 _XRead32 (dpy, (long *)fs->properties, nbytes); 501 reply_left -= (nbytes >> 2); 502 } 503 504 fs->per_char = NULL; 505#ifndef LONG64 506 /* compares each part to half the maximum, which should be far more than 507 any real font needs, so the combined total doesn't overflow either */ 508 if (reply.nUniqCharInfos > ((ULONG_MAX / 2) / SIZEOF(xCharInfo)) || 509 reply.nCharInfos > ((ULONG_MAX / 2) / sizeof(CARD16))) { 510 Xfree(fs->properties); 511 Xfree(fs); 512 _XEatDataWords(dpy, reply_left); 513 return (XFontStruct *)NULL; 514 } 515#endif 516 if (reply.nCharInfos > 0) { 517 /* fprintf(stderr, "received font metrics, nCharInfos = %d, nUniqCharInfos = %d, shmid = %d\n", reply.nCharInfos, reply.nUniqCharInfos, reply.shmid); */ 518 if (reply.shmid == (CARD32)(-1)) { 519 xCharInfo* pUniqCI; 520 CARD16* pIndex2UniqIndex; 521 int i; 522 523 nbytes = reply.nUniqCharInfos * SIZEOF(xCharInfo) 524 + (reply.nCharInfos+1)/2 * 2 * sizeof(CARD16); 525 pUniqCI = Xmalloc (nbytes); 526 if (!pUniqCI) { 527 Xfree(fs->properties); 528 Xfree(fs); 529 _XEatDataWords(dpy, reply_left); 530 return (XFontStruct *)NULL; 531 } 532 if (! (fs->per_char = Xmalloc (reply.nCharInfos * sizeof(XCharStruct)))) { 533 Xfree(pUniqCI); 534 Xfree(fs->properties); 535 Xfree(fs); 536 _XEatDataWords(dpy, reply_left); 537 return (XFontStruct *)NULL; 538 } 539 _XRead16 (dpy, (char *) pUniqCI, nbytes); 540 pIndex2UniqIndex = (CARD16*) (pUniqCI + reply.nUniqCharInfos); 541 for (i = 0; i < reply.nCharInfos; i++) { 542 if (pIndex2UniqIndex[i] >= reply.nUniqCharInfos) { 543 fprintf(stderr, "_XF86BigfontQueryFont: server returned wrong data\n"); 544 Xfree(pUniqCI); 545 Xfree(fs->properties); 546 Xfree(fs); 547 return (XFontStruct *)NULL; 548 } 549 /* XXX the next statement won't work if short isn't 16 bits */ 550 fs->per_char[i] = * (XCharStruct *) &pUniqCI[pIndex2UniqIndex[i]]; 551 } 552 Xfree(pUniqCI); 553 } else { 554#ifdef HAS_SHM 555 XExtData *pData; 556 XEDataObject fs_union; 557 char *addr; 558 559 pData = Xmalloc(sizeof(XExtData)); 560 if (!pData) { 561 Xfree(fs->properties); 562 Xfree(fs); 563 return (XFontStruct *)NULL; 564 } 565 566 /* In some cases (e.g. an ssh daemon forwarding an X session to 567 a remote machine) it is possible that the X server thinks we 568 are running on the same machine (because getpeername() and 569 LocalClient() cannot know about the forwarding) but we are 570 not really local. Therefore, when we attach the first shared 571 memory segment, we verify that we are on the same machine as 572 the X server by checking that 1. shmat() succeeds, 2. the 573 segment has a sufficient size, 3. it contains the X server's 574 signature. Then we set the CAP_VerifiedLocal bit to indicate 575 the verification was successful. */ 576 577 if ((addr = shmat(reply.shmid, NULL, SHM_RDONLY)) == (char *)-1) { 578 if (extcodes->serverCapabilities & CAP_VerifiedLocal) 579 fprintf(stderr, "_XF86BigfontQueryFont: could not attach shm segment\n"); 580 Xfree(pData); 581 Xfree(fs->properties); 582 Xfree(fs); 583 /* Stop requesting shared memory transport from now on. */ 584 extcodes->serverCapabilities &= ~ XF86Bigfont_CAP_LocalShm; 585 return (XFontStruct *)NULL; 586 } 587 588 if (!(extcodes->serverCapabilities & CAP_VerifiedLocal)) { 589 struct shmid_ds buf; 590 if (!(shmctl(reply.shmid, IPC_STAT, &buf) >= 0 591 && reply.nCharInfos < (INT_MAX / sizeof(XCharStruct)) 592 && buf.shm_segsz >= reply.shmsegoffset + reply.nCharInfos * sizeof(XCharStruct) + sizeof(CARD32) 593 && *(CARD32 *)(addr + reply.shmsegoffset + reply.nCharInfos * sizeof(XCharStruct)) == extcodes->serverSignature)) { 594 shmdt(addr); 595 Xfree(pData); 596 Xfree(fs->properties); 597 Xfree(fs); 598 /* Stop requesting shared memory transport from now on. */ 599 extcodes->serverCapabilities &= ~ XF86Bigfont_CAP_LocalShm; 600 return (XFontStruct *)NULL; 601 } 602 extcodes->serverCapabilities |= CAP_VerifiedLocal; 603 } 604 605 pData->number = XF86BigfontNumber; 606 pData->private_data = (XPointer) addr; 607 pData->free_private = _XF86BigfontFreeNop; 608 fs_union.font = fs; 609 XAddToExtensionList(XEHeadOfExtensionList(fs_union), pData); 610 611 fs->per_char = (XCharStruct *) (addr + reply.shmsegoffset); 612#else 613 fprintf(stderr, "_XF86BigfontQueryFont: try recompiling libX11 with HasShm, Xserver has shm support\n"); 614 if (fs->properties) Xfree(fs->properties); 615 Xfree(fs); 616 /* Stop requesting shared memory transport from now on. */ 617 extcodes->serverCapabilities &= ~ XF86Bigfont_CAP_LocalShm; 618 return (XFontStruct *)NULL; 619#endif 620 } 621 } 622 623 /* call out to any extensions interested */ 624 for (ext = dpy->ext_procs; ext; ext = ext->next) 625 if (ext->create_Font) (*ext->create_Font)(dpy, fs, &ext->codes); 626 return fs; 627} 628 629void 630_XF86BigfontFreeFontMetrics (XFontStruct *fs) 631{ 632#ifdef HAS_SHM 633 XExtData *pData; 634 XEDataObject fs_union; 635 636 fs_union.font = fs; 637 if ((pData = XFindOnExtensionList(XEHeadOfExtensionList(fs_union), 638 XF86BigfontNumber))) 639 shmdt ((char *) pData->private_data); 640 else 641 Xfree (fs->per_char); 642#else 643 Xfree (fs->per_char); 644#endif 645} 646 647#endif /* USE_XF86BIGFONT */ 648 649int _XF86LoadQueryLocaleFont( 650 Display *dpy, 651 _Xconst char *name, 652 XFontStruct **xfp, 653 Font *fidp) 654{ 655 int l; 656 const char *charset, *p; 657 char buf[256]; 658 XFontStruct *fs; 659 XLCd lcd; 660 661 if (!name) 662 return 0; 663 l = strlen(name); 664 if (l < 2 || name[l - 1] != '*' || name[l - 2] != '-') 665 return 0; 666 charset = NULL; 667 /* next three lines stolen from _XkbGetCharset() */ 668 lcd = _XlcCurrentLC(); 669 if ((lcd = _XlcCurrentLC()) != 0) 670 charset = XLC_PUBLIC(lcd, encoding_name); 671 if (!charset || (p = strrchr(charset, '-')) == 0 || p == charset || p[1] == 0 || (p[1] == '*' && p[2] == 0)) { 672 /* prefer latin1 if no encoding found */ 673 charset = "ISO8859-1"; 674 p = charset + 7; 675 } 676 if (l - 2 - (p - charset) < 0) 677 return 0; 678 if (_XlcNCompareISOLatin1(name + l - 2 - (p - charset), charset, p - charset)) 679 return 0; 680 if (strlen(p + 1) + l - 1 >= sizeof(buf) - 1) 681 return 0; 682 strcpy(buf, name); 683 strcpy(buf + l - 1, p + 1); 684 fs = XLoadQueryFont(dpy, buf); 685 if (!fs) 686 return 0; 687 if (xfp) { 688 *xfp = fs; 689 if (fidp) 690 *fidp = fs->fid; 691 } else if (fidp) { 692 if (fs->per_char) { 693#ifdef USE_XF86BIGFONT 694 _XF86BigfontFreeFontMetrics(fs); 695#else 696 Xfree (fs->per_char); 697#endif 698 } 699 _XFreeExtData(fs->ext_data); 700 701 Xfree (fs->properties); 702 *fidp = fs->fid; 703 Xfree (fs); 704 } else { 705 XFreeFont(dpy, fs); 706 } 707 return 1; 708} 709