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