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