Font.c revision cf2acdde
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;
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