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