Font.c revision e4e01221
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 (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
130XFontStruct *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
153int
154XFreeFont(
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
183static 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. */
296static int XF86BigfontNumber = 1040697125;
297
298static 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
309static 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
394static int
395_XF86BigfontFreeNop (
396    XExtData *extension)
397{
398    return 0;
399}
400
401static 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
633void
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
653int _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