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