dixfonts.c revision 6747b715
105b261ecSmrg/************************************************************************
205b261ecSmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
305b261ecSmrg
405b261ecSmrg                        All Rights Reserved
505b261ecSmrg
605b261ecSmrgPermission to use, copy, modify, and distribute this software and its
705b261ecSmrgdocumentation for any purpose and without fee is hereby granted,
805b261ecSmrgprovided that the above copyright notice appear in all copies and that
905b261ecSmrgboth that copyright notice and this permission notice appear in
1005b261ecSmrgsupporting documentation, and that the name of Digital not be
1105b261ecSmrgused in advertising or publicity pertaining to distribution of the
1205b261ecSmrgsoftware without specific, written prior permission.
1305b261ecSmrg
1405b261ecSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
1505b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
1605b261ecSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
1705b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
1805b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
1905b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2005b261ecSmrgSOFTWARE.
2105b261ecSmrg
2205b261ecSmrg************************************************************************/
2305b261ecSmrg/* The panoramix components contained the following notice */
2405b261ecSmrg/*
2505b261ecSmrgCopyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
2605b261ecSmrg
2705b261ecSmrgPermission is hereby granted, free of charge, to any person obtaining a copy
2805b261ecSmrgof this software and associated documentation files (the "Software"), to deal
2905b261ecSmrgin the Software without restriction, including without limitation the rights
3005b261ecSmrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell
3105b261ecSmrgcopies of the Software.
3205b261ecSmrg
3305b261ecSmrgThe above copyright notice and this permission notice shall be included in
3405b261ecSmrgall copies or substantial portions of the Software.
3505b261ecSmrg
3605b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
3705b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
3805b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
3905b261ecSmrgDIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
4005b261ecSmrgBUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
4105b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
4205b261ecSmrgIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
4305b261ecSmrg
4405b261ecSmrgExcept as contained in this notice, the name of Digital Equipment Corporation
4505b261ecSmrgshall not be used in advertising or otherwise to promote the sale, use or other
4605b261ecSmrgdealings in this Software without prior written authorization from Digital
4705b261ecSmrgEquipment Corporation.
4805b261ecSmrg
4905b261ecSmrg******************************************************************/
5005b261ecSmrg
5105b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
5205b261ecSmrg#include <dix-config.h>
5305b261ecSmrg#endif
5405b261ecSmrg
5505b261ecSmrg#include <X11/X.h>
5605b261ecSmrg#include <X11/Xmd.h>
5705b261ecSmrg#include <X11/Xproto.h>
5805b261ecSmrg#include "scrnintstr.h"
5905b261ecSmrg#include "resource.h"
6005b261ecSmrg#include "dixstruct.h"
6105b261ecSmrg#include "cursorstr.h"
6205b261ecSmrg#include "misc.h"
6305b261ecSmrg#include "opaque.h"
6405b261ecSmrg#include "dixfontstr.h"
6505b261ecSmrg#include "closestr.h"
6605b261ecSmrg#include "dixfont.h"
674642e01fSmrg#include "xace.h"
6805b261ecSmrg
6905b261ecSmrg#ifdef DEBUG
7005b261ecSmrg#include	<stdio.h>
7105b261ecSmrg#endif
7205b261ecSmrg
7305b261ecSmrg#ifdef XF86BIGFONT
746747b715Smrg#include "xf86bigfontsrv.h"
7505b261ecSmrg#endif
7605b261ecSmrg
7705b261ecSmrg#define QUERYCHARINFO(pci, pr)  *(pr) = (pci)->metrics
7805b261ecSmrg
7905b261ecSmrgextern pointer fosNaturalParams;
8005b261ecSmrgextern FontPtr defaultFont;
8105b261ecSmrg
8205b261ecSmrgstatic FontPathElementPtr *font_path_elements = (FontPathElementPtr *) 0;
8305b261ecSmrgstatic int  num_fpes = 0;
844642e01fSmrgstatic FPEFunctions *fpe_functions = (FPEFunctions *) 0;
8505b261ecSmrgstatic int  num_fpe_types = 0;
8605b261ecSmrg
8705b261ecSmrgstatic unsigned char *font_path_string;
8805b261ecSmrg
8905b261ecSmrgstatic int  num_slept_fpes = 0;
9005b261ecSmrgstatic int  size_slept_fpes = 0;
9105b261ecSmrgstatic FontPathElementPtr *slept_fpes = (FontPathElementPtr *) 0;
9205b261ecSmrgstatic FontPatternCachePtr patternCache;
9305b261ecSmrg
944642e01fSmrgstatic int
954642e01fSmrgFontToXError(int err)
9605b261ecSmrg{
9705b261ecSmrg    switch (err) {
9805b261ecSmrg    case Successful:
9905b261ecSmrg	return Success;
10005b261ecSmrg    case AllocError:
10105b261ecSmrg	return BadAlloc;
10205b261ecSmrg    case BadFontName:
10305b261ecSmrg	return BadName;
10405b261ecSmrg    case BadFontPath:
10505b261ecSmrg    case BadFontFormat:	/* is there something better? */
10605b261ecSmrg    case BadCharRange:
10705b261ecSmrg	return BadValue;
10805b261ecSmrg    default:
10905b261ecSmrg	return err;
11005b261ecSmrg    }
11105b261ecSmrg}
11205b261ecSmrg
1134642e01fSmrgstatic int
1144642e01fSmrgLoadGlyphs(ClientPtr client, FontPtr pfont, unsigned nchars, int item_size,
1154642e01fSmrg	   unsigned char *data)
1164642e01fSmrg{
1174642e01fSmrg    if (fpe_functions[pfont->fpe->type].load_glyphs)
1184642e01fSmrg	return (*fpe_functions[pfont->fpe->type].load_glyphs)
1194642e01fSmrg	    (client, pfont, 0, nchars, item_size, data);
1204642e01fSmrg    else
1214642e01fSmrg	return Successful;
1224642e01fSmrg}
12305b261ecSmrg
12405b261ecSmrg/*
12505b261ecSmrg * adding RT_FONT prevents conflict with default cursor font
12605b261ecSmrg */
12705b261ecSmrgBool
12805b261ecSmrgSetDefaultFont(char *defaultfontname)
12905b261ecSmrg{
13005b261ecSmrg    int         err;
13105b261ecSmrg    FontPtr     pf;
13205b261ecSmrg    XID         fid;
13305b261ecSmrg
13405b261ecSmrg    fid = FakeClientID(0);
13505b261ecSmrg    err = OpenFont(serverClient, fid, FontLoadAll | FontOpenSync,
13605b261ecSmrg		   (unsigned) strlen(defaultfontname), defaultfontname);
13705b261ecSmrg    if (err != Success)
13805b261ecSmrg	return FALSE;
1396747b715Smrg    err = dixLookupResourceByType((pointer *)&pf, fid, RT_FONT, serverClient,
1406747b715Smrg				  DixReadAccess);
1416747b715Smrg    if (err != Success)
14205b261ecSmrg	return FALSE;
14305b261ecSmrg    defaultFont = pf;
14405b261ecSmrg    return TRUE;
14505b261ecSmrg}
14605b261ecSmrg
14705b261ecSmrg/*
14805b261ecSmrg * note that the font wakeup queue is not refcounted.  this is because
14905b261ecSmrg * an fpe needs to be added when it's inited, and removed when it's finally
15005b261ecSmrg * freed, in order to handle any data that isn't requested, like FS events.
15105b261ecSmrg *
15205b261ecSmrg * since the only thing that should call these routines is the renderer's
15305b261ecSmrg * init_fpe() and free_fpe(), there shouldn't be any problem in using
15405b261ecSmrg * freed data.
15505b261ecSmrg */
15605b261ecSmrgvoid
15705b261ecSmrgQueueFontWakeup(FontPathElementPtr fpe)
15805b261ecSmrg{
15905b261ecSmrg    int         i;
16005b261ecSmrg    FontPathElementPtr *new;
16105b261ecSmrg
16205b261ecSmrg    for (i = 0; i < num_slept_fpes; i++) {
16305b261ecSmrg	if (slept_fpes[i] == fpe) {
16405b261ecSmrg	    return;
16505b261ecSmrg	}
16605b261ecSmrg    }
16705b261ecSmrg    if (num_slept_fpes == size_slept_fpes) {
16805b261ecSmrg	new = (FontPathElementPtr *)
1696747b715Smrg	    realloc(slept_fpes,
17005b261ecSmrg		     sizeof(FontPathElementPtr) * (size_slept_fpes + 4));
17105b261ecSmrg	if (!new)
17205b261ecSmrg	    return;
17305b261ecSmrg	slept_fpes = new;
17405b261ecSmrg	size_slept_fpes += 4;
17505b261ecSmrg    }
17605b261ecSmrg    slept_fpes[num_slept_fpes] = fpe;
17705b261ecSmrg    num_slept_fpes++;
17805b261ecSmrg}
17905b261ecSmrg
18005b261ecSmrgvoid
18105b261ecSmrgRemoveFontWakeup(FontPathElementPtr fpe)
18205b261ecSmrg{
18305b261ecSmrg    int         i,
18405b261ecSmrg                j;
18505b261ecSmrg
18605b261ecSmrg    for (i = 0; i < num_slept_fpes; i++) {
18705b261ecSmrg	if (slept_fpes[i] == fpe) {
18805b261ecSmrg	    for (j = i; j < num_slept_fpes; j++) {
18905b261ecSmrg		slept_fpes[j] = slept_fpes[j + 1];
19005b261ecSmrg	    }
19105b261ecSmrg	    num_slept_fpes--;
19205b261ecSmrg	    return;
19305b261ecSmrg	}
19405b261ecSmrg    }
19505b261ecSmrg}
19605b261ecSmrg
19705b261ecSmrgvoid
19805b261ecSmrgFontWakeup(pointer data, int count, pointer LastSelectMask)
19905b261ecSmrg{
20005b261ecSmrg    int         i;
20105b261ecSmrg    FontPathElementPtr fpe;
20205b261ecSmrg
20305b261ecSmrg    if (count < 0)
20405b261ecSmrg	return;
20505b261ecSmrg    /* wake up any fpe's that may be waiting for information */
20605b261ecSmrg    for (i = 0; i < num_slept_fpes; i++) {
20705b261ecSmrg	fpe = slept_fpes[i];
20805b261ecSmrg	(void) (*fpe_functions[fpe->type].wakeup_fpe) (fpe, LastSelectMask);
20905b261ecSmrg    }
21005b261ecSmrg}
21105b261ecSmrg
21205b261ecSmrg/* XXX -- these two funcs may want to be broken into macros */
21305b261ecSmrgstatic void
21405b261ecSmrgUseFPE(FontPathElementPtr fpe)
21505b261ecSmrg{
21605b261ecSmrg    fpe->refcount++;
21705b261ecSmrg}
21805b261ecSmrg
21905b261ecSmrgstatic void
22005b261ecSmrgFreeFPE (FontPathElementPtr fpe)
22105b261ecSmrg{
22205b261ecSmrg    fpe->refcount--;
22305b261ecSmrg    if (fpe->refcount == 0) {
22405b261ecSmrg	(*fpe_functions[fpe->type].free_fpe) (fpe);
2256747b715Smrg	free(fpe->name);
2266747b715Smrg	free(fpe);
22705b261ecSmrg    }
22805b261ecSmrg}
22905b261ecSmrg
23005b261ecSmrgstatic Bool
23105b261ecSmrgdoOpenFont(ClientPtr client, OFclosurePtr c)
23205b261ecSmrg{
23305b261ecSmrg    FontPtr     pfont = NullFont;
23405b261ecSmrg    FontPathElementPtr fpe = NULL;
23505b261ecSmrg    ScreenPtr   pScr;
23605b261ecSmrg    int         err = Successful;
23705b261ecSmrg    int         i;
23805b261ecSmrg    char       *alias,
23905b261ecSmrg               *newname;
24005b261ecSmrg    int         newlen;
24105b261ecSmrg    int		aliascount = 20;
24205b261ecSmrg    /*
24305b261ecSmrg     * Decide at runtime what FontFormat to use.
24405b261ecSmrg     */
24505b261ecSmrg    Mask FontFormat =
24605b261ecSmrg
24705b261ecSmrg	((screenInfo.imageByteOrder == LSBFirst) ?
24805b261ecSmrg	    BitmapFormatByteOrderLSB : BitmapFormatByteOrderMSB) |
24905b261ecSmrg
25005b261ecSmrg	((screenInfo.bitmapBitOrder == LSBFirst) ?
25105b261ecSmrg	    BitmapFormatBitOrderLSB : BitmapFormatBitOrderMSB) |
25205b261ecSmrg
25305b261ecSmrg	BitmapFormatImageRectMin |
25405b261ecSmrg
25505b261ecSmrg#if GLYPHPADBYTES == 1
25605b261ecSmrg	BitmapFormatScanlinePad8 |
25705b261ecSmrg#endif
25805b261ecSmrg
25905b261ecSmrg#if GLYPHPADBYTES == 2
26005b261ecSmrg	BitmapFormatScanlinePad16 |
26105b261ecSmrg#endif
26205b261ecSmrg
26305b261ecSmrg#if GLYPHPADBYTES == 4
26405b261ecSmrg	BitmapFormatScanlinePad32 |
26505b261ecSmrg#endif
26605b261ecSmrg
26705b261ecSmrg#if GLYPHPADBYTES == 8
26805b261ecSmrg	BitmapFormatScanlinePad64 |
26905b261ecSmrg#endif
27005b261ecSmrg
27105b261ecSmrg	BitmapFormatScanlineUnit8;
27205b261ecSmrg
27305b261ecSmrg    if (client->clientGone)
27405b261ecSmrg    {
27505b261ecSmrg	if (c->current_fpe < c->num_fpes)
27605b261ecSmrg	{
27705b261ecSmrg	    fpe = c->fpe_list[c->current_fpe];
27805b261ecSmrg	    (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
27905b261ecSmrg	}
28005b261ecSmrg	err = Successful;
28105b261ecSmrg	goto bail;
28205b261ecSmrg    }
28305b261ecSmrg    while (c->current_fpe < c->num_fpes) {
28405b261ecSmrg	fpe = c->fpe_list[c->current_fpe];
28505b261ecSmrg	err = (*fpe_functions[fpe->type].open_font)
28605b261ecSmrg	    ((pointer) client, fpe, c->flags,
28705b261ecSmrg	     c->fontname, c->fnamelen, FontFormat,
28805b261ecSmrg	     BitmapFormatMaskByte |
28905b261ecSmrg	     BitmapFormatMaskBit |
29005b261ecSmrg	     BitmapFormatMaskImageRectangle |
29105b261ecSmrg	     BitmapFormatMaskScanLinePad |
29205b261ecSmrg	     BitmapFormatMaskScanLineUnit,
29305b261ecSmrg	     c->fontid, &pfont, &alias,
29405b261ecSmrg	     c->non_cachable_font && c->non_cachable_font->fpe == fpe ?
29505b261ecSmrg		 c->non_cachable_font :
29605b261ecSmrg		 (FontPtr)0);
29705b261ecSmrg
29805b261ecSmrg	if (err == FontNameAlias && alias) {
29905b261ecSmrg	    newlen = strlen(alias);
3006747b715Smrg	    newname = (char *) realloc(c->fontname, newlen);
30105b261ecSmrg	    if (!newname) {
30205b261ecSmrg		err = AllocError;
30305b261ecSmrg		break;
30405b261ecSmrg	    }
30505b261ecSmrg	    memmove(newname, alias, newlen);
30605b261ecSmrg	    c->fontname = newname;
30705b261ecSmrg	    c->fnamelen = newlen;
30805b261ecSmrg	    c->current_fpe = 0;
3094642e01fSmrg	    if (--aliascount <= 0) {
3104642e01fSmrg		/* We've tried resolving this alias 20 times, we're
3114642e01fSmrg 		 * probably stuck in an infinite loop of aliases pointing
3124642e01fSmrg 		 * to each other - time to take emergency exit!
3134642e01fSmrg 		 */
3144642e01fSmrg 		err = BadImplementation;
31505b261ecSmrg		break;
3164642e01fSmrg	    }
31705b261ecSmrg	    continue;
31805b261ecSmrg	}
31905b261ecSmrg	if (err == BadFontName) {
32005b261ecSmrg	    c->current_fpe++;
32105b261ecSmrg	    continue;
32205b261ecSmrg	}
32305b261ecSmrg	if (err == Suspended) {
3246747b715Smrg	    if (!ClientIsAsleep(client))
3256747b715Smrg		ClientSleep(client, (ClientSleepProcPtr)doOpenFont, c);
3266747b715Smrg	    else
3276747b715Smrg		goto xinerama_sleep;
32805b261ecSmrg	    return TRUE;
32905b261ecSmrg	}
33005b261ecSmrg	break;
33105b261ecSmrg    }
33205b261ecSmrg
33305b261ecSmrg    if (err != Successful)
33405b261ecSmrg	goto bail;
33505b261ecSmrg    if (!pfont) {
33605b261ecSmrg	err = BadFontName;
33705b261ecSmrg	goto bail;
33805b261ecSmrg    }
33905b261ecSmrg    /* check values for firstCol, lastCol, firstRow, and lastRow */
34005b261ecSmrg    if (pfont->info.firstCol > pfont->info.lastCol ||
34105b261ecSmrg       pfont->info.firstRow > pfont->info.lastRow ||
34205b261ecSmrg       pfont->info.lastCol - pfont->info.firstCol > 255) {
34305b261ecSmrg       err = AllocError;
34405b261ecSmrg       goto bail;
34505b261ecSmrg    }
34605b261ecSmrg    if (!pfont->fpe)
34705b261ecSmrg	pfont->fpe = fpe;
34805b261ecSmrg    pfont->refcnt++;
34905b261ecSmrg    if (pfont->refcnt == 1) {
35005b261ecSmrg	UseFPE(pfont->fpe);
35105b261ecSmrg	for (i = 0; i < screenInfo.numScreens; i++) {
35205b261ecSmrg	    pScr = screenInfo.screens[i];
35305b261ecSmrg	    if (pScr->RealizeFont)
35405b261ecSmrg	    {
35505b261ecSmrg		if (!(*pScr->RealizeFont) (pScr, pfont))
35605b261ecSmrg		{
35705b261ecSmrg		    CloseFont (pfont, (Font) 0);
35805b261ecSmrg		    err = AllocError;
35905b261ecSmrg		    goto bail;
36005b261ecSmrg		}
36105b261ecSmrg	    }
36205b261ecSmrg	}
36305b261ecSmrg    }
36405b261ecSmrg    if (!AddResource(c->fontid, RT_FONT, (pointer) pfont)) {
36505b261ecSmrg	err = AllocError;
36605b261ecSmrg	goto bail;
36705b261ecSmrg    }
36805b261ecSmrg    if (patternCache && pfont != c->non_cachable_font)
36905b261ecSmrg	CacheFontPattern(patternCache, c->origFontName, c->origFontNameLen,
37005b261ecSmrg			 pfont);
37105b261ecSmrgbail:
37205b261ecSmrg    if (err != Successful && c->client != serverClient) {
37305b261ecSmrg	SendErrorToClient(c->client, X_OpenFont, 0,
37405b261ecSmrg			  c->fontid, FontToXError(err));
37505b261ecSmrg    }
3766747b715Smrg    ClientWakeup(c->client);
3776747b715Smrgxinerama_sleep:
37805b261ecSmrg    for (i = 0; i < c->num_fpes; i++) {
37905b261ecSmrg	FreeFPE(c->fpe_list[i]);
38005b261ecSmrg    }
3816747b715Smrg    free(c->fpe_list);
3826747b715Smrg    free(c->fontname);
3836747b715Smrg    free(c);
38405b261ecSmrg    return TRUE;
38505b261ecSmrg}
38605b261ecSmrg
38705b261ecSmrgint
38805b261ecSmrgOpenFont(ClientPtr client, XID fid, Mask flags, unsigned lenfname, char *pfontname)
38905b261ecSmrg{
39005b261ecSmrg    OFclosurePtr c;
39105b261ecSmrg    int         i;
39205b261ecSmrg    FontPtr     cached = (FontPtr)0;
39305b261ecSmrg
39405b261ecSmrg#ifdef FONTDEBUG
39505b261ecSmrg    char *f;
3966747b715Smrg    f = malloc(lenfname + 1);
39705b261ecSmrg    memmove(f, pfontname, lenfname);
39805b261ecSmrg    f[lenfname] = '\0';
3994642e01fSmrg    ErrorF("[dix] OpenFont: fontname is \"%s\"\n", f);
4006747b715Smrg    free(f);
40105b261ecSmrg#endif
40205b261ecSmrg    if (!lenfname || lenfname > XLFDMAXFONTNAMELEN)
40305b261ecSmrg	return BadName;
40405b261ecSmrg    if (patternCache)
40505b261ecSmrg    {
40605b261ecSmrg
40705b261ecSmrg    /*
40805b261ecSmrg    ** Check name cache.  If we find a cached version of this font that
40905b261ecSmrg    ** is cachable, immediately satisfy the request with it.  If we find
41005b261ecSmrg    ** a cached version of this font that is non-cachable, we do not
41105b261ecSmrg    ** satisfy the request with it.  Instead, we pass the FontPtr to the
41205b261ecSmrg    ** FPE's open_font code (the fontfile FPE in turn passes the
41305b261ecSmrg    ** information to the rasterizer; the fserve FPE ignores it).
41405b261ecSmrg    **
41505b261ecSmrg    ** Presumably, the font is marked non-cachable because the FPE has
41605b261ecSmrg    ** put some licensing restrictions on it.  If the FPE, using
41705b261ecSmrg    ** whatever logic it relies on, determines that it is willing to
41805b261ecSmrg    ** share this existing font with the client, then it has the option
41905b261ecSmrg    ** to return the FontPtr we passed it as the newly-opened font.
42005b261ecSmrg    ** This allows the FPE to exercise its licensing logic without
42105b261ecSmrg    ** having to create another instance of a font that already exists.
42205b261ecSmrg    */
42305b261ecSmrg
42405b261ecSmrg	cached = FindCachedFontPattern(patternCache, pfontname, lenfname);
42505b261ecSmrg	if (cached && cached->info.cachable)
42605b261ecSmrg	{
42705b261ecSmrg	    if (!AddResource(fid, RT_FONT, (pointer) cached))
42805b261ecSmrg		return BadAlloc;
42905b261ecSmrg	    cached->refcnt++;
43005b261ecSmrg	    return Success;
43105b261ecSmrg	}
43205b261ecSmrg    }
4336747b715Smrg    c = malloc(sizeof(OFclosureRec));
43405b261ecSmrg    if (!c)
43505b261ecSmrg	return BadAlloc;
4366747b715Smrg    c->fontname = malloc(lenfname);
43705b261ecSmrg    c->origFontName = pfontname;
43805b261ecSmrg    c->origFontNameLen = lenfname;
43905b261ecSmrg    if (!c->fontname) {
4406747b715Smrg	free(c);
44105b261ecSmrg	return BadAlloc;
44205b261ecSmrg    }
44305b261ecSmrg    /*
44405b261ecSmrg     * copy the current FPE list, so that if it gets changed by another client
44505b261ecSmrg     * while we're blocking, the request still appears atomic
44605b261ecSmrg     */
4476747b715Smrg    c->fpe_list = malloc(sizeof(FontPathElementPtr) * num_fpes);
44805b261ecSmrg    if (!c->fpe_list) {
4496747b715Smrg	free(c->fontname);
4506747b715Smrg	free(c);
45105b261ecSmrg	return BadAlloc;
45205b261ecSmrg    }
45305b261ecSmrg    memmove(c->fontname, pfontname, lenfname);
45405b261ecSmrg    for (i = 0; i < num_fpes; i++) {
45505b261ecSmrg	c->fpe_list[i] = font_path_elements[i];
45605b261ecSmrg	UseFPE(c->fpe_list[i]);
45705b261ecSmrg    }
45805b261ecSmrg    c->client = client;
45905b261ecSmrg    c->fontid = fid;
46005b261ecSmrg    c->current_fpe = 0;
46105b261ecSmrg    c->num_fpes = num_fpes;
46205b261ecSmrg    c->fnamelen = lenfname;
46305b261ecSmrg    c->flags = flags;
46405b261ecSmrg    c->non_cachable_font = cached;
46505b261ecSmrg
46605b261ecSmrg    (void) doOpenFont(client, c);
46705b261ecSmrg    return Success;
46805b261ecSmrg}
46905b261ecSmrg
47005b261ecSmrg/**
47105b261ecSmrg * Decrement font's ref count, and free storage if ref count equals zero
47205b261ecSmrg *
47305b261ecSmrg *  \param value must conform to DeleteType
47405b261ecSmrg */
4754642e01fSmrgint
47605b261ecSmrgCloseFont(pointer value, XID fid)
47705b261ecSmrg{
47805b261ecSmrg    int         nscr;
47905b261ecSmrg    ScreenPtr   pscr;
48005b261ecSmrg    FontPathElementPtr fpe;
48105b261ecSmrg    FontPtr     pfont = (FontPtr)value;
48205b261ecSmrg
48305b261ecSmrg    if (pfont == NullFont)
4846747b715Smrg	return Success;
48505b261ecSmrg    if (--pfont->refcnt == 0) {
48605b261ecSmrg	if (patternCache)
48705b261ecSmrg	    RemoveCachedFontPattern (patternCache, pfont);
48805b261ecSmrg	/*
48905b261ecSmrg	 * since the last reference is gone, ask each screen to free any
49005b261ecSmrg	 * storage it may have allocated locally for it.
49105b261ecSmrg	 */
49205b261ecSmrg	for (nscr = 0; nscr < screenInfo.numScreens; nscr++) {
49305b261ecSmrg	    pscr = screenInfo.screens[nscr];
49405b261ecSmrg	    if (pscr->UnrealizeFont)
49505b261ecSmrg		(*pscr->UnrealizeFont) (pscr, pfont);
49605b261ecSmrg	}
49705b261ecSmrg	if (pfont == defaultFont)
49805b261ecSmrg	    defaultFont = NULL;
49905b261ecSmrg#ifdef XF86BIGFONT
50005b261ecSmrg	XF86BigfontFreeFontShm(pfont);
50105b261ecSmrg#endif
50205b261ecSmrg	fpe = pfont->fpe;
50305b261ecSmrg	(*fpe_functions[fpe->type].close_font) (fpe, pfont);
50405b261ecSmrg	FreeFPE(fpe);
50505b261ecSmrg    }
5066747b715Smrg    return Success;
50705b261ecSmrg}
50805b261ecSmrg
50905b261ecSmrg
51005b261ecSmrg/***====================================================================***/
51105b261ecSmrg
51205b261ecSmrg/**
51305b261ecSmrg * Sets up pReply as the correct QueryFontReply for pFont with the first
51405b261ecSmrg * nProtoCCIStructs char infos.
51505b261ecSmrg *
51605b261ecSmrg *  \param pReply caller must allocate this storage
51705b261ecSmrg  */
51805b261ecSmrgvoid
51905b261ecSmrgQueryFont(FontPtr pFont, xQueryFontReply *pReply, int nProtoCCIStructs)
52005b261ecSmrg{
52105b261ecSmrg    FontPropPtr      pFP;
52205b261ecSmrg    int              r,
52305b261ecSmrg                     c,
52405b261ecSmrg                     i;
52505b261ecSmrg    xFontProp       *prFP;
52605b261ecSmrg    xCharInfo       *prCI;
52705b261ecSmrg    xCharInfo       *charInfos[256];
52805b261ecSmrg    unsigned char    chars[512];
52905b261ecSmrg    int              ninfos;
53005b261ecSmrg    unsigned long    ncols;
53105b261ecSmrg    unsigned long    count;
53205b261ecSmrg
53305b261ecSmrg    /* pr->length set in dispatch */
53405b261ecSmrg    pReply->minCharOrByte2 = pFont->info.firstCol;
53505b261ecSmrg    pReply->defaultChar = pFont->info.defaultCh;
53605b261ecSmrg    pReply->maxCharOrByte2 = pFont->info.lastCol;
53705b261ecSmrg    pReply->drawDirection = pFont->info.drawDirection;
53805b261ecSmrg    pReply->allCharsExist = pFont->info.allExist;
53905b261ecSmrg    pReply->minByte1 = pFont->info.firstRow;
54005b261ecSmrg    pReply->maxByte1 = pFont->info.lastRow;
54105b261ecSmrg    pReply->fontAscent = pFont->info.fontAscent;
54205b261ecSmrg    pReply->fontDescent = pFont->info.fontDescent;
54305b261ecSmrg
54405b261ecSmrg    pReply->minBounds = pFont->info.ink_minbounds;
54505b261ecSmrg    pReply->maxBounds = pFont->info.ink_maxbounds;
54605b261ecSmrg
54705b261ecSmrg    pReply->nFontProps = pFont->info.nprops;
54805b261ecSmrg    pReply->nCharInfos = nProtoCCIStructs;
54905b261ecSmrg
55005b261ecSmrg    for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) (&pReply[1]);
55105b261ecSmrg	    i < pFont->info.nprops;
55205b261ecSmrg	    i++, pFP++, prFP++) {
55305b261ecSmrg	prFP->name = pFP->name;
55405b261ecSmrg	prFP->value = pFP->value;
55505b261ecSmrg    }
55605b261ecSmrg
55705b261ecSmrg    ninfos = 0;
55805b261ecSmrg    ncols = (unsigned long) (pFont->info.lastCol - pFont->info.firstCol + 1);
55905b261ecSmrg    prCI = (xCharInfo *) (prFP);
56005b261ecSmrg    for (r = pFont->info.firstRow;
56105b261ecSmrg	    ninfos < nProtoCCIStructs && r <= (int)pFont->info.lastRow;
56205b261ecSmrg	    r++) {
56305b261ecSmrg	i = 0;
56405b261ecSmrg	for (c = pFont->info.firstCol; c <= (int)pFont->info.lastCol; c++) {
56505b261ecSmrg	    chars[i++] = r;
56605b261ecSmrg	    chars[i++] = c;
56705b261ecSmrg	}
56805b261ecSmrg	(*pFont->get_metrics) (pFont, ncols, chars,
56905b261ecSmrg				TwoD16Bit, &count, charInfos);
57005b261ecSmrg	i = 0;
57105b261ecSmrg	for (i = 0; i < (int) count && ninfos < nProtoCCIStructs; i++) {
57205b261ecSmrg	    *prCI = *charInfos[i];
57305b261ecSmrg	    prCI++;
57405b261ecSmrg	    ninfos++;
57505b261ecSmrg	}
57605b261ecSmrg    }
57705b261ecSmrg    return;
57805b261ecSmrg}
57905b261ecSmrg
58005b261ecSmrgstatic Bool
58105b261ecSmrgdoListFontsAndAliases(ClientPtr client, LFclosurePtr c)
58205b261ecSmrg{
58305b261ecSmrg    FontPathElementPtr fpe;
58405b261ecSmrg    int         err = Successful;
58505b261ecSmrg    FontNamesPtr names = NULL;
58605b261ecSmrg    char       *name, *resolved=NULL;
58705b261ecSmrg    int         namelen, resolvedlen;
58805b261ecSmrg    int		nnames;
58905b261ecSmrg    int         stringLens;
59005b261ecSmrg    int         i;
59105b261ecSmrg    xListFontsReply reply;
59205b261ecSmrg    char	*bufptr;
59305b261ecSmrg    char	*bufferStart;
59405b261ecSmrg    int		aliascount = 0;
59505b261ecSmrg
59605b261ecSmrg    if (client->clientGone)
59705b261ecSmrg    {
59805b261ecSmrg	if (c->current.current_fpe < c->num_fpes)
59905b261ecSmrg	{
60005b261ecSmrg	    fpe = c->fpe_list[c->current.current_fpe];
60105b261ecSmrg	    (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
60205b261ecSmrg	}
60305b261ecSmrg	err = Successful;
60405b261ecSmrg	goto bail;
60505b261ecSmrg    }
60605b261ecSmrg
60705b261ecSmrg    if (!c->current.patlen)
60805b261ecSmrg	goto finish;
60905b261ecSmrg
61005b261ecSmrg    while (c->current.current_fpe < c->num_fpes) {
61105b261ecSmrg	fpe = c->fpe_list[c->current.current_fpe];
61205b261ecSmrg	err = Successful;
61305b261ecSmrg
61405b261ecSmrg	if (!fpe_functions[fpe->type].start_list_fonts_and_aliases)
61505b261ecSmrg	{
61605b261ecSmrg	    /* This FPE doesn't support/require list_fonts_and_aliases */
61705b261ecSmrg
61805b261ecSmrg	    err = (*fpe_functions[fpe->type].list_fonts)
61905b261ecSmrg		((pointer) c->client, fpe, c->current.pattern,
62005b261ecSmrg		 c->current.patlen, c->current.max_names - c->names->nnames,
62105b261ecSmrg		 c->names);
62205b261ecSmrg
62305b261ecSmrg	    if (err == Suspended) {
6246747b715Smrg		if (!ClientIsAsleep(client))
62505b261ecSmrg		    ClientSleep(client,
6266747b715Smrg				(ClientSleepProcPtr)doListFontsAndAliases,
6276747b715Smrg				c);
6286747b715Smrg		else
6296747b715Smrg		    goto xinerama_sleep;
63005b261ecSmrg		return TRUE;
63105b261ecSmrg	    }
63205b261ecSmrg
63305b261ecSmrg	    err = BadFontName;
63405b261ecSmrg	}
63505b261ecSmrg	else
63605b261ecSmrg	{
63705b261ecSmrg	    /* Start of list_fonts_and_aliases functionality.  Modeled
63805b261ecSmrg	       after list_fonts_with_info in that it resolves aliases,
63905b261ecSmrg	       except that the information collected from FPEs is just
64005b261ecSmrg	       names, not font info.  Each list_next_font_or_alias()
64105b261ecSmrg	       returns either a name into name/namelen or an alias into
64205b261ecSmrg	       name/namelen and its target name into resolved/resolvedlen.
64305b261ecSmrg	       The code at this level then resolves the alias by polling
64405b261ecSmrg	       the FPEs.  */
64505b261ecSmrg
64605b261ecSmrg	    if (!c->current.list_started) {
64705b261ecSmrg		err = (*fpe_functions[fpe->type].start_list_fonts_and_aliases)
64805b261ecSmrg		    ((pointer) c->client, fpe, c->current.pattern,
64905b261ecSmrg		     c->current.patlen, c->current.max_names - c->names->nnames,
65005b261ecSmrg		     &c->current.private);
65105b261ecSmrg		if (err == Suspended) {
6526747b715Smrg		    if (!ClientIsAsleep(client))
65305b261ecSmrg			ClientSleep(client,
65405b261ecSmrg				    (ClientSleepProcPtr)doListFontsAndAliases,
6556747b715Smrg				    c);
6566747b715Smrg		    else
6576747b715Smrg			goto xinerama_sleep;
65805b261ecSmrg		    return TRUE;
65905b261ecSmrg		}
66005b261ecSmrg		if (err == Successful)
66105b261ecSmrg		    c->current.list_started = TRUE;
66205b261ecSmrg	    }
66305b261ecSmrg	    if (err == Successful) {
66405b261ecSmrg		char    *tmpname;
66505b261ecSmrg		name = 0;
66605b261ecSmrg		err = (*fpe_functions[fpe->type].list_next_font_or_alias)
66705b261ecSmrg		    ((pointer) c->client, fpe, &name, &namelen, &tmpname,
66805b261ecSmrg		     &resolvedlen, c->current.private);
66905b261ecSmrg		if (err == Suspended) {
6706747b715Smrg		    if (ClientIsAsleep(client))
67105b261ecSmrg			ClientSleep(client,
67205b261ecSmrg				    (ClientSleepProcPtr)doListFontsAndAliases,
6736747b715Smrg				    c);
6746747b715Smrg		    else
6756747b715Smrg			goto xinerama_sleep;
67605b261ecSmrg		    return TRUE;
67705b261ecSmrg		}
67805b261ecSmrg		if (err == FontNameAlias) {
6796747b715Smrg		    free(resolved);
6806747b715Smrg		    resolved = malloc(resolvedlen + 1);
68105b261ecSmrg		    if (resolved)
68205b261ecSmrg			memmove(resolved, tmpname, resolvedlen + 1);
68305b261ecSmrg		}
68405b261ecSmrg	    }
68505b261ecSmrg
68605b261ecSmrg	    if (err == Successful)
68705b261ecSmrg	    {
68805b261ecSmrg		if (c->haveSaved)
68905b261ecSmrg		{
69005b261ecSmrg		    if (c->savedName)
69105b261ecSmrg			(void)AddFontNamesName(c->names, c->savedName,
69205b261ecSmrg					       c->savedNameLen);
69305b261ecSmrg		}
69405b261ecSmrg		else
69505b261ecSmrg		    (void)AddFontNamesName(c->names, name, namelen);
69605b261ecSmrg	    }
69705b261ecSmrg
69805b261ecSmrg	    /*
69905b261ecSmrg	     * When we get an alias back, save our state and reset back to
70005b261ecSmrg	     * the start of the FPE looking for the specified name.  As
70105b261ecSmrg	     * soon as a real font is found for the alias, pop back to the
70205b261ecSmrg	     * old state
70305b261ecSmrg	     */
70405b261ecSmrg	    else if (err == FontNameAlias) {
70505b261ecSmrg		char	tmp_pattern[XLFDMAXFONTNAMELEN];
70605b261ecSmrg		/*
70705b261ecSmrg		 * when an alias recurses, we need to give
70805b261ecSmrg		 * the last FPE a chance to clean up; so we call
70905b261ecSmrg		 * it again, and assume that the error returned
71005b261ecSmrg		 * is BadFontName, indicating the alias resolution
71105b261ecSmrg		 * is complete.
71205b261ecSmrg		 */
71305b261ecSmrg		memmove(tmp_pattern, resolved, resolvedlen);
71405b261ecSmrg		if (c->haveSaved)
71505b261ecSmrg		{
71605b261ecSmrg		    char    *tmpname;
71705b261ecSmrg		    int     tmpnamelen;
71805b261ecSmrg
71905b261ecSmrg		    tmpname = 0;
72005b261ecSmrg		    (void) (*fpe_functions[fpe->type].list_next_font_or_alias)
72105b261ecSmrg			((pointer) c->client, fpe, &tmpname, &tmpnamelen,
72205b261ecSmrg			 &tmpname, &tmpnamelen, c->current.private);
72305b261ecSmrg		    if (--aliascount <= 0)
72405b261ecSmrg		    {
72505b261ecSmrg			err = BadFontName;
72605b261ecSmrg			goto ContBadFontName;
72705b261ecSmrg		    }
72805b261ecSmrg		}
72905b261ecSmrg		else
73005b261ecSmrg		{
73105b261ecSmrg		    c->saved = c->current;
73205b261ecSmrg		    c->haveSaved = TRUE;
7336747b715Smrg		    free(c->savedName);
7346747b715Smrg		    c->savedName = malloc(namelen + 1);
73505b261ecSmrg		    if (c->savedName)
73605b261ecSmrg			memmove(c->savedName, name, namelen + 1);
73705b261ecSmrg		    c->savedNameLen = namelen;
73805b261ecSmrg		    aliascount = 20;
73905b261ecSmrg		}
74005b261ecSmrg		memmove(c->current.pattern, tmp_pattern, resolvedlen);
74105b261ecSmrg		c->current.patlen = resolvedlen;
74205b261ecSmrg		c->current.max_names = c->names->nnames + 1;
74305b261ecSmrg		c->current.current_fpe = -1;
74405b261ecSmrg		c->current.private = 0;
74505b261ecSmrg		err = BadFontName;
74605b261ecSmrg	    }
74705b261ecSmrg	}
74805b261ecSmrg	/*
74905b261ecSmrg	 * At the end of this FPE, step to the next.  If we've finished
75005b261ecSmrg	 * processing an alias, pop state back. If we've collected enough
75105b261ecSmrg	 * font names, quit.
75205b261ecSmrg	 */
75305b261ecSmrg	if (err == BadFontName) {
75405b261ecSmrg	  ContBadFontName: ;
75505b261ecSmrg	    c->current.list_started = FALSE;
75605b261ecSmrg	    c->current.current_fpe++;
75705b261ecSmrg	    err = Successful;
75805b261ecSmrg	    if (c->haveSaved)
75905b261ecSmrg	    {
76005b261ecSmrg		if (c->names->nnames == c->current.max_names ||
76105b261ecSmrg			c->current.current_fpe == c->num_fpes) {
76205b261ecSmrg		    c->haveSaved = FALSE;
76305b261ecSmrg		    c->current = c->saved;
76405b261ecSmrg		    /* Give the saved namelist a chance to clean itself up */
76505b261ecSmrg		    continue;
76605b261ecSmrg		}
76705b261ecSmrg	    }
76805b261ecSmrg	    if (c->names->nnames == c->current.max_names)
76905b261ecSmrg		break;
77005b261ecSmrg	}
77105b261ecSmrg    }
77205b261ecSmrg
77305b261ecSmrg    /*
77405b261ecSmrg     * send the reply
77505b261ecSmrg     */
77605b261ecSmrg    if (err != Successful) {
77705b261ecSmrg	SendErrorToClient(client, X_ListFonts, 0, 0, FontToXError(err));
77805b261ecSmrg	goto bail;
77905b261ecSmrg    }
78005b261ecSmrg
78105b261ecSmrgfinish:
78205b261ecSmrg
78305b261ecSmrg    names = c->names;
78405b261ecSmrg    nnames = names->nnames;
78505b261ecSmrg    client = c->client;
78605b261ecSmrg    stringLens = 0;
78705b261ecSmrg    for (i = 0; i < nnames; i++)
78805b261ecSmrg	stringLens += (names->length[i] <= 255) ? names->length[i] : 0;
78905b261ecSmrg
7906747b715Smrg    memset(&reply, 0, sizeof(xListFontsReply));
79105b261ecSmrg    reply.type = X_Reply;
7926747b715Smrg    reply.length = bytes_to_int32(stringLens + nnames);
79305b261ecSmrg    reply.nFonts = nnames;
79405b261ecSmrg    reply.sequenceNumber = client->sequence;
79505b261ecSmrg
7966747b715Smrg    bufptr = bufferStart = malloc(reply.length << 2);
79705b261ecSmrg
79805b261ecSmrg    if (!bufptr && reply.length) {
79905b261ecSmrg	SendErrorToClient(client, X_ListFonts, 0, 0, BadAlloc);
80005b261ecSmrg	goto bail;
80105b261ecSmrg    }
80205b261ecSmrg    /*
80305b261ecSmrg     * since WriteToClient long word aligns things, copy to temp buffer and
80405b261ecSmrg     * write all at once
80505b261ecSmrg     */
80605b261ecSmrg    for (i = 0; i < nnames; i++) {
80705b261ecSmrg	if (names->length[i] > 255)
80805b261ecSmrg	    reply.nFonts--;
80905b261ecSmrg	else
81005b261ecSmrg	{
81105b261ecSmrg	    *bufptr++ = names->length[i];
81205b261ecSmrg	    memmove( bufptr, names->names[i], names->length[i]);
81305b261ecSmrg	    bufptr += names->length[i];
81405b261ecSmrg	}
81505b261ecSmrg    }
81605b261ecSmrg    nnames = reply.nFonts;
8176747b715Smrg    reply.length = bytes_to_int32(stringLens + nnames);
81805b261ecSmrg    client->pSwapReplyFunc = ReplySwapVector[X_ListFonts];
81905b261ecSmrg    WriteSwappedDataToClient(client, sizeof(xListFontsReply), &reply);
82005b261ecSmrg    (void) WriteToClient(client, stringLens + nnames, bufferStart);
8216747b715Smrg    free(bufferStart);
82205b261ecSmrg
82305b261ecSmrgbail:
8246747b715Smrg    ClientWakeup(client);
8256747b715Smrgxinerama_sleep:
82605b261ecSmrg    for (i = 0; i < c->num_fpes; i++)
82705b261ecSmrg	FreeFPE(c->fpe_list[i]);
8286747b715Smrg    free(c->fpe_list);
8296747b715Smrg    free(c->savedName);
83005b261ecSmrg    FreeFontNames(names);
8316747b715Smrg    free(c);
8326747b715Smrg    free(resolved);
83305b261ecSmrg    return TRUE;
83405b261ecSmrg}
83505b261ecSmrg
83605b261ecSmrgint
83705b261ecSmrgListFonts(ClientPtr client, unsigned char *pattern, unsigned length,
83805b261ecSmrg          unsigned max_names)
83905b261ecSmrg{
84005b261ecSmrg    int         i;
84105b261ecSmrg    LFclosurePtr c;
84205b261ecSmrg
84305b261ecSmrg    /*
84405b261ecSmrg     * The right error to return here would be BadName, however the
84505b261ecSmrg     * specification does not allow for a Name error on this request.
84605b261ecSmrg     * Perhaps a better solution would be to return a nil list, i.e.
84705b261ecSmrg     * a list containing zero fontnames.
84805b261ecSmrg     */
84905b261ecSmrg    if (length > XLFDMAXFONTNAMELEN)
85005b261ecSmrg	return BadAlloc;
85105b261ecSmrg
8524642e01fSmrg    i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess);
8534642e01fSmrg    if (i != Success)
8544642e01fSmrg	return i;
8554642e01fSmrg
8566747b715Smrg    if (!(c = malloc(sizeof *c)))
85705b261ecSmrg	return BadAlloc;
8586747b715Smrg    c->fpe_list = malloc(sizeof(FontPathElementPtr) * num_fpes);
85905b261ecSmrg    if (!c->fpe_list) {
8606747b715Smrg	free(c);
86105b261ecSmrg	return BadAlloc;
86205b261ecSmrg    }
86305b261ecSmrg    c->names = MakeFontNamesRecord(max_names < 100 ? max_names : 100);
86405b261ecSmrg    if (!c->names)
86505b261ecSmrg    {
8666747b715Smrg	free(c->fpe_list);
8676747b715Smrg	free(c);
86805b261ecSmrg	return BadAlloc;
86905b261ecSmrg    }
87005b261ecSmrg    memmove( c->current.pattern, pattern, length);
87105b261ecSmrg    for (i = 0; i < num_fpes; i++) {
87205b261ecSmrg	c->fpe_list[i] = font_path_elements[i];
87305b261ecSmrg	UseFPE(c->fpe_list[i]);
87405b261ecSmrg    }
87505b261ecSmrg    c->client = client;
87605b261ecSmrg    c->num_fpes = num_fpes;
87705b261ecSmrg    c->current.patlen = length;
87805b261ecSmrg    c->current.current_fpe = 0;
87905b261ecSmrg    c->current.max_names = max_names;
88005b261ecSmrg    c->current.list_started = FALSE;
88105b261ecSmrg    c->current.private = 0;
88205b261ecSmrg    c->haveSaved = FALSE;
88305b261ecSmrg    c->savedName = 0;
88405b261ecSmrg    doListFontsAndAliases(client, c);
88505b261ecSmrg    return Success;
88605b261ecSmrg}
88705b261ecSmrg
88805b261ecSmrgint
88905b261ecSmrgdoListFontsWithInfo(ClientPtr client, LFWIclosurePtr c)
89005b261ecSmrg{
89105b261ecSmrg    FontPathElementPtr fpe;
89205b261ecSmrg    int         err = Successful;
89305b261ecSmrg    char       *name;
89405b261ecSmrg    int         namelen;
89505b261ecSmrg    int         numFonts;
89605b261ecSmrg    FontInfoRec fontInfo,
89705b261ecSmrg               *pFontInfo;
89805b261ecSmrg    xListFontsWithInfoReply *reply;
89905b261ecSmrg    int         length;
90005b261ecSmrg    xFontProp  *pFP;
90105b261ecSmrg    int         i;
90205b261ecSmrg    int		aliascount = 0;
90305b261ecSmrg    xListFontsWithInfoReply finalReply;
90405b261ecSmrg
90505b261ecSmrg    if (client->clientGone)
90605b261ecSmrg    {
90705b261ecSmrg	if (c->current.current_fpe < c->num_fpes)
90805b261ecSmrg 	{
90905b261ecSmrg	    fpe = c->fpe_list[c->current.current_fpe];
91005b261ecSmrg	    (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
91105b261ecSmrg	}
91205b261ecSmrg	err = Successful;
91305b261ecSmrg	goto bail;
91405b261ecSmrg    }
91505b261ecSmrg    client->pSwapReplyFunc = ReplySwapVector[X_ListFontsWithInfo];
91605b261ecSmrg    if (!c->current.patlen)
91705b261ecSmrg	goto finish;
91805b261ecSmrg    while (c->current.current_fpe < c->num_fpes)
91905b261ecSmrg    {
92005b261ecSmrg	fpe = c->fpe_list[c->current.current_fpe];
92105b261ecSmrg	err = Successful;
92205b261ecSmrg	if (!c->current.list_started)
92305b261ecSmrg 	{
92405b261ecSmrg	    err = (*fpe_functions[fpe->type].start_list_fonts_with_info)
92505b261ecSmrg		(client, fpe, c->current.pattern, c->current.patlen,
92605b261ecSmrg		 c->current.max_names, &c->current.private);
92705b261ecSmrg	    if (err == Suspended)
92805b261ecSmrg 	    {
9296747b715Smrg		if (!ClientIsAsleep(client))
9306747b715Smrg		    ClientSleep(client,
9316747b715Smrg				(ClientSleepProcPtr)doListFontsWithInfo, c);
9326747b715Smrg		else
9336747b715Smrg		    goto xinerama_sleep;
93405b261ecSmrg		return TRUE;
93505b261ecSmrg	    }
93605b261ecSmrg	    if (err == Successful)
93705b261ecSmrg		c->current.list_started = TRUE;
93805b261ecSmrg	}
93905b261ecSmrg	if (err == Successful)
94005b261ecSmrg 	{
94105b261ecSmrg	    name = 0;
94205b261ecSmrg	    pFontInfo = &fontInfo;
94305b261ecSmrg	    err = (*fpe_functions[fpe->type].list_next_font_with_info)
94405b261ecSmrg		(client, fpe, &name, &namelen, &pFontInfo,
94505b261ecSmrg		 &numFonts, c->current.private);
94605b261ecSmrg	    if (err == Suspended)
94705b261ecSmrg 	    {
9486747b715Smrg		if (!ClientIsAsleep(client))
94905b261ecSmrg		    ClientSleep(client,
9506747b715Smrg				(ClientSleepProcPtr)doListFontsWithInfo, c);
9516747b715Smrg		else
9526747b715Smrg		    goto xinerama_sleep;
95305b261ecSmrg		return TRUE;
95405b261ecSmrg	    }
95505b261ecSmrg	}
95605b261ecSmrg	/*
95705b261ecSmrg	 * When we get an alias back, save our state and reset back to the
95805b261ecSmrg	 * start of the FPE looking for the specified name.  As soon as a real
95905b261ecSmrg	 * font is found for the alias, pop back to the old state
96005b261ecSmrg	 */
96105b261ecSmrg	if (err == FontNameAlias)
96205b261ecSmrg 	{
96305b261ecSmrg	    /*
96405b261ecSmrg	     * when an alias recurses, we need to give
96505b261ecSmrg	     * the last FPE a chance to clean up; so we call
96605b261ecSmrg	     * it again, and assume that the error returned
96705b261ecSmrg	     * is BadFontName, indicating the alias resolution
96805b261ecSmrg	     * is complete.
96905b261ecSmrg	     */
97005b261ecSmrg	    if (c->haveSaved)
97105b261ecSmrg	    {
97205b261ecSmrg		char	*tmpname;
97305b261ecSmrg		int	tmpnamelen;
97405b261ecSmrg		FontInfoPtr tmpFontInfo;
97505b261ecSmrg
97605b261ecSmrg	    	tmpname = 0;
97705b261ecSmrg	    	tmpFontInfo = &fontInfo;
97805b261ecSmrg	    	(void) (*fpe_functions[fpe->type].list_next_font_with_info)
97905b261ecSmrg		    (client, fpe, &tmpname, &tmpnamelen, &tmpFontInfo,
98005b261ecSmrg		     &numFonts, c->current.private);
98105b261ecSmrg		if (--aliascount <= 0)
98205b261ecSmrg		{
98305b261ecSmrg		    err = BadFontName;
98405b261ecSmrg		    goto ContBadFontName;
98505b261ecSmrg		}
98605b261ecSmrg	    }
98705b261ecSmrg	    else
98805b261ecSmrg	    {
98905b261ecSmrg		c->saved = c->current;
99005b261ecSmrg		c->haveSaved = TRUE;
99105b261ecSmrg		c->savedNumFonts = numFonts;
9926747b715Smrg		free(c->savedName);
9936747b715Smrg		c->savedName = malloc(namelen + 1);
99405b261ecSmrg		if (c->savedName)
99505b261ecSmrg		  memmove(c->savedName, name, namelen + 1);
99605b261ecSmrg		aliascount = 20;
99705b261ecSmrg	    }
99805b261ecSmrg	    memmove(c->current.pattern, name, namelen);
99905b261ecSmrg	    c->current.patlen = namelen;
100005b261ecSmrg	    c->current.max_names = 1;
100105b261ecSmrg	    c->current.current_fpe = 0;
100205b261ecSmrg	    c->current.private = 0;
100305b261ecSmrg	    c->current.list_started = FALSE;
100405b261ecSmrg	}
100505b261ecSmrg	/*
100605b261ecSmrg	 * At the end of this FPE, step to the next.  If we've finished
100705b261ecSmrg	 * processing an alias, pop state back.  If we've sent enough font
100805b261ecSmrg	 * names, quit.  Always wait for BadFontName to let the FPE
100905b261ecSmrg	 * have a chance to clean up.
101005b261ecSmrg	 */
101105b261ecSmrg	else if (err == BadFontName)
101205b261ecSmrg 	{
101305b261ecSmrg	  ContBadFontName: ;
101405b261ecSmrg	    c->current.list_started = FALSE;
101505b261ecSmrg	    c->current.current_fpe++;
101605b261ecSmrg	    err = Successful;
101705b261ecSmrg	    if (c->haveSaved)
101805b261ecSmrg 	    {
101905b261ecSmrg		if (c->current.max_names == 0 ||
102005b261ecSmrg			c->current.current_fpe == c->num_fpes)
102105b261ecSmrg 		{
102205b261ecSmrg		    c->haveSaved = FALSE;
102305b261ecSmrg		    c->saved.max_names -= (1 - c->current.max_names);
102405b261ecSmrg		    c->current = c->saved;
102505b261ecSmrg		}
102605b261ecSmrg	    }
102705b261ecSmrg	    else if (c->current.max_names == 0)
102805b261ecSmrg		break;
102905b261ecSmrg	}
103005b261ecSmrg 	else if (err == Successful)
103105b261ecSmrg 	{
103205b261ecSmrg	    length = sizeof(*reply) + pFontInfo->nprops * sizeof(xFontProp);
103305b261ecSmrg	    reply = c->reply;
103405b261ecSmrg	    if (c->length < length)
103505b261ecSmrg 	    {
10366747b715Smrg		reply = (xListFontsWithInfoReply *) realloc(c->reply, length);
103705b261ecSmrg		if (!reply)
103805b261ecSmrg 		{
103905b261ecSmrg		    err = AllocError;
104005b261ecSmrg		    break;
104105b261ecSmrg		}
10426747b715Smrg		memset((char*)reply + c->length, 0, length - c->length);
104305b261ecSmrg		c->reply = reply;
104405b261ecSmrg		c->length = length;
104505b261ecSmrg	    }
104605b261ecSmrg	    if (c->haveSaved)
104705b261ecSmrg 	    {
104805b261ecSmrg		numFonts = c->savedNumFonts;
104905b261ecSmrg		name = c->savedName;
105005b261ecSmrg		namelen = strlen(name);
105105b261ecSmrg	    }
105205b261ecSmrg	    reply->type = X_Reply;
10536747b715Smrg	    reply->length = bytes_to_int32(sizeof *reply - sizeof(xGenericReply) +
105405b261ecSmrg			     pFontInfo->nprops * sizeof(xFontProp) +
10556747b715Smrg			     namelen);
105605b261ecSmrg	    reply->sequenceNumber = client->sequence;
105705b261ecSmrg	    reply->nameLength = namelen;
105805b261ecSmrg	    reply->minBounds = pFontInfo->ink_minbounds;
105905b261ecSmrg	    reply->maxBounds = pFontInfo->ink_maxbounds;
106005b261ecSmrg	    reply->minCharOrByte2 = pFontInfo->firstCol;
106105b261ecSmrg	    reply->maxCharOrByte2 = pFontInfo->lastCol;
106205b261ecSmrg	    reply->defaultChar = pFontInfo->defaultCh;
106305b261ecSmrg	    reply->nFontProps = pFontInfo->nprops;
106405b261ecSmrg	    reply->drawDirection = pFontInfo->drawDirection;
106505b261ecSmrg	    reply->minByte1 = pFontInfo->firstRow;
106605b261ecSmrg	    reply->maxByte1 = pFontInfo->lastRow;
106705b261ecSmrg	    reply->allCharsExist = pFontInfo->allExist;
106805b261ecSmrg	    reply->fontAscent = pFontInfo->fontAscent;
106905b261ecSmrg	    reply->fontDescent = pFontInfo->fontDescent;
107005b261ecSmrg	    reply->nReplies = numFonts;
107105b261ecSmrg	    pFP = (xFontProp *) (reply + 1);
107205b261ecSmrg	    for (i = 0; i < pFontInfo->nprops; i++)
107305b261ecSmrg 	    {
107405b261ecSmrg		pFP->name = pFontInfo->props[i].name;
107505b261ecSmrg		pFP->value = pFontInfo->props[i].value;
107605b261ecSmrg		pFP++;
107705b261ecSmrg	    }
107805b261ecSmrg	    WriteSwappedDataToClient(client, length, reply);
107905b261ecSmrg	    (void) WriteToClient(client, namelen, name);
108005b261ecSmrg	    if (pFontInfo == &fontInfo)
108105b261ecSmrg 	    {
10826747b715Smrg		free(fontInfo.props);
10836747b715Smrg		free(fontInfo.isStringProp);
108405b261ecSmrg	    }
108505b261ecSmrg	    --c->current.max_names;
108605b261ecSmrg	}
108705b261ecSmrg    }
108805b261ecSmrgfinish:
108905b261ecSmrg    length = sizeof(xListFontsWithInfoReply);
10906747b715Smrg    memset((char *) &finalReply, 0, sizeof(xListFontsWithInfoReply));
109105b261ecSmrg    finalReply.type = X_Reply;
109205b261ecSmrg    finalReply.sequenceNumber = client->sequence;
10936747b715Smrg    finalReply.length = bytes_to_int32(sizeof(xListFontsWithInfoReply)
10946747b715Smrg		     - sizeof(xGenericReply));
109505b261ecSmrg    WriteSwappedDataToClient(client, length, &finalReply);
109605b261ecSmrgbail:
10976747b715Smrg    ClientWakeup(client);
10986747b715Smrgxinerama_sleep:
109905b261ecSmrg    for (i = 0; i < c->num_fpes; i++)
110005b261ecSmrg	FreeFPE(c->fpe_list[i]);
11016747b715Smrg    free(c->reply);
11026747b715Smrg    free(c->fpe_list);
11036747b715Smrg    free(c->savedName);
11046747b715Smrg    free(c);
110505b261ecSmrg    return TRUE;
110605b261ecSmrg}
110705b261ecSmrg
110805b261ecSmrgint
110905b261ecSmrgStartListFontsWithInfo(ClientPtr client, int length, unsigned char *pattern,
111005b261ecSmrg                       int max_names)
111105b261ecSmrg{
111205b261ecSmrg    int		    i;
111305b261ecSmrg    LFWIclosurePtr  c;
111405b261ecSmrg
111505b261ecSmrg    /*
111605b261ecSmrg     * The right error to return here would be BadName, however the
111705b261ecSmrg     * specification does not allow for a Name error on this request.
111805b261ecSmrg     * Perhaps a better solution would be to return a nil list, i.e.
111905b261ecSmrg     * a list containing zero fontnames.
112005b261ecSmrg     */
112105b261ecSmrg    if (length > XLFDMAXFONTNAMELEN)
112205b261ecSmrg	return BadAlloc;
112305b261ecSmrg
11244642e01fSmrg    i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess);
11254642e01fSmrg    if (i != Success)
11264642e01fSmrg	return i;
11274642e01fSmrg
11286747b715Smrg    if (!(c = malloc(sizeof *c)))
112905b261ecSmrg	goto badAlloc;
11306747b715Smrg    c->fpe_list = malloc(sizeof(FontPathElementPtr) * num_fpes);
113105b261ecSmrg    if (!c->fpe_list)
113205b261ecSmrg    {
11336747b715Smrg	free(c);
113405b261ecSmrg	goto badAlloc;
113505b261ecSmrg    }
113605b261ecSmrg    memmove(c->current.pattern, pattern, length);
113705b261ecSmrg    for (i = 0; i < num_fpes; i++)
113805b261ecSmrg    {
113905b261ecSmrg	c->fpe_list[i] = font_path_elements[i];
114005b261ecSmrg	UseFPE(c->fpe_list[i]);
114105b261ecSmrg    }
114205b261ecSmrg    c->client = client;
114305b261ecSmrg    c->num_fpes = num_fpes;
114405b261ecSmrg    c->reply = 0;
114505b261ecSmrg    c->length = 0;
114605b261ecSmrg    c->current.patlen = length;
114705b261ecSmrg    c->current.current_fpe = 0;
114805b261ecSmrg    c->current.max_names = max_names;
114905b261ecSmrg    c->current.list_started = FALSE;
115005b261ecSmrg    c->current.private = 0;
115105b261ecSmrg    c->savedNumFonts = 0;
115205b261ecSmrg    c->haveSaved = FALSE;
115305b261ecSmrg    c->savedName = 0;
115405b261ecSmrg    doListFontsWithInfo(client, c);
115505b261ecSmrg    return Success;
115605b261ecSmrgbadAlloc:
115705b261ecSmrg    return BadAlloc;
115805b261ecSmrg}
115905b261ecSmrg
116005b261ecSmrg#define TextEltHeader 2
116105b261ecSmrg#define FontShiftSize 5
11626747b715Smrgstatic ChangeGCVal clearGC[] = { { .ptr = NullPixmap } };
116305b261ecSmrg#define clearGCmask (GCClipMask)
116405b261ecSmrg
116505b261ecSmrgint
116605b261ecSmrgdoPolyText(ClientPtr client, PTclosurePtr c)
116705b261ecSmrg{
116805b261ecSmrg    FontPtr pFont = c->pGC->font, oldpFont;
116905b261ecSmrg    int err = Success, lgerr;	/* err is in X error, not font error, space */
117005b261ecSmrg    enum { NEVER_SLEPT, START_SLEEP, SLEEPING } client_state = NEVER_SLEPT;
117105b261ecSmrg    FontPathElementPtr fpe;
117205b261ecSmrg    GC *origGC = NULL;
117305b261ecSmrg
117405b261ecSmrg    if (client->clientGone)
117505b261ecSmrg    {
117605b261ecSmrg	fpe = c->pGC->font->fpe;
117705b261ecSmrg	(*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
117805b261ecSmrg
11796747b715Smrg	if (ClientIsAsleep(client))
118005b261ecSmrg	{
118105b261ecSmrg	    /* Client has died, but we cannot bail out right now.  We
118205b261ecSmrg	       need to clean up after the work we did when going to
118305b261ecSmrg	       sleep.  Setting the drawable pointer to 0 makes this
118405b261ecSmrg	       happen without any attempts to render or perform other
118505b261ecSmrg	       unnecessary activities.  */
118605b261ecSmrg	    c->pDraw = (DrawablePtr)0;
118705b261ecSmrg	}
118805b261ecSmrg	else
118905b261ecSmrg	{
119005b261ecSmrg	    err = Success;
119105b261ecSmrg	    goto bail;
119205b261ecSmrg	}
119305b261ecSmrg    }
119405b261ecSmrg
119505b261ecSmrg    /* Make sure our drawable hasn't disappeared while we slept. */
11966747b715Smrg    if (ClientIsAsleep(client) && c->pDraw)
119705b261ecSmrg    {
11986747b715Smrg	DrawablePtr pDraw;
11996747b715Smrg	dixLookupDrawable(&pDraw, c->did, client, 0, DixWriteAccess);
12006747b715Smrg	if (c->pDraw != pDraw) {
12016747b715Smrg	    /* Our drawable has disappeared.  Treat like client died... ask
12026747b715Smrg	       the FPE code to clean up after client and avoid further
12036747b715Smrg	       rendering while we clean up after ourself.  */
12046747b715Smrg	    fpe = c->pGC->font->fpe;
12056747b715Smrg	    (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
12066747b715Smrg	    c->pDraw = (DrawablePtr)0;
12076747b715Smrg	}
120805b261ecSmrg    }
120905b261ecSmrg
12106747b715Smrg    client_state = ClientIsAsleep(client) ? SLEEPING : NEVER_SLEPT;
121105b261ecSmrg
121205b261ecSmrg    while (c->endReq - c->pElt > TextEltHeader)
121305b261ecSmrg    {
121405b261ecSmrg	if (*c->pElt == FontChange)
121505b261ecSmrg        {
12166747b715Smrg	    Font fid;
121705b261ecSmrg	    if (c->endReq - c->pElt < FontShiftSize)
121805b261ecSmrg	    {
121905b261ecSmrg		 err = BadLength;
122005b261ecSmrg		 goto bail;
122105b261ecSmrg	    }
122205b261ecSmrg
122305b261ecSmrg	    oldpFont = pFont;
122405b261ecSmrg
122505b261ecSmrg	    fid =  ((Font)*(c->pElt+4))		/* big-endian */
122605b261ecSmrg		 | ((Font)*(c->pElt+3)) << 8
122705b261ecSmrg		 | ((Font)*(c->pElt+2)) << 16
122805b261ecSmrg		 | ((Font)*(c->pElt+1)) << 24;
12296747b715Smrg	    err = dixLookupResourceByType((pointer *)&pFont, fid, RT_FONT,
12306747b715Smrg					  client, DixUseAccess);
12316747b715Smrg	    if (err != Success)
123205b261ecSmrg	    {
12336747b715Smrg		/* restore pFont for step 4 (described below) */
123405b261ecSmrg		pFont = oldpFont;
123505b261ecSmrg
123605b261ecSmrg		/* If we're in START_SLEEP mode, the following step
123705b261ecSmrg		   shortens the request...  in the unlikely event that
123805b261ecSmrg		   the fid somehow becomes valid before we come through
123905b261ecSmrg		   again to actually execute the polytext, which would
124005b261ecSmrg		   then mess up our refcounting scheme badly.  */
124105b261ecSmrg		c->err = err;
124205b261ecSmrg		c->endReq = c->pElt;
124305b261ecSmrg
124405b261ecSmrg		goto bail;
124505b261ecSmrg	    }
124605b261ecSmrg
124705b261ecSmrg	    /* Step 3 (described below) on our new font */
124805b261ecSmrg	    if (client_state == START_SLEEP)
124905b261ecSmrg		pFont->refcnt++;
125005b261ecSmrg	    else
125105b261ecSmrg	    {
125205b261ecSmrg		if (pFont != c->pGC->font && c->pDraw)
125305b261ecSmrg		{
12546747b715Smrg		    ChangeGCVal val;
12556747b715Smrg		    val.ptr = pFont;
12566747b715Smrg		    ChangeGC(NullClient, c->pGC, GCFont, &val);
125705b261ecSmrg		    ValidateGC(c->pDraw, c->pGC);
125805b261ecSmrg		    if (c->reqType == X_PolyText8)
125905b261ecSmrg			c->polyText = (PolyTextPtr) c->pGC->ops->PolyText8;
126005b261ecSmrg		    else
126105b261ecSmrg			c->polyText = (PolyTextPtr) c->pGC->ops->PolyText16;
126205b261ecSmrg		}
126305b261ecSmrg
126405b261ecSmrg		/* Undo the refcnt++ we performed when going to sleep */
126505b261ecSmrg		if (client_state == SLEEPING)
126605b261ecSmrg		    (void)CloseFont(c->pGC->font, (Font)0);
126705b261ecSmrg	    }
126805b261ecSmrg	    c->pElt += FontShiftSize;
126905b261ecSmrg	}
127005b261ecSmrg	else	/* print a string */
127105b261ecSmrg	{
127205b261ecSmrg	    unsigned char *pNextElt;
127305b261ecSmrg	    pNextElt = c->pElt + TextEltHeader + (*c->pElt)*c->itemSize;
127405b261ecSmrg	    if ( pNextElt > c->endReq)
127505b261ecSmrg	    {
127605b261ecSmrg		err = BadLength;
127705b261ecSmrg		goto bail;
127805b261ecSmrg	    }
127905b261ecSmrg	    if (client_state == START_SLEEP)
128005b261ecSmrg	    {
128105b261ecSmrg		c->pElt = pNextElt;
128205b261ecSmrg		continue;
128305b261ecSmrg	    }
128405b261ecSmrg	    if (c->pDraw)
128505b261ecSmrg	    {
128605b261ecSmrg		lgerr = LoadGlyphs(client, c->pGC->font, *c->pElt, c->itemSize,
128705b261ecSmrg				   c->pElt + TextEltHeader);
128805b261ecSmrg	    }
128905b261ecSmrg	    else lgerr = Successful;
129005b261ecSmrg
129105b261ecSmrg	    if (lgerr == Suspended)
129205b261ecSmrg	    {
12936747b715Smrg		if (!ClientIsAsleep(client)) {
129405b261ecSmrg		    int len;
129505b261ecSmrg		    GC *pGC;
129605b261ecSmrg		    PTclosurePtr new_closure;
129705b261ecSmrg
129805b261ecSmrg    /*  We're putting the client to sleep.  We need to do a few things
129905b261ecSmrg	to ensure successful and atomic-appearing execution of the
130005b261ecSmrg	remainder of the request.  First, copy the remainder of the
130105b261ecSmrg	request into a safe malloc'd area.  Second, create a scratch GC
130205b261ecSmrg	to use for the remainder of the request.  Third, mark all fonts
130305b261ecSmrg	referenced in the remainder of the request to prevent their
130405b261ecSmrg	deallocation.  Fourth, make the original GC look like the
130505b261ecSmrg	request has completed...  set its font to the final font value
130605b261ecSmrg	from this request.  These GC manipulations are for the unlikely
130705b261ecSmrg	(but possible) event that some other client is using the GC.
130805b261ecSmrg	Steps 3 and 4 are performed by running this procedure through
130905b261ecSmrg	the remainder of the request in a special no-render mode
131005b261ecSmrg	indicated by client_state = START_SLEEP.  */
131105b261ecSmrg
131205b261ecSmrg		    /* Step 1 */
131305b261ecSmrg		    /* Allocate a malloc'd closure structure to replace
131405b261ecSmrg		       the local one we were passed */
13156747b715Smrg		    new_closure = malloc(sizeof(PTclosureRec));
131605b261ecSmrg		    if (!new_closure)
131705b261ecSmrg		    {
131805b261ecSmrg			err = BadAlloc;
131905b261ecSmrg			goto bail;
132005b261ecSmrg		    }
132105b261ecSmrg		    *new_closure = *c;
132205b261ecSmrg		    c = new_closure;
132305b261ecSmrg
132405b261ecSmrg		    len = c->endReq - c->pElt;
13256747b715Smrg		    c->data = malloc(len);
132605b261ecSmrg		    if (!c->data)
132705b261ecSmrg		    {
13286747b715Smrg			free(c);
132905b261ecSmrg			err = BadAlloc;
133005b261ecSmrg			goto bail;
133105b261ecSmrg		    }
133205b261ecSmrg		    memmove(c->data, c->pElt, len);
133305b261ecSmrg		    c->pElt = c->data;
133405b261ecSmrg		    c->endReq = c->pElt + len;
133505b261ecSmrg
133605b261ecSmrg		    /* Step 2 */
133705b261ecSmrg
133805b261ecSmrg		    pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen);
133905b261ecSmrg		    if (!pGC)
134005b261ecSmrg		    {
13416747b715Smrg			free(c->data);
13426747b715Smrg			free(c);
134305b261ecSmrg			err = BadAlloc;
134405b261ecSmrg			goto bail;
134505b261ecSmrg		    }
134605b261ecSmrg		    if ((err = CopyGC(c->pGC, pGC, GCFunction |
134705b261ecSmrg				      GCPlaneMask | GCForeground |
134805b261ecSmrg				      GCBackground | GCFillStyle |
134905b261ecSmrg				      GCTile | GCStipple |
135005b261ecSmrg				      GCTileStipXOrigin |
135105b261ecSmrg				      GCTileStipYOrigin | GCFont |
135205b261ecSmrg				      GCSubwindowMode | GCClipXOrigin |
135305b261ecSmrg				      GCClipYOrigin | GCClipMask)) !=
135405b261ecSmrg				      Success)
135505b261ecSmrg		    {
135605b261ecSmrg			FreeScratchGC(pGC);
13576747b715Smrg			free(c->data);
13586747b715Smrg			free(c);
135905b261ecSmrg			err = BadAlloc;
136005b261ecSmrg			goto bail;
136105b261ecSmrg		    }
136205b261ecSmrg		    origGC = c->pGC;
136305b261ecSmrg		    c->pGC = pGC;
136405b261ecSmrg		    ValidateGC(c->pDraw, c->pGC);
136505b261ecSmrg
13666747b715Smrg		    ClientSleep(client, (ClientSleepProcPtr)doPolyText, c);
136705b261ecSmrg
136805b261ecSmrg		    /* Set up to perform steps 3 and 4 */
136905b261ecSmrg		    client_state = START_SLEEP;
137005b261ecSmrg		    continue;	/* on to steps 3 and 4 */
137105b261ecSmrg		}
13726747b715Smrg		else
13736747b715Smrg		    goto xinerama_sleep;
137405b261ecSmrg		return TRUE;
137505b261ecSmrg	    }
137605b261ecSmrg	    else if (lgerr != Successful)
137705b261ecSmrg	    {
137805b261ecSmrg		err = FontToXError(lgerr);
137905b261ecSmrg		goto bail;
138005b261ecSmrg	    }
138105b261ecSmrg	    if (c->pDraw)
138205b261ecSmrg	    {
138305b261ecSmrg		c->xorg += *((INT8 *)(c->pElt + 1));	/* must be signed */
138405b261ecSmrg		c->xorg = (* c->polyText)(c->pDraw, c->pGC, c->xorg, c->yorg,
138505b261ecSmrg		    *c->pElt, c->pElt + TextEltHeader);
138605b261ecSmrg	    }
138705b261ecSmrg	    c->pElt = pNextElt;
138805b261ecSmrg	}
138905b261ecSmrg    }
139005b261ecSmrg
139105b261ecSmrgbail:
139205b261ecSmrg
139305b261ecSmrg    if (client_state == START_SLEEP)
139405b261ecSmrg    {
139505b261ecSmrg	/* Step 4 */
139605b261ecSmrg	if (pFont != origGC->font)
139705b261ecSmrg	{
13986747b715Smrg	    ChangeGCVal val;
13996747b715Smrg	    val.ptr = pFont;
14006747b715Smrg	    ChangeGC(NullClient, origGC, GCFont, &val);
140105b261ecSmrg	    ValidateGC(c->pDraw, origGC);
140205b261ecSmrg	}
140305b261ecSmrg
140405b261ecSmrg	/* restore pElt pointer for execution of remainder of the request */
140505b261ecSmrg	c->pElt = c->data;
140605b261ecSmrg	return TRUE;
140705b261ecSmrg    }
140805b261ecSmrg
140905b261ecSmrg    if (c->err != Success) err = c->err;
141005b261ecSmrg    if (err != Success && c->client != serverClient) {
141105b261ecSmrg#ifdef PANORAMIX
141205b261ecSmrg        if (noPanoramiXExtension || !c->pGC->pScreen->myNum)
141305b261ecSmrg#endif
141405b261ecSmrg	    SendErrorToClient(c->client, c->reqType, 0, 0, err);
141505b261ecSmrg    }
14166747b715Smrg    if (ClientIsAsleep(client))
141705b261ecSmrg    {
141805b261ecSmrg	ClientWakeup(c->client);
14196747b715Smrgxinerama_sleep:
14206747b715Smrg	ChangeGC(NullClient, c->pGC, clearGCmask, clearGC);
142105b261ecSmrg
142205b261ecSmrg	/* Unreference the font from the scratch GC */
142305b261ecSmrg	CloseFont(c->pGC->font, (Font)0);
142405b261ecSmrg	c->pGC->font = NullFont;
142505b261ecSmrg
142605b261ecSmrg	FreeScratchGC(c->pGC);
14276747b715Smrg	free(c->data);
14286747b715Smrg	free(c);
142905b261ecSmrg    }
143005b261ecSmrg    return TRUE;
143105b261ecSmrg}
143205b261ecSmrg
143305b261ecSmrgint
143405b261ecSmrgPolyText(ClientPtr client, DrawablePtr pDraw, GC *pGC, unsigned char *pElt,
143505b261ecSmrg         unsigned char *endReq, int xorg, int yorg, int reqType, XID did)
143605b261ecSmrg{
143705b261ecSmrg    PTclosureRec local_closure;
143805b261ecSmrg
143905b261ecSmrg    local_closure.pElt = pElt;
144005b261ecSmrg    local_closure.endReq = endReq;
144105b261ecSmrg    local_closure.client = client;
144205b261ecSmrg    local_closure.pDraw = pDraw;
144305b261ecSmrg    local_closure.xorg = xorg;
144405b261ecSmrg    local_closure.yorg = yorg;
144505b261ecSmrg    if ((local_closure.reqType = reqType) == X_PolyText8)
144605b261ecSmrg    {
144705b261ecSmrg	local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText8;
144805b261ecSmrg	local_closure.itemSize = 1;
144905b261ecSmrg    }
145005b261ecSmrg    else
145105b261ecSmrg    {
145205b261ecSmrg	local_closure.polyText =  (PolyTextPtr) pGC->ops->PolyText16;
145305b261ecSmrg	local_closure.itemSize = 2;
145405b261ecSmrg    }
145505b261ecSmrg    local_closure.pGC = pGC;
145605b261ecSmrg    local_closure.did = did;
145705b261ecSmrg    local_closure.err = Success;
145805b261ecSmrg
145905b261ecSmrg    (void) doPolyText(client, &local_closure);
146005b261ecSmrg    return Success;
146105b261ecSmrg}
146205b261ecSmrg
146305b261ecSmrg
146405b261ecSmrg#undef TextEltHeader
146505b261ecSmrg#undef FontShiftSize
146605b261ecSmrg
146705b261ecSmrgint
146805b261ecSmrgdoImageText(ClientPtr client, ITclosurePtr c)
146905b261ecSmrg{
147005b261ecSmrg    int err = Success, lgerr;	/* err is in X error, not font error, space */
147105b261ecSmrg    FontPathElementPtr fpe;
147205b261ecSmrg
147305b261ecSmrg    if (client->clientGone)
147405b261ecSmrg    {
147505b261ecSmrg	fpe = c->pGC->font->fpe;
147605b261ecSmrg	(*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
147705b261ecSmrg	err = Success;
147805b261ecSmrg	goto bail;
147905b261ecSmrg    }
148005b261ecSmrg
148105b261ecSmrg    /* Make sure our drawable hasn't disappeared while we slept. */
14826747b715Smrg    if (ClientIsAsleep(client) && c->pDraw)
148305b261ecSmrg    {
14846747b715Smrg	DrawablePtr pDraw;
14856747b715Smrg	dixLookupDrawable(&pDraw, c->did, client, 0, DixWriteAccess);
14866747b715Smrg	if (c->pDraw != pDraw) {
14876747b715Smrg	    /* Our drawable has disappeared.  Treat like client died... ask
14886747b715Smrg	       the FPE code to clean up after client. */
14896747b715Smrg	    fpe = c->pGC->font->fpe;
14906747b715Smrg	    (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
14916747b715Smrg	    err = Success;
14926747b715Smrg	    goto bail;
14936747b715Smrg	}
149405b261ecSmrg    }
149505b261ecSmrg
149605b261ecSmrg    lgerr = LoadGlyphs(client, c->pGC->font, c->nChars, c->itemSize, c->data);
149705b261ecSmrg    if (lgerr == Suspended)
149805b261ecSmrg    {
14996747b715Smrg        if (!ClientIsAsleep(client)) {
150005b261ecSmrg	    GC *pGC;
150105b261ecSmrg	    unsigned char *data;
150205b261ecSmrg	    ITclosurePtr new_closure;
150305b261ecSmrg
150405b261ecSmrg	    /* We're putting the client to sleep.  We need to
150505b261ecSmrg	       save some state.  Similar problem to that handled
150605b261ecSmrg	       in doPolyText, but much simpler because the
150705b261ecSmrg	       request structure is much simpler. */
150805b261ecSmrg
15096747b715Smrg	    new_closure = malloc(sizeof(ITclosureRec));
151005b261ecSmrg	    if (!new_closure)
151105b261ecSmrg	    {
151205b261ecSmrg		err = BadAlloc;
151305b261ecSmrg		goto bail;
151405b261ecSmrg	    }
151505b261ecSmrg	    *new_closure = *c;
151605b261ecSmrg	    c = new_closure;
151705b261ecSmrg
15186747b715Smrg	    data = malloc(c->nChars * c->itemSize);
151905b261ecSmrg	    if (!data)
152005b261ecSmrg	    {
15216747b715Smrg		free(c);
152205b261ecSmrg		err = BadAlloc;
152305b261ecSmrg		goto bail;
152405b261ecSmrg	    }
152505b261ecSmrg	    memmove(data, c->data, c->nChars * c->itemSize);
152605b261ecSmrg	    c->data = data;
152705b261ecSmrg
152805b261ecSmrg	    pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen);
152905b261ecSmrg	    if (!pGC)
153005b261ecSmrg	    {
15316747b715Smrg		free(c->data);
15326747b715Smrg		free(c);
153305b261ecSmrg		err = BadAlloc;
153405b261ecSmrg		goto bail;
153505b261ecSmrg	    }
153605b261ecSmrg	    if ((err = CopyGC(c->pGC, pGC, GCFunction | GCPlaneMask |
153705b261ecSmrg			      GCForeground | GCBackground | GCFillStyle |
153805b261ecSmrg			      GCTile | GCStipple | GCTileStipXOrigin |
153905b261ecSmrg			      GCTileStipYOrigin | GCFont |
154005b261ecSmrg			      GCSubwindowMode | GCClipXOrigin |
154105b261ecSmrg			      GCClipYOrigin | GCClipMask)) != Success)
154205b261ecSmrg	    {
154305b261ecSmrg		FreeScratchGC(pGC);
15446747b715Smrg		free(c->data);
15456747b715Smrg		free(c);
154605b261ecSmrg		err = BadAlloc;
154705b261ecSmrg		goto bail;
154805b261ecSmrg	    }
154905b261ecSmrg	    c->pGC = pGC;
155005b261ecSmrg	    ValidateGC(c->pDraw, c->pGC);
155105b261ecSmrg
15526747b715Smrg            ClientSleep(client, (ClientSleepProcPtr)doImageText, c);
155305b261ecSmrg        }
15546747b715Smrg	else
15556747b715Smrg	    goto xinerama_sleep;
155605b261ecSmrg        return TRUE;
155705b261ecSmrg    }
155805b261ecSmrg    else if (lgerr != Successful)
155905b261ecSmrg    {
156005b261ecSmrg        err = FontToXError(lgerr);
156105b261ecSmrg        goto bail;
156205b261ecSmrg    }
156305b261ecSmrg    if (c->pDraw)
156405b261ecSmrg    {
156505b261ecSmrg	(* c->imageText)(c->pDraw, c->pGC, c->xorg, c->yorg,
156605b261ecSmrg	    c->nChars, c->data);
156705b261ecSmrg    }
156805b261ecSmrg
156905b261ecSmrgbail:
157005b261ecSmrg
157105b261ecSmrg    if (err != Success && c->client != serverClient) {
157205b261ecSmrg	SendErrorToClient(c->client, c->reqType, 0, 0, err);
157305b261ecSmrg    }
15746747b715Smrg    if (ClientIsAsleep(client))
157505b261ecSmrg    {
157605b261ecSmrg	ClientWakeup(c->client);
15776747b715Smrgxinerama_sleep:
15786747b715Smrg	ChangeGC(NullClient, c->pGC, clearGCmask, clearGC);
157905b261ecSmrg
158005b261ecSmrg	/* Unreference the font from the scratch GC */
158105b261ecSmrg	CloseFont(c->pGC->font, (Font)0);
158205b261ecSmrg	c->pGC->font = NullFont;
158305b261ecSmrg
158405b261ecSmrg	FreeScratchGC(c->pGC);
15856747b715Smrg	free(c->data);
15866747b715Smrg	free(c);
158705b261ecSmrg    }
158805b261ecSmrg    return TRUE;
158905b261ecSmrg}
159005b261ecSmrg
159105b261ecSmrgint
159205b261ecSmrgImageText(ClientPtr client, DrawablePtr pDraw, GC *pGC, int nChars,
159305b261ecSmrg          unsigned char *data, int xorg, int yorg, int reqType, XID did)
159405b261ecSmrg{
159505b261ecSmrg    ITclosureRec local_closure;
159605b261ecSmrg
159705b261ecSmrg    local_closure.client = client;
159805b261ecSmrg    local_closure.pDraw = pDraw;
159905b261ecSmrg    local_closure.pGC = pGC;
160005b261ecSmrg    local_closure.nChars = nChars;
160105b261ecSmrg    local_closure.data = data;
160205b261ecSmrg    local_closure.xorg = xorg;
160305b261ecSmrg    local_closure.yorg = yorg;
160405b261ecSmrg    if ((local_closure.reqType = reqType) == X_ImageText8)
160505b261ecSmrg    {
160605b261ecSmrg	local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText8;
160705b261ecSmrg	local_closure.itemSize = 1;
160805b261ecSmrg    }
160905b261ecSmrg    else
161005b261ecSmrg    {
161105b261ecSmrg	local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText16;
161205b261ecSmrg	local_closure.itemSize = 2;
161305b261ecSmrg    }
161405b261ecSmrg    local_closure.did = did;
161505b261ecSmrg
161605b261ecSmrg    (void) doImageText(client, &local_closure);
161705b261ecSmrg    return Success;
161805b261ecSmrg}
161905b261ecSmrg
162005b261ecSmrg
162105b261ecSmrg/* does the necessary magic to figure out the fpe type */
162205b261ecSmrgstatic int
162305b261ecSmrgDetermineFPEType(char *pathname)
162405b261ecSmrg{
162505b261ecSmrg    int         i;
162605b261ecSmrg
162705b261ecSmrg    for (i = 0; i < num_fpe_types; i++) {
162805b261ecSmrg	if ((*fpe_functions[i].name_check) (pathname))
162905b261ecSmrg	    return i;
163005b261ecSmrg    }
163105b261ecSmrg    return -1;
163205b261ecSmrg}
163305b261ecSmrg
163405b261ecSmrg
163505b261ecSmrgstatic void
163605b261ecSmrgFreeFontPath(FontPathElementPtr *list, int n, Bool force)
163705b261ecSmrg{
163805b261ecSmrg    int         i;
163905b261ecSmrg
164005b261ecSmrg    for (i = 0; i < n; i++) {
164105b261ecSmrg	if (force) {
164205b261ecSmrg	    /* Sanity check that all refcounts will be 0 by the time
164305b261ecSmrg	       we get to the end of the list. */
164405b261ecSmrg	    int found = 1;	/* the first reference is us */
164505b261ecSmrg	    int j;
164605b261ecSmrg	    for (j = i+1; j < n; j++) {
164705b261ecSmrg		if (list[j] == list[i])
164805b261ecSmrg		    found++;
164905b261ecSmrg	    }
165005b261ecSmrg	    if (list[i]->refcount != found) {
165105b261ecSmrg		list[i]->refcount = found; /* ensure it will get freed */
165205b261ecSmrg	    }
165305b261ecSmrg	}
165405b261ecSmrg	FreeFPE(list[i]);
165505b261ecSmrg    }
16566747b715Smrg    free(list);
165705b261ecSmrg}
165805b261ecSmrg
165905b261ecSmrgstatic FontPathElementPtr
166005b261ecSmrgfind_existing_fpe(FontPathElementPtr *list, int num, unsigned char *name, int len)
166105b261ecSmrg{
166205b261ecSmrg    FontPathElementPtr fpe;
166305b261ecSmrg    int         i;
166405b261ecSmrg
166505b261ecSmrg    for (i = 0; i < num; i++) {
166605b261ecSmrg	fpe = list[i];
166705b261ecSmrg	if (fpe->name_length == len && memcmp(name, fpe->name, len) == 0)
166805b261ecSmrg	    return fpe;
166905b261ecSmrg    }
167005b261ecSmrg    return (FontPathElementPtr) 0;
167105b261ecSmrg}
167205b261ecSmrg
167305b261ecSmrg
167405b261ecSmrgstatic int
167505b261ecSmrgSetFontPathElements(int npaths, unsigned char *paths, int *bad, Bool persist)
167605b261ecSmrg{
167705b261ecSmrg    int         i, err = 0;
167805b261ecSmrg    int         valid_paths = 0;
167905b261ecSmrg    unsigned int len;
168005b261ecSmrg    unsigned char *cp = paths;
168105b261ecSmrg    FontPathElementPtr fpe = NULL, *fplist;
168205b261ecSmrg
16836747b715Smrg    fplist = malloc(sizeof(FontPathElementPtr) * npaths);
168405b261ecSmrg    if (!fplist) {
168505b261ecSmrg	*bad = 0;
168605b261ecSmrg	return BadAlloc;
168705b261ecSmrg    }
168805b261ecSmrg    for (i = 0; i < num_fpe_types; i++) {
168905b261ecSmrg	if (fpe_functions[i].set_path_hook)
169005b261ecSmrg	    (*fpe_functions[i].set_path_hook) ();
169105b261ecSmrg    }
169205b261ecSmrg    for (i = 0; i < npaths; i++)
169305b261ecSmrg    {
169405b261ecSmrg	len = (unsigned int) (*cp++);
169505b261ecSmrg
169605b261ecSmrg	if (len == 0)
169705b261ecSmrg	{
169805b261ecSmrg	    if (persist)
16994642e01fSmrg		ErrorF("[dix] Removing empty element from the valid list of fontpaths\n");
170005b261ecSmrg	    err = BadValue;
170105b261ecSmrg	}
170205b261ecSmrg	else
170305b261ecSmrg	{
170405b261ecSmrg	    /* if it's already in our active list, just reset it */
170505b261ecSmrg	    /*
170605b261ecSmrg	     * note that this can miss FPE's in limbo -- may be worth catching
170705b261ecSmrg	     * them, though it'd muck up refcounting
170805b261ecSmrg	     */
170905b261ecSmrg	    fpe = find_existing_fpe(font_path_elements, num_fpes, cp, len);
171005b261ecSmrg	    if (fpe)
171105b261ecSmrg	    {
171205b261ecSmrg		err = (*fpe_functions[fpe->type].reset_fpe) (fpe);
171305b261ecSmrg		if (err == Successful)
171405b261ecSmrg		{
171505b261ecSmrg		    UseFPE(fpe);/* since it'll be decref'd later when freed
171605b261ecSmrg				 * from the old list */
171705b261ecSmrg		}
171805b261ecSmrg		else
171905b261ecSmrg		    fpe = 0;
172005b261ecSmrg	    }
172105b261ecSmrg	    /* if error or can't do it, act like it's a new one */
172205b261ecSmrg	    if (!fpe)
172305b261ecSmrg	    {
17246747b715Smrg		fpe = malloc(sizeof(FontPathElementRec));
172505b261ecSmrg		if (!fpe)
172605b261ecSmrg		{
172705b261ecSmrg		    err = BadAlloc;
172805b261ecSmrg		    goto bail;
172905b261ecSmrg		}
17306747b715Smrg		fpe->name = malloc(len + 1);
173105b261ecSmrg		if (!fpe->name)
173205b261ecSmrg		{
17336747b715Smrg		    free(fpe);
173405b261ecSmrg		    err = BadAlloc;
173505b261ecSmrg		    goto bail;
173605b261ecSmrg		}
173705b261ecSmrg		fpe->refcount = 1;
173805b261ecSmrg
173905b261ecSmrg		strncpy(fpe->name, (char *) cp, (int) len);
174005b261ecSmrg		fpe->name[len] = '\0';
174105b261ecSmrg		fpe->name_length = len;
174205b261ecSmrg		fpe->type = DetermineFPEType(fpe->name);
174305b261ecSmrg		if (fpe->type == -1)
174405b261ecSmrg		    err = BadValue;
174505b261ecSmrg		else
174605b261ecSmrg		    err = (*fpe_functions[fpe->type].init_fpe) (fpe);
174705b261ecSmrg		if (err != Successful)
174805b261ecSmrg		{
174905b261ecSmrg		    if (persist)
175005b261ecSmrg		    {
17514642e01fSmrg			ErrorF("[dix] Could not init font path element %s, removing from list!\n",
175205b261ecSmrg			       fpe->name);
175305b261ecSmrg		    }
17546747b715Smrg		    free(fpe->name);
17556747b715Smrg		    free(fpe);
175605b261ecSmrg		}
175705b261ecSmrg	    }
175805b261ecSmrg	}
175905b261ecSmrg	if (err != Successful)
176005b261ecSmrg	{
176105b261ecSmrg	    if (!persist)
176205b261ecSmrg		goto bail;
176305b261ecSmrg	}
176405b261ecSmrg	else
176505b261ecSmrg	{
176605b261ecSmrg	    fplist[valid_paths++] = fpe;
176705b261ecSmrg	}
176805b261ecSmrg	cp += len;
176905b261ecSmrg    }
177005b261ecSmrg
177105b261ecSmrg    FreeFontPath(font_path_elements, num_fpes, FALSE);
177205b261ecSmrg    font_path_elements = fplist;
177305b261ecSmrg    if (patternCache)
177405b261ecSmrg	EmptyFontPatternCache(patternCache);
177505b261ecSmrg    num_fpes = valid_paths;
177605b261ecSmrg
177705b261ecSmrg    return Success;
177805b261ecSmrgbail:
177905b261ecSmrg    *bad = i;
178005b261ecSmrg    while (--valid_paths >= 0)
178105b261ecSmrg	FreeFPE(fplist[valid_paths]);
17826747b715Smrg    free(fplist);
178305b261ecSmrg    return FontToXError(err);
178405b261ecSmrg}
178505b261ecSmrg
178605b261ecSmrgint
17876747b715SmrgSetFontPath(ClientPtr client, int npaths, unsigned char *paths)
178805b261ecSmrg{
17894642e01fSmrg    int err = XaceHook(XACE_SERVER_ACCESS, client, DixManageAccess);
17904642e01fSmrg    if (err != Success)
17914642e01fSmrg	return err;
179205b261ecSmrg
179305b261ecSmrg    if (npaths == 0) {
179405b261ecSmrg	if (SetDefaultFontPath(defaultFontPath) != Success)
179505b261ecSmrg	    return BadValue;
179605b261ecSmrg    } else {
17976747b715Smrg	int bad;
17986747b715Smrg	err = SetFontPathElements(npaths, paths, &bad, FALSE);
17996747b715Smrg	client->errorValue = bad;
180005b261ecSmrg    }
180105b261ecSmrg    return err;
180205b261ecSmrg}
180305b261ecSmrg
180405b261ecSmrgint
180505b261ecSmrgSetDefaultFontPath(char *path)
180605b261ecSmrg{
1807b1d344b3Smrg    char       *temp_path,
1808b1d344b3Smrg               *start,
1809b1d344b3Smrg               *end;
181005b261ecSmrg    unsigned char *cp,
181105b261ecSmrg               *pp,
181205b261ecSmrg               *nump,
181305b261ecSmrg               *newpath;
181405b261ecSmrg    int         num = 1,
181505b261ecSmrg                len,
181605b261ecSmrg                err,
181705b261ecSmrg                size = 0,
181805b261ecSmrg                bad;
181905b261ecSmrg
1820b1d344b3Smrg    /* ensure temp_path contains "built-ins" */
1821b1d344b3Smrg    start = path;
1822b1d344b3Smrg    while (1) {
1823b1d344b3Smrg	start = strstr(start, "built-ins");
1824b1d344b3Smrg	if (start == NULL)
1825b1d344b3Smrg	    break;
1826b1d344b3Smrg	end = start + strlen("built-ins");
1827b1d344b3Smrg	if ((start == path || start[-1] == ',') && (!*end || *end == ','))
1828b1d344b3Smrg	    break;
1829b1d344b3Smrg	start = end;
1830b1d344b3Smrg    }
1831b1d344b3Smrg    if (!start) {
1832b1d344b3Smrg	temp_path = Xprintf("%s%sbuilt-ins", path, *path ? "," : "");
1833b1d344b3Smrg    } else {
18346747b715Smrg	temp_path = strdup(path);
1835b1d344b3Smrg    }
1836b1d344b3Smrg    if (!temp_path)
1837b1d344b3Smrg        return BadAlloc;
1838b1d344b3Smrg
183905b261ecSmrg    /* get enough for string, plus values -- use up commas */
1840b1d344b3Smrg    len = strlen(temp_path) + 1;
18416747b715Smrg    nump = cp = newpath = malloc(len);
184205b261ecSmrg    if (!newpath)
184305b261ecSmrg	return BadAlloc;
1844b1d344b3Smrg    pp = (unsigned char *) temp_path;
184505b261ecSmrg    cp++;
184605b261ecSmrg    while (*pp) {
184705b261ecSmrg	if (*pp == ',') {
184805b261ecSmrg	    *nump = (unsigned char) size;
184905b261ecSmrg	    nump = cp++;
185005b261ecSmrg	    pp++;
185105b261ecSmrg	    num++;
185205b261ecSmrg	    size = 0;
185305b261ecSmrg	} else {
185405b261ecSmrg	    *cp++ = *pp++;
185505b261ecSmrg	    size++;
185605b261ecSmrg	}
185705b261ecSmrg    }
185805b261ecSmrg    *nump = (unsigned char) size;
185905b261ecSmrg
186005b261ecSmrg    err = SetFontPathElements(num, newpath, &bad, TRUE);
186105b261ecSmrg
18626747b715Smrg    free(newpath);
18636747b715Smrg    free(temp_path);
186405b261ecSmrg
186505b261ecSmrg    return err;
186605b261ecSmrg}
186705b261ecSmrg
18684642e01fSmrgint
18694642e01fSmrgGetFontPath(ClientPtr client, int *count, int *length, unsigned char **result)
187005b261ecSmrg{
187105b261ecSmrg    int			i;
187205b261ecSmrg    unsigned char       *c;
187305b261ecSmrg    int			len;
187405b261ecSmrg    FontPathElementPtr	fpe;
187505b261ecSmrg
18764642e01fSmrg    i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess);
18774642e01fSmrg    if (i != Success)
18784642e01fSmrg	return i;
18794642e01fSmrg
188005b261ecSmrg    len = 0;
188105b261ecSmrg    for (i = 0; i < num_fpes; i++) {
188205b261ecSmrg	fpe = font_path_elements[i];
188305b261ecSmrg	len += fpe->name_length + 1;
188405b261ecSmrg    }
18856747b715Smrg    font_path_string = (unsigned char *) realloc(font_path_string, len);
188605b261ecSmrg    if (!font_path_string)
18874642e01fSmrg	return BadAlloc;
188805b261ecSmrg
188905b261ecSmrg    c = font_path_string;
189005b261ecSmrg    *length = 0;
189105b261ecSmrg    for (i = 0; i < num_fpes; i++) {
189205b261ecSmrg	fpe = font_path_elements[i];
189305b261ecSmrg	*c = fpe->name_length;
189405b261ecSmrg	*length += *c++;
189505b261ecSmrg	memmove(c, fpe->name, fpe->name_length);
189605b261ecSmrg	c += fpe->name_length;
189705b261ecSmrg    }
189805b261ecSmrg    *count = num_fpes;
18994642e01fSmrg    *result = font_path_string;
19004642e01fSmrg    return Success;
190105b261ecSmrg}
190205b261ecSmrg
190305b261ecSmrgvoid
190405b261ecSmrgDeleteClientFontStuff(ClientPtr client)
190505b261ecSmrg{
190605b261ecSmrg    int			i;
190705b261ecSmrg    FontPathElementPtr	fpe;
190805b261ecSmrg
190905b261ecSmrg    for (i = 0; i < num_fpes; i++)
191005b261ecSmrg    {
191105b261ecSmrg	fpe = font_path_elements[i];
191205b261ecSmrg	if (fpe_functions[fpe->type].client_died)
191305b261ecSmrg	    (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
191405b261ecSmrg    }
191505b261ecSmrg}
191605b261ecSmrg
191705b261ecSmrgvoid
191805b261ecSmrgInitFonts (void)
191905b261ecSmrg{
192005b261ecSmrg    patternCache = MakeFontPatternCache();
192105b261ecSmrg
19226747b715Smrg    register_fpe_functions();
192305b261ecSmrg}
192405b261ecSmrg
192505b261ecSmrgint
19266747b715SmrgGetDefaultPointSize (void)
192705b261ecSmrg{
192805b261ecSmrg    return 120;
192905b261ecSmrg}
193005b261ecSmrg
193105b261ecSmrg
193205b261ecSmrgFontResolutionPtr
193305b261ecSmrgGetClientResolutions (int *num)
193405b261ecSmrg{
19354642e01fSmrg    static struct _FontResolution res;
19364642e01fSmrg    ScreenPtr   pScreen;
193705b261ecSmrg
19384642e01fSmrg    pScreen = screenInfo.screens[0];
19394642e01fSmrg    res.x_resolution = (pScreen->width * 25.4) / pScreen->mmWidth;
19404642e01fSmrg    /*
19414642e01fSmrg     * XXX - we'll want this as long as bitmap instances are prevalent
19424642e01fSmrg     so that we can match them from scalable fonts
19434642e01fSmrg     */
19444642e01fSmrg    if (res.x_resolution < 88)
19454642e01fSmrg	res.x_resolution = 75;
19464642e01fSmrg    else
19474642e01fSmrg	res.x_resolution = 100;
19484642e01fSmrg    res.y_resolution = (pScreen->height * 25.4) / pScreen->mmHeight;
19494642e01fSmrg    if (res.y_resolution < 88)
19504642e01fSmrg	res.y_resolution = 75;
19514642e01fSmrg    else
19524642e01fSmrg	res.y_resolution = 100;
19534642e01fSmrg    res.point_size = 120;
19544642e01fSmrg    *num = 1;
19554642e01fSmrg    return &res;
195605b261ecSmrg}
195705b261ecSmrg
195805b261ecSmrg/*
195905b261ecSmrg * returns the type index of the new fpe
196005b261ecSmrg *
196105b261ecSmrg * should be called (only once!) by each type of fpe when initialized
196205b261ecSmrg */
196305b261ecSmrg
196405b261ecSmrgint
196505b261ecSmrgRegisterFPEFunctions(NameCheckFunc name_func,
196605b261ecSmrg		     InitFpeFunc init_func,
196705b261ecSmrg		     FreeFpeFunc free_func,
196805b261ecSmrg		     ResetFpeFunc reset_func,
196905b261ecSmrg		     OpenFontFunc open_func,
197005b261ecSmrg		     CloseFontFunc close_func,
197105b261ecSmrg		     ListFontsFunc list_func,
197205b261ecSmrg		     StartLfwiFunc start_lfwi_func,
197305b261ecSmrg		     NextLfwiFunc next_lfwi_func,
197405b261ecSmrg		     WakeupFpeFunc wakeup_func,
197505b261ecSmrg		     ClientDiedFunc client_died,
197605b261ecSmrg		     LoadGlyphsFunc load_glyphs,
197705b261ecSmrg		     StartLaFunc start_list_alias_func,
197805b261ecSmrg		     NextLaFunc next_list_alias_func,
197905b261ecSmrg		     SetPathFunc set_path_func)
198005b261ecSmrg{
198105b261ecSmrg    FPEFunctions *new;
198205b261ecSmrg
198305b261ecSmrg    /* grow the list */
19846747b715Smrg    new = (FPEFunctions *) realloc(fpe_functions,
198505b261ecSmrg				 (num_fpe_types + 1) * sizeof(FPEFunctions));
198605b261ecSmrg    if (!new)
198705b261ecSmrg	return -1;
198805b261ecSmrg    fpe_functions = new;
198905b261ecSmrg
199005b261ecSmrg    fpe_functions[num_fpe_types].name_check = name_func;
199105b261ecSmrg    fpe_functions[num_fpe_types].open_font = open_func;
199205b261ecSmrg    fpe_functions[num_fpe_types].close_font = close_func;
199305b261ecSmrg    fpe_functions[num_fpe_types].wakeup_fpe = wakeup_func;
199405b261ecSmrg    fpe_functions[num_fpe_types].list_fonts = list_func;
199505b261ecSmrg    fpe_functions[num_fpe_types].start_list_fonts_with_info =
199605b261ecSmrg	start_lfwi_func;
199705b261ecSmrg    fpe_functions[num_fpe_types].list_next_font_with_info =
199805b261ecSmrg	next_lfwi_func;
199905b261ecSmrg    fpe_functions[num_fpe_types].init_fpe = init_func;
200005b261ecSmrg    fpe_functions[num_fpe_types].free_fpe = free_func;
200105b261ecSmrg    fpe_functions[num_fpe_types].reset_fpe = reset_func;
200205b261ecSmrg    fpe_functions[num_fpe_types].client_died = client_died;
200305b261ecSmrg    fpe_functions[num_fpe_types].load_glyphs = load_glyphs;
200405b261ecSmrg    fpe_functions[num_fpe_types].start_list_fonts_and_aliases =
200505b261ecSmrg	start_list_alias_func;
200605b261ecSmrg    fpe_functions[num_fpe_types].list_next_font_or_alias =
200705b261ecSmrg	next_list_alias_func;
200805b261ecSmrg    fpe_functions[num_fpe_types].set_path_hook = set_path_func;
200905b261ecSmrg
201005b261ecSmrg    return num_fpe_types++;
201105b261ecSmrg}
201205b261ecSmrg
201305b261ecSmrgvoid
201405b261ecSmrgFreeFonts(void)
201505b261ecSmrg{
201605b261ecSmrg    if (patternCache) {
201705b261ecSmrg	FreeFontPatternCache(patternCache);
201805b261ecSmrg	patternCache = 0;
201905b261ecSmrg    }
202005b261ecSmrg    FreeFontPath(font_path_elements, num_fpes, TRUE);
202105b261ecSmrg    font_path_elements = 0;
202205b261ecSmrg    num_fpes = 0;
20236747b715Smrg    free(fpe_functions);
202405b261ecSmrg    num_fpe_types = 0;
202505b261ecSmrg    fpe_functions = (FPEFunctions *) 0;
202605b261ecSmrg}
202705b261ecSmrg
202805b261ecSmrg/* convenience functions for FS interface */
202905b261ecSmrg
203005b261ecSmrgFontPtr
203105b261ecSmrgfind_old_font(XID id)
203205b261ecSmrg{
20336747b715Smrg    pointer pFont;
20346747b715Smrg    dixLookupResourceByType(&pFont, id, RT_NONE, serverClient, DixReadAccess);
20356747b715Smrg    return (FontPtr)pFont;
203605b261ecSmrg}
203705b261ecSmrg
203805b261ecSmrgFont
20396747b715SmrgGetNewFontClientID(void)
204005b261ecSmrg{
204105b261ecSmrg    return FakeClientID(0);
204205b261ecSmrg}
204305b261ecSmrg
204405b261ecSmrgint
204505b261ecSmrgStoreFontClientFont(FontPtr pfont, Font id)
204605b261ecSmrg{
204705b261ecSmrg    return AddResource(id, RT_NONE, (pointer) pfont);
204805b261ecSmrg}
204905b261ecSmrg
205005b261ecSmrgvoid
205105b261ecSmrgDeleteFontClientID(Font id)
205205b261ecSmrg{
205305b261ecSmrg    FreeResource(id, RT_NONE);
205405b261ecSmrg}
205505b261ecSmrg
205605b261ecSmrgint
205705b261ecSmrgclient_auth_generation(ClientPtr client)
205805b261ecSmrg{
205905b261ecSmrg    return 0;
206005b261ecSmrg}
206105b261ecSmrg
206205b261ecSmrgstatic int  fs_handlers_installed = 0;
206305b261ecSmrgstatic unsigned int last_server_gen;
206405b261ecSmrg
206505b261ecSmrgint
206605b261ecSmrginit_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler)
206705b261ecSmrg{
206805b261ecSmrg    /* if server has reset, make sure the b&w handlers are reinstalled */
206905b261ecSmrg    if (last_server_gen < serverGeneration) {
207005b261ecSmrg	last_server_gen = serverGeneration;
207105b261ecSmrg	fs_handlers_installed = 0;
207205b261ecSmrg    }
207305b261ecSmrg    if (fs_handlers_installed == 0) {
207405b261ecSmrg	if (!RegisterBlockAndWakeupHandlers(block_handler,
207505b261ecSmrg					    FontWakeup, (pointer) 0))
207605b261ecSmrg	    return AllocError;
207705b261ecSmrg	fs_handlers_installed++;
207805b261ecSmrg    }
207905b261ecSmrg    QueueFontWakeup(fpe);
208005b261ecSmrg    return Successful;
208105b261ecSmrg}
208205b261ecSmrg
208305b261ecSmrgvoid
208405b261ecSmrgremove_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler, Bool all)
208505b261ecSmrg{
208605b261ecSmrg    if (all) {
208705b261ecSmrg	/* remove the handlers if no one else is using them */
208805b261ecSmrg	if (--fs_handlers_installed == 0) {
208905b261ecSmrg	    RemoveBlockAndWakeupHandlers(block_handler, FontWakeup,
209005b261ecSmrg					 (pointer) 0);
209105b261ecSmrg	}
209205b261ecSmrg    }
209305b261ecSmrg    RemoveFontWakeup(fpe);
209405b261ecSmrg}
2095