dixfonts.c revision b1d344b3
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#define NEED_REPLIES
5205b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
5305b261ecSmrg#include <dix-config.h>
5405b261ecSmrg#endif
5505b261ecSmrg
5605b261ecSmrg#include <X11/X.h>
5705b261ecSmrg#include <X11/Xmd.h>
5805b261ecSmrg#include <X11/Xproto.h>
5905b261ecSmrg#include "scrnintstr.h"
6005b261ecSmrg#include "resource.h"
6105b261ecSmrg#include "dixstruct.h"
6205b261ecSmrg#include "cursorstr.h"
6305b261ecSmrg#include "misc.h"
6405b261ecSmrg#include "opaque.h"
6505b261ecSmrg#include "dixfontstr.h"
6605b261ecSmrg#include "closestr.h"
6705b261ecSmrg#include "dixfont.h"
684642e01fSmrg#include "xace.h"
6905b261ecSmrg
7005b261ecSmrg#ifdef DEBUG
7105b261ecSmrg#include	<stdio.h>
7205b261ecSmrg#endif
7305b261ecSmrg
7405b261ecSmrg#ifdef PANORAMIX
7505b261ecSmrg#include "panoramiX.h"
7605b261ecSmrg#endif
7705b261ecSmrg
7805b261ecSmrg#ifdef XF86BIGFONT
7905b261ecSmrg#define _XF86BIGFONT_SERVER_
8005b261ecSmrg#include <X11/extensions/xf86bigfont.h>
8105b261ecSmrg#endif
8205b261ecSmrg
8305b261ecSmrg#define QUERYCHARINFO(pci, pr)  *(pr) = (pci)->metrics
8405b261ecSmrg
8505b261ecSmrgextern pointer fosNaturalParams;
8605b261ecSmrgextern FontPtr defaultFont;
8705b261ecSmrg
8805b261ecSmrgstatic FontPathElementPtr *font_path_elements = (FontPathElementPtr *) 0;
8905b261ecSmrgstatic int  num_fpes = 0;
904642e01fSmrgstatic FPEFunctions *fpe_functions = (FPEFunctions *) 0;
9105b261ecSmrgstatic int  num_fpe_types = 0;
9205b261ecSmrg
9305b261ecSmrgstatic unsigned char *font_path_string;
9405b261ecSmrg
9505b261ecSmrgstatic int  num_slept_fpes = 0;
9605b261ecSmrgstatic int  size_slept_fpes = 0;
9705b261ecSmrgstatic FontPathElementPtr *slept_fpes = (FontPathElementPtr *) 0;
9805b261ecSmrgstatic FontPatternCachePtr patternCache;
9905b261ecSmrg
1004642e01fSmrgstatic int
1014642e01fSmrgFontToXError(int err)
10205b261ecSmrg{
10305b261ecSmrg    switch (err) {
10405b261ecSmrg    case Successful:
10505b261ecSmrg	return Success;
10605b261ecSmrg    case AllocError:
10705b261ecSmrg	return BadAlloc;
10805b261ecSmrg    case BadFontName:
10905b261ecSmrg	return BadName;
11005b261ecSmrg    case BadFontPath:
11105b261ecSmrg    case BadFontFormat:	/* is there something better? */
11205b261ecSmrg    case BadCharRange:
11305b261ecSmrg	return BadValue;
11405b261ecSmrg    default:
11505b261ecSmrg	return err;
11605b261ecSmrg    }
11705b261ecSmrg}
11805b261ecSmrg
1194642e01fSmrgstatic int
1204642e01fSmrgLoadGlyphs(ClientPtr client, FontPtr pfont, unsigned nchars, int item_size,
1214642e01fSmrg	   unsigned char *data)
1224642e01fSmrg{
1234642e01fSmrg    if (fpe_functions[pfont->fpe->type].load_glyphs)
1244642e01fSmrg	return (*fpe_functions[pfont->fpe->type].load_glyphs)
1254642e01fSmrg	    (client, pfont, 0, nchars, item_size, data);
1264642e01fSmrg    else
1274642e01fSmrg	return Successful;
1284642e01fSmrg}
12905b261ecSmrg
13005b261ecSmrg/*
13105b261ecSmrg * adding RT_FONT prevents conflict with default cursor font
13205b261ecSmrg */
13305b261ecSmrgBool
13405b261ecSmrgSetDefaultFont(char *defaultfontname)
13505b261ecSmrg{
13605b261ecSmrg    int         err;
13705b261ecSmrg    FontPtr     pf;
13805b261ecSmrg    XID         fid;
13905b261ecSmrg
14005b261ecSmrg    fid = FakeClientID(0);
14105b261ecSmrg    err = OpenFont(serverClient, fid, FontLoadAll | FontOpenSync,
14205b261ecSmrg		   (unsigned) strlen(defaultfontname), defaultfontname);
14305b261ecSmrg    if (err != Success)
14405b261ecSmrg	return FALSE;
14505b261ecSmrg    pf = (FontPtr) LookupIDByType(fid, RT_FONT);
14605b261ecSmrg    if (pf == (FontPtr) NULL)
14705b261ecSmrg	return FALSE;
14805b261ecSmrg    defaultFont = pf;
14905b261ecSmrg    return TRUE;
15005b261ecSmrg}
15105b261ecSmrg
15205b261ecSmrg/*
15305b261ecSmrg * note that the font wakeup queue is not refcounted.  this is because
15405b261ecSmrg * an fpe needs to be added when it's inited, and removed when it's finally
15505b261ecSmrg * freed, in order to handle any data that isn't requested, like FS events.
15605b261ecSmrg *
15705b261ecSmrg * since the only thing that should call these routines is the renderer's
15805b261ecSmrg * init_fpe() and free_fpe(), there shouldn't be any problem in using
15905b261ecSmrg * freed data.
16005b261ecSmrg */
16105b261ecSmrgvoid
16205b261ecSmrgQueueFontWakeup(FontPathElementPtr fpe)
16305b261ecSmrg{
16405b261ecSmrg    int         i;
16505b261ecSmrg    FontPathElementPtr *new;
16605b261ecSmrg
16705b261ecSmrg    for (i = 0; i < num_slept_fpes; i++) {
16805b261ecSmrg	if (slept_fpes[i] == fpe) {
16905b261ecSmrg	    return;
17005b261ecSmrg	}
17105b261ecSmrg    }
17205b261ecSmrg    if (num_slept_fpes == size_slept_fpes) {
17305b261ecSmrg	new = (FontPathElementPtr *)
17405b261ecSmrg	    xrealloc(slept_fpes,
17505b261ecSmrg		     sizeof(FontPathElementPtr) * (size_slept_fpes + 4));
17605b261ecSmrg	if (!new)
17705b261ecSmrg	    return;
17805b261ecSmrg	slept_fpes = new;
17905b261ecSmrg	size_slept_fpes += 4;
18005b261ecSmrg    }
18105b261ecSmrg    slept_fpes[num_slept_fpes] = fpe;
18205b261ecSmrg    num_slept_fpes++;
18305b261ecSmrg}
18405b261ecSmrg
18505b261ecSmrgvoid
18605b261ecSmrgRemoveFontWakeup(FontPathElementPtr fpe)
18705b261ecSmrg{
18805b261ecSmrg    int         i,
18905b261ecSmrg                j;
19005b261ecSmrg
19105b261ecSmrg    for (i = 0; i < num_slept_fpes; i++) {
19205b261ecSmrg	if (slept_fpes[i] == fpe) {
19305b261ecSmrg	    for (j = i; j < num_slept_fpes; j++) {
19405b261ecSmrg		slept_fpes[j] = slept_fpes[j + 1];
19505b261ecSmrg	    }
19605b261ecSmrg	    num_slept_fpes--;
19705b261ecSmrg	    return;
19805b261ecSmrg	}
19905b261ecSmrg    }
20005b261ecSmrg}
20105b261ecSmrg
20205b261ecSmrgvoid
20305b261ecSmrgFontWakeup(pointer data, int count, pointer LastSelectMask)
20405b261ecSmrg{
20505b261ecSmrg    int         i;
20605b261ecSmrg    FontPathElementPtr fpe;
20705b261ecSmrg
20805b261ecSmrg    if (count < 0)
20905b261ecSmrg	return;
21005b261ecSmrg    /* wake up any fpe's that may be waiting for information */
21105b261ecSmrg    for (i = 0; i < num_slept_fpes; i++) {
21205b261ecSmrg	fpe = slept_fpes[i];
21305b261ecSmrg	(void) (*fpe_functions[fpe->type].wakeup_fpe) (fpe, LastSelectMask);
21405b261ecSmrg    }
21505b261ecSmrg}
21605b261ecSmrg
21705b261ecSmrg/* XXX -- these two funcs may want to be broken into macros */
21805b261ecSmrgstatic void
21905b261ecSmrgUseFPE(FontPathElementPtr fpe)
22005b261ecSmrg{
22105b261ecSmrg    fpe->refcount++;
22205b261ecSmrg}
22305b261ecSmrg
22405b261ecSmrgstatic void
22505b261ecSmrgFreeFPE (FontPathElementPtr fpe)
22605b261ecSmrg{
22705b261ecSmrg    fpe->refcount--;
22805b261ecSmrg    if (fpe->refcount == 0) {
22905b261ecSmrg	(*fpe_functions[fpe->type].free_fpe) (fpe);
23005b261ecSmrg	xfree(fpe->name);
23105b261ecSmrg	xfree(fpe);
23205b261ecSmrg    }
23305b261ecSmrg}
23405b261ecSmrg
23505b261ecSmrgstatic Bool
23605b261ecSmrgdoOpenFont(ClientPtr client, OFclosurePtr c)
23705b261ecSmrg{
23805b261ecSmrg    FontPtr     pfont = NullFont;
23905b261ecSmrg    FontPathElementPtr fpe = NULL;
24005b261ecSmrg    ScreenPtr   pScr;
24105b261ecSmrg    int         err = Successful;
24205b261ecSmrg    int         i;
24305b261ecSmrg    char       *alias,
24405b261ecSmrg               *newname;
24505b261ecSmrg    int         newlen;
24605b261ecSmrg    int		aliascount = 20;
24705b261ecSmrg    /*
24805b261ecSmrg     * Decide at runtime what FontFormat to use.
24905b261ecSmrg     */
25005b261ecSmrg    Mask FontFormat =
25105b261ecSmrg
25205b261ecSmrg	((screenInfo.imageByteOrder == LSBFirst) ?
25305b261ecSmrg	    BitmapFormatByteOrderLSB : BitmapFormatByteOrderMSB) |
25405b261ecSmrg
25505b261ecSmrg	((screenInfo.bitmapBitOrder == LSBFirst) ?
25605b261ecSmrg	    BitmapFormatBitOrderLSB : BitmapFormatBitOrderMSB) |
25705b261ecSmrg
25805b261ecSmrg	BitmapFormatImageRectMin |
25905b261ecSmrg
26005b261ecSmrg#if GLYPHPADBYTES == 1
26105b261ecSmrg	BitmapFormatScanlinePad8 |
26205b261ecSmrg#endif
26305b261ecSmrg
26405b261ecSmrg#if GLYPHPADBYTES == 2
26505b261ecSmrg	BitmapFormatScanlinePad16 |
26605b261ecSmrg#endif
26705b261ecSmrg
26805b261ecSmrg#if GLYPHPADBYTES == 4
26905b261ecSmrg	BitmapFormatScanlinePad32 |
27005b261ecSmrg#endif
27105b261ecSmrg
27205b261ecSmrg#if GLYPHPADBYTES == 8
27305b261ecSmrg	BitmapFormatScanlinePad64 |
27405b261ecSmrg#endif
27505b261ecSmrg
27605b261ecSmrg	BitmapFormatScanlineUnit8;
27705b261ecSmrg
27805b261ecSmrg    if (client->clientGone)
27905b261ecSmrg    {
28005b261ecSmrg	if (c->current_fpe < c->num_fpes)
28105b261ecSmrg	{
28205b261ecSmrg	    fpe = c->fpe_list[c->current_fpe];
28305b261ecSmrg	    (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
28405b261ecSmrg	}
28505b261ecSmrg	err = Successful;
28605b261ecSmrg	goto bail;
28705b261ecSmrg    }
28805b261ecSmrg    while (c->current_fpe < c->num_fpes) {
28905b261ecSmrg	fpe = c->fpe_list[c->current_fpe];
29005b261ecSmrg	err = (*fpe_functions[fpe->type].open_font)
29105b261ecSmrg	    ((pointer) client, fpe, c->flags,
29205b261ecSmrg	     c->fontname, c->fnamelen, FontFormat,
29305b261ecSmrg	     BitmapFormatMaskByte |
29405b261ecSmrg	     BitmapFormatMaskBit |
29505b261ecSmrg	     BitmapFormatMaskImageRectangle |
29605b261ecSmrg	     BitmapFormatMaskScanLinePad |
29705b261ecSmrg	     BitmapFormatMaskScanLineUnit,
29805b261ecSmrg	     c->fontid, &pfont, &alias,
29905b261ecSmrg	     c->non_cachable_font && c->non_cachable_font->fpe == fpe ?
30005b261ecSmrg		 c->non_cachable_font :
30105b261ecSmrg		 (FontPtr)0);
30205b261ecSmrg
30305b261ecSmrg	if (err == FontNameAlias && alias) {
30405b261ecSmrg	    newlen = strlen(alias);
30505b261ecSmrg	    newname = (char *) xrealloc(c->fontname, newlen);
30605b261ecSmrg	    if (!newname) {
30705b261ecSmrg		err = AllocError;
30805b261ecSmrg		break;
30905b261ecSmrg	    }
31005b261ecSmrg	    memmove(newname, alias, newlen);
31105b261ecSmrg	    c->fontname = newname;
31205b261ecSmrg	    c->fnamelen = newlen;
31305b261ecSmrg	    c->current_fpe = 0;
3144642e01fSmrg	    if (--aliascount <= 0) {
3154642e01fSmrg		/* We've tried resolving this alias 20 times, we're
3164642e01fSmrg 		 * probably stuck in an infinite loop of aliases pointing
3174642e01fSmrg 		 * to each other - time to take emergency exit!
3184642e01fSmrg 		 */
3194642e01fSmrg 		err = BadImplementation;
32005b261ecSmrg		break;
3214642e01fSmrg	    }
32205b261ecSmrg	    continue;
32305b261ecSmrg	}
32405b261ecSmrg	if (err == BadFontName) {
32505b261ecSmrg	    c->current_fpe++;
32605b261ecSmrg	    continue;
32705b261ecSmrg	}
32805b261ecSmrg	if (err == Suspended) {
32905b261ecSmrg	    if (!c->slept) {
33005b261ecSmrg		c->slept = TRUE;
33105b261ecSmrg		ClientSleep(client, (ClientSleepProcPtr)doOpenFont, (pointer) c);
33205b261ecSmrg	    }
33305b261ecSmrg	    return TRUE;
33405b261ecSmrg	}
33505b261ecSmrg	break;
33605b261ecSmrg    }
33705b261ecSmrg
33805b261ecSmrg    if (err != Successful)
33905b261ecSmrg	goto bail;
34005b261ecSmrg    if (!pfont) {
34105b261ecSmrg	err = BadFontName;
34205b261ecSmrg	goto bail;
34305b261ecSmrg    }
34405b261ecSmrg    /* check values for firstCol, lastCol, firstRow, and lastRow */
34505b261ecSmrg    if (pfont->info.firstCol > pfont->info.lastCol ||
34605b261ecSmrg       pfont->info.firstRow > pfont->info.lastRow ||
34705b261ecSmrg       pfont->info.lastCol - pfont->info.firstCol > 255) {
34805b261ecSmrg       err = AllocError;
34905b261ecSmrg       goto bail;
35005b261ecSmrg    }
35105b261ecSmrg    if (!pfont->fpe)
35205b261ecSmrg	pfont->fpe = fpe;
35305b261ecSmrg    pfont->refcnt++;
35405b261ecSmrg    if (pfont->refcnt == 1) {
35505b261ecSmrg	UseFPE(pfont->fpe);
35605b261ecSmrg	for (i = 0; i < screenInfo.numScreens; i++) {
35705b261ecSmrg	    pScr = screenInfo.screens[i];
35805b261ecSmrg	    if (pScr->RealizeFont)
35905b261ecSmrg	    {
36005b261ecSmrg		if (!(*pScr->RealizeFont) (pScr, pfont))
36105b261ecSmrg		{
36205b261ecSmrg		    CloseFont (pfont, (Font) 0);
36305b261ecSmrg		    err = AllocError;
36405b261ecSmrg		    goto bail;
36505b261ecSmrg		}
36605b261ecSmrg	    }
36705b261ecSmrg	}
36805b261ecSmrg    }
36905b261ecSmrg    if (!AddResource(c->fontid, RT_FONT, (pointer) pfont)) {
37005b261ecSmrg	err = AllocError;
37105b261ecSmrg	goto bail;
37205b261ecSmrg    }
37305b261ecSmrg    if (patternCache && pfont != c->non_cachable_font)
37405b261ecSmrg	CacheFontPattern(patternCache, c->origFontName, c->origFontNameLen,
37505b261ecSmrg			 pfont);
37605b261ecSmrgbail:
37705b261ecSmrg    if (err != Successful && c->client != serverClient) {
37805b261ecSmrg	SendErrorToClient(c->client, X_OpenFont, 0,
37905b261ecSmrg			  c->fontid, FontToXError(err));
38005b261ecSmrg    }
38105b261ecSmrg    if (c->slept)
38205b261ecSmrg	ClientWakeup(c->client);
38305b261ecSmrg    for (i = 0; i < c->num_fpes; i++) {
38405b261ecSmrg	FreeFPE(c->fpe_list[i]);
38505b261ecSmrg    }
38605b261ecSmrg    xfree(c->fpe_list);
38705b261ecSmrg    xfree(c->fontname);
38805b261ecSmrg    xfree(c);
38905b261ecSmrg    return TRUE;
39005b261ecSmrg}
39105b261ecSmrg
39205b261ecSmrgint
39305b261ecSmrgOpenFont(ClientPtr client, XID fid, Mask flags, unsigned lenfname, char *pfontname)
39405b261ecSmrg{
39505b261ecSmrg    OFclosurePtr c;
39605b261ecSmrg    int         i;
39705b261ecSmrg    FontPtr     cached = (FontPtr)0;
39805b261ecSmrg
39905b261ecSmrg#ifdef FONTDEBUG
40005b261ecSmrg    char *f;
40105b261ecSmrg    f = (char *)xalloc(lenfname + 1);
40205b261ecSmrg    memmove(f, pfontname, lenfname);
40305b261ecSmrg    f[lenfname] = '\0';
4044642e01fSmrg    ErrorF("[dix] OpenFont: fontname is \"%s\"\n", f);
40505b261ecSmrg    xfree(f);
40605b261ecSmrg#endif
40705b261ecSmrg    if (!lenfname || lenfname > XLFDMAXFONTNAMELEN)
40805b261ecSmrg	return BadName;
40905b261ecSmrg    if (patternCache)
41005b261ecSmrg    {
41105b261ecSmrg
41205b261ecSmrg    /*
41305b261ecSmrg    ** Check name cache.  If we find a cached version of this font that
41405b261ecSmrg    ** is cachable, immediately satisfy the request with it.  If we find
41505b261ecSmrg    ** a cached version of this font that is non-cachable, we do not
41605b261ecSmrg    ** satisfy the request with it.  Instead, we pass the FontPtr to the
41705b261ecSmrg    ** FPE's open_font code (the fontfile FPE in turn passes the
41805b261ecSmrg    ** information to the rasterizer; the fserve FPE ignores it).
41905b261ecSmrg    **
42005b261ecSmrg    ** Presumably, the font is marked non-cachable because the FPE has
42105b261ecSmrg    ** put some licensing restrictions on it.  If the FPE, using
42205b261ecSmrg    ** whatever logic it relies on, determines that it is willing to
42305b261ecSmrg    ** share this existing font with the client, then it has the option
42405b261ecSmrg    ** to return the FontPtr we passed it as the newly-opened font.
42505b261ecSmrg    ** This allows the FPE to exercise its licensing logic without
42605b261ecSmrg    ** having to create another instance of a font that already exists.
42705b261ecSmrg    */
42805b261ecSmrg
42905b261ecSmrg	cached = FindCachedFontPattern(patternCache, pfontname, lenfname);
43005b261ecSmrg	if (cached && cached->info.cachable)
43105b261ecSmrg	{
43205b261ecSmrg	    if (!AddResource(fid, RT_FONT, (pointer) cached))
43305b261ecSmrg		return BadAlloc;
43405b261ecSmrg	    cached->refcnt++;
43505b261ecSmrg	    return Success;
43605b261ecSmrg	}
43705b261ecSmrg    }
43805b261ecSmrg    c = (OFclosurePtr) xalloc(sizeof(OFclosureRec));
43905b261ecSmrg    if (!c)
44005b261ecSmrg	return BadAlloc;
44105b261ecSmrg    c->fontname = (char *) xalloc(lenfname);
44205b261ecSmrg    c->origFontName = pfontname;
44305b261ecSmrg    c->origFontNameLen = lenfname;
44405b261ecSmrg    if (!c->fontname) {
44505b261ecSmrg	xfree(c);
44605b261ecSmrg	return BadAlloc;
44705b261ecSmrg    }
44805b261ecSmrg    /*
44905b261ecSmrg     * copy the current FPE list, so that if it gets changed by another client
45005b261ecSmrg     * while we're blocking, the request still appears atomic
45105b261ecSmrg     */
45205b261ecSmrg    c->fpe_list = (FontPathElementPtr *)
45305b261ecSmrg	xalloc(sizeof(FontPathElementPtr) * num_fpes);
45405b261ecSmrg    if (!c->fpe_list) {
45505b261ecSmrg	xfree(c->fontname);
45605b261ecSmrg	xfree(c);
45705b261ecSmrg	return BadAlloc;
45805b261ecSmrg    }
45905b261ecSmrg    memmove(c->fontname, pfontname, lenfname);
46005b261ecSmrg    for (i = 0; i < num_fpes; i++) {
46105b261ecSmrg	c->fpe_list[i] = font_path_elements[i];
46205b261ecSmrg	UseFPE(c->fpe_list[i]);
46305b261ecSmrg    }
46405b261ecSmrg    c->client = client;
46505b261ecSmrg    c->fontid = fid;
46605b261ecSmrg    c->current_fpe = 0;
46705b261ecSmrg    c->num_fpes = num_fpes;
46805b261ecSmrg    c->fnamelen = lenfname;
46905b261ecSmrg    c->slept = FALSE;
47005b261ecSmrg    c->flags = flags;
47105b261ecSmrg    c->non_cachable_font = cached;
47205b261ecSmrg
47305b261ecSmrg    (void) doOpenFont(client, c);
47405b261ecSmrg    return Success;
47505b261ecSmrg}
47605b261ecSmrg
47705b261ecSmrg/**
47805b261ecSmrg * Decrement font's ref count, and free storage if ref count equals zero
47905b261ecSmrg *
48005b261ecSmrg *  \param value must conform to DeleteType
48105b261ecSmrg */
4824642e01fSmrgint
48305b261ecSmrgCloseFont(pointer value, XID fid)
48405b261ecSmrg{
48505b261ecSmrg    int         nscr;
48605b261ecSmrg    ScreenPtr   pscr;
48705b261ecSmrg    FontPathElementPtr fpe;
48805b261ecSmrg    FontPtr     pfont = (FontPtr)value;
48905b261ecSmrg
49005b261ecSmrg    if (pfont == NullFont)
49105b261ecSmrg	return (Success);
49205b261ecSmrg    if (--pfont->refcnt == 0) {
49305b261ecSmrg	if (patternCache)
49405b261ecSmrg	    RemoveCachedFontPattern (patternCache, pfont);
49505b261ecSmrg	/*
49605b261ecSmrg	 * since the last reference is gone, ask each screen to free any
49705b261ecSmrg	 * storage it may have allocated locally for it.
49805b261ecSmrg	 */
49905b261ecSmrg	for (nscr = 0; nscr < screenInfo.numScreens; nscr++) {
50005b261ecSmrg	    pscr = screenInfo.screens[nscr];
50105b261ecSmrg	    if (pscr->UnrealizeFont)
50205b261ecSmrg		(*pscr->UnrealizeFont) (pscr, pfont);
50305b261ecSmrg	}
50405b261ecSmrg	if (pfont == defaultFont)
50505b261ecSmrg	    defaultFont = NULL;
50605b261ecSmrg#ifdef XF86BIGFONT
50705b261ecSmrg	XF86BigfontFreeFontShm(pfont);
50805b261ecSmrg#endif
50905b261ecSmrg	fpe = pfont->fpe;
51005b261ecSmrg	(*fpe_functions[fpe->type].close_font) (fpe, pfont);
51105b261ecSmrg	FreeFPE(fpe);
51205b261ecSmrg    }
51305b261ecSmrg    return (Success);
51405b261ecSmrg}
51505b261ecSmrg
51605b261ecSmrg
51705b261ecSmrg/***====================================================================***/
51805b261ecSmrg
51905b261ecSmrg/**
52005b261ecSmrg * Sets up pReply as the correct QueryFontReply for pFont with the first
52105b261ecSmrg * nProtoCCIStructs char infos.
52205b261ecSmrg *
52305b261ecSmrg *  \param pReply caller must allocate this storage
52405b261ecSmrg  */
52505b261ecSmrgvoid
52605b261ecSmrgQueryFont(FontPtr pFont, xQueryFontReply *pReply, int nProtoCCIStructs)
52705b261ecSmrg{
52805b261ecSmrg    FontPropPtr      pFP;
52905b261ecSmrg    int              r,
53005b261ecSmrg                     c,
53105b261ecSmrg                     i;
53205b261ecSmrg    xFontProp       *prFP;
53305b261ecSmrg    xCharInfo       *prCI;
53405b261ecSmrg    xCharInfo       *charInfos[256];
53505b261ecSmrg    unsigned char    chars[512];
53605b261ecSmrg    int              ninfos;
53705b261ecSmrg    unsigned long    ncols;
53805b261ecSmrg    unsigned long    count;
53905b261ecSmrg
54005b261ecSmrg    /* pr->length set in dispatch */
54105b261ecSmrg    pReply->minCharOrByte2 = pFont->info.firstCol;
54205b261ecSmrg    pReply->defaultChar = pFont->info.defaultCh;
54305b261ecSmrg    pReply->maxCharOrByte2 = pFont->info.lastCol;
54405b261ecSmrg    pReply->drawDirection = pFont->info.drawDirection;
54505b261ecSmrg    pReply->allCharsExist = pFont->info.allExist;
54605b261ecSmrg    pReply->minByte1 = pFont->info.firstRow;
54705b261ecSmrg    pReply->maxByte1 = pFont->info.lastRow;
54805b261ecSmrg    pReply->fontAscent = pFont->info.fontAscent;
54905b261ecSmrg    pReply->fontDescent = pFont->info.fontDescent;
55005b261ecSmrg
55105b261ecSmrg    pReply->minBounds = pFont->info.ink_minbounds;
55205b261ecSmrg    pReply->maxBounds = pFont->info.ink_maxbounds;
55305b261ecSmrg
55405b261ecSmrg    pReply->nFontProps = pFont->info.nprops;
55505b261ecSmrg    pReply->nCharInfos = nProtoCCIStructs;
55605b261ecSmrg
55705b261ecSmrg    for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) (&pReply[1]);
55805b261ecSmrg	    i < pFont->info.nprops;
55905b261ecSmrg	    i++, pFP++, prFP++) {
56005b261ecSmrg	prFP->name = pFP->name;
56105b261ecSmrg	prFP->value = pFP->value;
56205b261ecSmrg    }
56305b261ecSmrg
56405b261ecSmrg    ninfos = 0;
56505b261ecSmrg    ncols = (unsigned long) (pFont->info.lastCol - pFont->info.firstCol + 1);
56605b261ecSmrg    prCI = (xCharInfo *) (prFP);
56705b261ecSmrg    for (r = pFont->info.firstRow;
56805b261ecSmrg	    ninfos < nProtoCCIStructs && r <= (int)pFont->info.lastRow;
56905b261ecSmrg	    r++) {
57005b261ecSmrg	i = 0;
57105b261ecSmrg	for (c = pFont->info.firstCol; c <= (int)pFont->info.lastCol; c++) {
57205b261ecSmrg	    chars[i++] = r;
57305b261ecSmrg	    chars[i++] = c;
57405b261ecSmrg	}
57505b261ecSmrg	(*pFont->get_metrics) (pFont, ncols, chars,
57605b261ecSmrg				TwoD16Bit, &count, charInfos);
57705b261ecSmrg	i = 0;
57805b261ecSmrg	for (i = 0; i < (int) count && ninfos < nProtoCCIStructs; i++) {
57905b261ecSmrg	    *prCI = *charInfos[i];
58005b261ecSmrg	    prCI++;
58105b261ecSmrg	    ninfos++;
58205b261ecSmrg	}
58305b261ecSmrg    }
58405b261ecSmrg    return;
58505b261ecSmrg}
58605b261ecSmrg
58705b261ecSmrgstatic Bool
58805b261ecSmrgdoListFontsAndAliases(ClientPtr client, LFclosurePtr c)
58905b261ecSmrg{
59005b261ecSmrg    FontPathElementPtr fpe;
59105b261ecSmrg    int         err = Successful;
59205b261ecSmrg    FontNamesPtr names = NULL;
59305b261ecSmrg    char       *name, *resolved=NULL;
59405b261ecSmrg    int         namelen, resolvedlen;
59505b261ecSmrg    int		nnames;
59605b261ecSmrg    int         stringLens;
59705b261ecSmrg    int         i;
59805b261ecSmrg    xListFontsReply reply;
59905b261ecSmrg    char	*bufptr;
60005b261ecSmrg    char	*bufferStart;
60105b261ecSmrg    int		aliascount = 0;
60205b261ecSmrg
60305b261ecSmrg    if (client->clientGone)
60405b261ecSmrg    {
60505b261ecSmrg	if (c->current.current_fpe < c->num_fpes)
60605b261ecSmrg	{
60705b261ecSmrg	    fpe = c->fpe_list[c->current.current_fpe];
60805b261ecSmrg	    (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
60905b261ecSmrg	}
61005b261ecSmrg	err = Successful;
61105b261ecSmrg	goto bail;
61205b261ecSmrg    }
61305b261ecSmrg
61405b261ecSmrg    if (!c->current.patlen)
61505b261ecSmrg	goto finish;
61605b261ecSmrg
61705b261ecSmrg    while (c->current.current_fpe < c->num_fpes) {
61805b261ecSmrg	fpe = c->fpe_list[c->current.current_fpe];
61905b261ecSmrg	err = Successful;
62005b261ecSmrg
62105b261ecSmrg	if (!fpe_functions[fpe->type].start_list_fonts_and_aliases)
62205b261ecSmrg	{
62305b261ecSmrg	    /* This FPE doesn't support/require list_fonts_and_aliases */
62405b261ecSmrg
62505b261ecSmrg	    err = (*fpe_functions[fpe->type].list_fonts)
62605b261ecSmrg		((pointer) c->client, fpe, c->current.pattern,
62705b261ecSmrg		 c->current.patlen, c->current.max_names - c->names->nnames,
62805b261ecSmrg		 c->names);
62905b261ecSmrg
63005b261ecSmrg	    if (err == Suspended) {
63105b261ecSmrg		if (!c->slept) {
63205b261ecSmrg		    c->slept = TRUE;
63305b261ecSmrg		    ClientSleep(client,
63405b261ecSmrg			(ClientSleepProcPtr)doListFontsAndAliases,
63505b261ecSmrg			(pointer) c);
63605b261ecSmrg		}
63705b261ecSmrg		return TRUE;
63805b261ecSmrg	    }
63905b261ecSmrg
64005b261ecSmrg	    err = BadFontName;
64105b261ecSmrg	}
64205b261ecSmrg	else
64305b261ecSmrg	{
64405b261ecSmrg	    /* Start of list_fonts_and_aliases functionality.  Modeled
64505b261ecSmrg	       after list_fonts_with_info in that it resolves aliases,
64605b261ecSmrg	       except that the information collected from FPEs is just
64705b261ecSmrg	       names, not font info.  Each list_next_font_or_alias()
64805b261ecSmrg	       returns either a name into name/namelen or an alias into
64905b261ecSmrg	       name/namelen and its target name into resolved/resolvedlen.
65005b261ecSmrg	       The code at this level then resolves the alias by polling
65105b261ecSmrg	       the FPEs.  */
65205b261ecSmrg
65305b261ecSmrg	    if (!c->current.list_started) {
65405b261ecSmrg		err = (*fpe_functions[fpe->type].start_list_fonts_and_aliases)
65505b261ecSmrg		    ((pointer) c->client, fpe, c->current.pattern,
65605b261ecSmrg		     c->current.patlen, c->current.max_names - c->names->nnames,
65705b261ecSmrg		     &c->current.private);
65805b261ecSmrg		if (err == Suspended) {
65905b261ecSmrg		    if (!c->slept) {
66005b261ecSmrg			ClientSleep(client,
66105b261ecSmrg				    (ClientSleepProcPtr)doListFontsAndAliases,
66205b261ecSmrg				    (pointer) c);
66305b261ecSmrg			c->slept = TRUE;
66405b261ecSmrg		    }
66505b261ecSmrg		    return TRUE;
66605b261ecSmrg		}
66705b261ecSmrg		if (err == Successful)
66805b261ecSmrg		    c->current.list_started = TRUE;
66905b261ecSmrg	    }
67005b261ecSmrg	    if (err == Successful) {
67105b261ecSmrg		char    *tmpname;
67205b261ecSmrg		name = 0;
67305b261ecSmrg		err = (*fpe_functions[fpe->type].list_next_font_or_alias)
67405b261ecSmrg		    ((pointer) c->client, fpe, &name, &namelen, &tmpname,
67505b261ecSmrg		     &resolvedlen, c->current.private);
67605b261ecSmrg		if (err == Suspended) {
67705b261ecSmrg		    if (!c->slept) {
67805b261ecSmrg			ClientSleep(client,
67905b261ecSmrg				    (ClientSleepProcPtr)doListFontsAndAliases,
68005b261ecSmrg				    (pointer) c);
68105b261ecSmrg			c->slept = TRUE;
68205b261ecSmrg		    }
68305b261ecSmrg		    return TRUE;
68405b261ecSmrg		}
68505b261ecSmrg		if (err == FontNameAlias) {
68605b261ecSmrg		    if (resolved) xfree(resolved);
68705b261ecSmrg		    resolved = (char *) xalloc(resolvedlen + 1);
68805b261ecSmrg		    if (resolved)
68905b261ecSmrg			memmove(resolved, tmpname, resolvedlen + 1);
69005b261ecSmrg		}
69105b261ecSmrg	    }
69205b261ecSmrg
69305b261ecSmrg	    if (err == Successful)
69405b261ecSmrg	    {
69505b261ecSmrg		if (c->haveSaved)
69605b261ecSmrg		{
69705b261ecSmrg		    if (c->savedName)
69805b261ecSmrg			(void)AddFontNamesName(c->names, c->savedName,
69905b261ecSmrg					       c->savedNameLen);
70005b261ecSmrg		}
70105b261ecSmrg		else
70205b261ecSmrg		    (void)AddFontNamesName(c->names, name, namelen);
70305b261ecSmrg	    }
70405b261ecSmrg
70505b261ecSmrg	    /*
70605b261ecSmrg	     * When we get an alias back, save our state and reset back to
70705b261ecSmrg	     * the start of the FPE looking for the specified name.  As
70805b261ecSmrg	     * soon as a real font is found for the alias, pop back to the
70905b261ecSmrg	     * old state
71005b261ecSmrg	     */
71105b261ecSmrg	    else if (err == FontNameAlias) {
71205b261ecSmrg		char	tmp_pattern[XLFDMAXFONTNAMELEN];
71305b261ecSmrg		/*
71405b261ecSmrg		 * when an alias recurses, we need to give
71505b261ecSmrg		 * the last FPE a chance to clean up; so we call
71605b261ecSmrg		 * it again, and assume that the error returned
71705b261ecSmrg		 * is BadFontName, indicating the alias resolution
71805b261ecSmrg		 * is complete.
71905b261ecSmrg		 */
72005b261ecSmrg		memmove(tmp_pattern, resolved, resolvedlen);
72105b261ecSmrg		if (c->haveSaved)
72205b261ecSmrg		{
72305b261ecSmrg		    char    *tmpname;
72405b261ecSmrg		    int     tmpnamelen;
72505b261ecSmrg
72605b261ecSmrg		    tmpname = 0;
72705b261ecSmrg		    (void) (*fpe_functions[fpe->type].list_next_font_or_alias)
72805b261ecSmrg			((pointer) c->client, fpe, &tmpname, &tmpnamelen,
72905b261ecSmrg			 &tmpname, &tmpnamelen, c->current.private);
73005b261ecSmrg		    if (--aliascount <= 0)
73105b261ecSmrg		    {
73205b261ecSmrg			err = BadFontName;
73305b261ecSmrg			goto ContBadFontName;
73405b261ecSmrg		    }
73505b261ecSmrg		}
73605b261ecSmrg		else
73705b261ecSmrg		{
73805b261ecSmrg		    c->saved = c->current;
73905b261ecSmrg		    c->haveSaved = TRUE;
74005b261ecSmrg		    if (c->savedName)
74105b261ecSmrg			xfree(c->savedName);
74205b261ecSmrg		    c->savedName = (char *)xalloc(namelen + 1);
74305b261ecSmrg		    if (c->savedName)
74405b261ecSmrg			memmove(c->savedName, name, namelen + 1);
74505b261ecSmrg		    c->savedNameLen = namelen;
74605b261ecSmrg		    aliascount = 20;
74705b261ecSmrg		}
74805b261ecSmrg		memmove(c->current.pattern, tmp_pattern, resolvedlen);
74905b261ecSmrg		c->current.patlen = resolvedlen;
75005b261ecSmrg		c->current.max_names = c->names->nnames + 1;
75105b261ecSmrg		c->current.current_fpe = -1;
75205b261ecSmrg		c->current.private = 0;
75305b261ecSmrg		err = BadFontName;
75405b261ecSmrg	    }
75505b261ecSmrg	}
75605b261ecSmrg	/*
75705b261ecSmrg	 * At the end of this FPE, step to the next.  If we've finished
75805b261ecSmrg	 * processing an alias, pop state back. If we've collected enough
75905b261ecSmrg	 * font names, quit.
76005b261ecSmrg	 */
76105b261ecSmrg	if (err == BadFontName) {
76205b261ecSmrg	  ContBadFontName: ;
76305b261ecSmrg	    c->current.list_started = FALSE;
76405b261ecSmrg	    c->current.current_fpe++;
76505b261ecSmrg	    err = Successful;
76605b261ecSmrg	    if (c->haveSaved)
76705b261ecSmrg	    {
76805b261ecSmrg		if (c->names->nnames == c->current.max_names ||
76905b261ecSmrg			c->current.current_fpe == c->num_fpes) {
77005b261ecSmrg		    c->haveSaved = FALSE;
77105b261ecSmrg		    c->current = c->saved;
77205b261ecSmrg		    /* Give the saved namelist a chance to clean itself up */
77305b261ecSmrg		    continue;
77405b261ecSmrg		}
77505b261ecSmrg	    }
77605b261ecSmrg	    if (c->names->nnames == c->current.max_names)
77705b261ecSmrg		break;
77805b261ecSmrg	}
77905b261ecSmrg    }
78005b261ecSmrg
78105b261ecSmrg    /*
78205b261ecSmrg     * send the reply
78305b261ecSmrg     */
78405b261ecSmrg    if (err != Successful) {
78505b261ecSmrg	SendErrorToClient(client, X_ListFonts, 0, 0, FontToXError(err));
78605b261ecSmrg	goto bail;
78705b261ecSmrg    }
78805b261ecSmrg
78905b261ecSmrgfinish:
79005b261ecSmrg
79105b261ecSmrg    names = c->names;
79205b261ecSmrg    nnames = names->nnames;
79305b261ecSmrg    client = c->client;
79405b261ecSmrg    stringLens = 0;
79505b261ecSmrg    for (i = 0; i < nnames; i++)
79605b261ecSmrg	stringLens += (names->length[i] <= 255) ? names->length[i] : 0;
79705b261ecSmrg
79805b261ecSmrg    reply.type = X_Reply;
79905b261ecSmrg    reply.length = (stringLens + nnames + 3) >> 2;
80005b261ecSmrg    reply.nFonts = nnames;
80105b261ecSmrg    reply.sequenceNumber = client->sequence;
80205b261ecSmrg
8034642e01fSmrg    bufptr = bufferStart = (char *) xalloc(reply.length << 2);
80405b261ecSmrg
80505b261ecSmrg    if (!bufptr && reply.length) {
80605b261ecSmrg	SendErrorToClient(client, X_ListFonts, 0, 0, BadAlloc);
80705b261ecSmrg	goto bail;
80805b261ecSmrg    }
80905b261ecSmrg    /*
81005b261ecSmrg     * since WriteToClient long word aligns things, copy to temp buffer and
81105b261ecSmrg     * write all at once
81205b261ecSmrg     */
81305b261ecSmrg    for (i = 0; i < nnames; i++) {
81405b261ecSmrg	if (names->length[i] > 255)
81505b261ecSmrg	    reply.nFonts--;
81605b261ecSmrg	else
81705b261ecSmrg	{
81805b261ecSmrg	    *bufptr++ = names->length[i];
81905b261ecSmrg	    memmove( bufptr, names->names[i], names->length[i]);
82005b261ecSmrg	    bufptr += names->length[i];
82105b261ecSmrg	}
82205b261ecSmrg    }
82305b261ecSmrg    nnames = reply.nFonts;
82405b261ecSmrg    reply.length = (stringLens + nnames + 3) >> 2;
82505b261ecSmrg    client->pSwapReplyFunc = ReplySwapVector[X_ListFonts];
82605b261ecSmrg    WriteSwappedDataToClient(client, sizeof(xListFontsReply), &reply);
82705b261ecSmrg    (void) WriteToClient(client, stringLens + nnames, bufferStart);
8284642e01fSmrg    xfree(bufferStart);
82905b261ecSmrg
83005b261ecSmrgbail:
83105b261ecSmrg    if (c->slept)
83205b261ecSmrg	ClientWakeup(client);
83305b261ecSmrg    for (i = 0; i < c->num_fpes; i++)
83405b261ecSmrg	FreeFPE(c->fpe_list[i]);
83505b261ecSmrg    xfree(c->fpe_list);
83605b261ecSmrg    if (c->savedName) xfree(c->savedName);
83705b261ecSmrg    FreeFontNames(names);
83805b261ecSmrg    xfree(c);
83905b261ecSmrg    if (resolved) xfree(resolved);
84005b261ecSmrg    return TRUE;
84105b261ecSmrg}
84205b261ecSmrg
84305b261ecSmrgint
84405b261ecSmrgListFonts(ClientPtr client, unsigned char *pattern, unsigned length,
84505b261ecSmrg          unsigned max_names)
84605b261ecSmrg{
84705b261ecSmrg    int         i;
84805b261ecSmrg    LFclosurePtr c;
84905b261ecSmrg
85005b261ecSmrg    /*
85105b261ecSmrg     * The right error to return here would be BadName, however the
85205b261ecSmrg     * specification does not allow for a Name error on this request.
85305b261ecSmrg     * Perhaps a better solution would be to return a nil list, i.e.
85405b261ecSmrg     * a list containing zero fontnames.
85505b261ecSmrg     */
85605b261ecSmrg    if (length > XLFDMAXFONTNAMELEN)
85705b261ecSmrg	return BadAlloc;
85805b261ecSmrg
8594642e01fSmrg    i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess);
8604642e01fSmrg    if (i != Success)
8614642e01fSmrg	return i;
8624642e01fSmrg
86305b261ecSmrg    if (!(c = (LFclosurePtr) xalloc(sizeof *c)))
86405b261ecSmrg	return BadAlloc;
86505b261ecSmrg    c->fpe_list = (FontPathElementPtr *)
86605b261ecSmrg	xalloc(sizeof(FontPathElementPtr) * num_fpes);
86705b261ecSmrg    if (!c->fpe_list) {
86805b261ecSmrg	xfree(c);
86905b261ecSmrg	return BadAlloc;
87005b261ecSmrg    }
87105b261ecSmrg    c->names = MakeFontNamesRecord(max_names < 100 ? max_names : 100);
87205b261ecSmrg    if (!c->names)
87305b261ecSmrg    {
87405b261ecSmrg	xfree(c->fpe_list);
87505b261ecSmrg	xfree(c);
87605b261ecSmrg	return BadAlloc;
87705b261ecSmrg    }
87805b261ecSmrg    memmove( c->current.pattern, pattern, length);
87905b261ecSmrg    for (i = 0; i < num_fpes; i++) {
88005b261ecSmrg	c->fpe_list[i] = font_path_elements[i];
88105b261ecSmrg	UseFPE(c->fpe_list[i]);
88205b261ecSmrg    }
88305b261ecSmrg    c->client = client;
88405b261ecSmrg    c->num_fpes = num_fpes;
88505b261ecSmrg    c->current.patlen = length;
88605b261ecSmrg    c->current.current_fpe = 0;
88705b261ecSmrg    c->current.max_names = max_names;
88805b261ecSmrg    c->current.list_started = FALSE;
88905b261ecSmrg    c->current.private = 0;
89005b261ecSmrg    c->haveSaved = FALSE;
89105b261ecSmrg    c->slept = FALSE;
89205b261ecSmrg    c->savedName = 0;
89305b261ecSmrg    doListFontsAndAliases(client, c);
89405b261ecSmrg    return Success;
89505b261ecSmrg}
89605b261ecSmrg
89705b261ecSmrgint
89805b261ecSmrgdoListFontsWithInfo(ClientPtr client, LFWIclosurePtr c)
89905b261ecSmrg{
90005b261ecSmrg    FontPathElementPtr fpe;
90105b261ecSmrg    int         err = Successful;
90205b261ecSmrg    char       *name;
90305b261ecSmrg    int         namelen;
90405b261ecSmrg    int         numFonts;
90505b261ecSmrg    FontInfoRec fontInfo,
90605b261ecSmrg               *pFontInfo;
90705b261ecSmrg    xListFontsWithInfoReply *reply;
90805b261ecSmrg    int         length;
90905b261ecSmrg    xFontProp  *pFP;
91005b261ecSmrg    int         i;
91105b261ecSmrg    int		aliascount = 0;
91205b261ecSmrg    xListFontsWithInfoReply finalReply;
91305b261ecSmrg
91405b261ecSmrg    if (client->clientGone)
91505b261ecSmrg    {
91605b261ecSmrg	if (c->current.current_fpe < c->num_fpes)
91705b261ecSmrg 	{
91805b261ecSmrg	    fpe = c->fpe_list[c->current.current_fpe];
91905b261ecSmrg	    (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
92005b261ecSmrg	}
92105b261ecSmrg	err = Successful;
92205b261ecSmrg	goto bail;
92305b261ecSmrg    }
92405b261ecSmrg    client->pSwapReplyFunc = ReplySwapVector[X_ListFontsWithInfo];
92505b261ecSmrg    if (!c->current.patlen)
92605b261ecSmrg	goto finish;
92705b261ecSmrg    while (c->current.current_fpe < c->num_fpes)
92805b261ecSmrg    {
92905b261ecSmrg	fpe = c->fpe_list[c->current.current_fpe];
93005b261ecSmrg	err = Successful;
93105b261ecSmrg	if (!c->current.list_started)
93205b261ecSmrg 	{
93305b261ecSmrg	    err = (*fpe_functions[fpe->type].start_list_fonts_with_info)
93405b261ecSmrg		(client, fpe, c->current.pattern, c->current.patlen,
93505b261ecSmrg		 c->current.max_names, &c->current.private);
93605b261ecSmrg	    if (err == Suspended)
93705b261ecSmrg 	    {
93805b261ecSmrg		if (!c->slept)
93905b261ecSmrg 		{
94005b261ecSmrg		    ClientSleep(client, (ClientSleepProcPtr)doListFontsWithInfo, c);
94105b261ecSmrg		    c->slept = TRUE;
94205b261ecSmrg		}
94305b261ecSmrg		return TRUE;
94405b261ecSmrg	    }
94505b261ecSmrg	    if (err == Successful)
94605b261ecSmrg		c->current.list_started = TRUE;
94705b261ecSmrg	}
94805b261ecSmrg	if (err == Successful)
94905b261ecSmrg 	{
95005b261ecSmrg	    name = 0;
95105b261ecSmrg	    pFontInfo = &fontInfo;
95205b261ecSmrg	    err = (*fpe_functions[fpe->type].list_next_font_with_info)
95305b261ecSmrg		(client, fpe, &name, &namelen, &pFontInfo,
95405b261ecSmrg		 &numFonts, c->current.private);
95505b261ecSmrg	    if (err == Suspended)
95605b261ecSmrg 	    {
95705b261ecSmrg		if (!c->slept)
95805b261ecSmrg 		{
95905b261ecSmrg		    ClientSleep(client,
96005b261ecSmrg		    	     (ClientSleepProcPtr)doListFontsWithInfo,
96105b261ecSmrg			     c);
96205b261ecSmrg		    c->slept = TRUE;
96305b261ecSmrg		}
96405b261ecSmrg		return TRUE;
96505b261ecSmrg	    }
96605b261ecSmrg	}
96705b261ecSmrg	/*
96805b261ecSmrg	 * When we get an alias back, save our state and reset back to the
96905b261ecSmrg	 * start of the FPE looking for the specified name.  As soon as a real
97005b261ecSmrg	 * font is found for the alias, pop back to the old state
97105b261ecSmrg	 */
97205b261ecSmrg	if (err == FontNameAlias)
97305b261ecSmrg 	{
97405b261ecSmrg	    /*
97505b261ecSmrg	     * when an alias recurses, we need to give
97605b261ecSmrg	     * the last FPE a chance to clean up; so we call
97705b261ecSmrg	     * it again, and assume that the error returned
97805b261ecSmrg	     * is BadFontName, indicating the alias resolution
97905b261ecSmrg	     * is complete.
98005b261ecSmrg	     */
98105b261ecSmrg	    if (c->haveSaved)
98205b261ecSmrg	    {
98305b261ecSmrg		char	*tmpname;
98405b261ecSmrg		int	tmpnamelen;
98505b261ecSmrg		FontInfoPtr tmpFontInfo;
98605b261ecSmrg
98705b261ecSmrg	    	tmpname = 0;
98805b261ecSmrg	    	tmpFontInfo = &fontInfo;
98905b261ecSmrg	    	(void) (*fpe_functions[fpe->type].list_next_font_with_info)
99005b261ecSmrg		    (client, fpe, &tmpname, &tmpnamelen, &tmpFontInfo,
99105b261ecSmrg		     &numFonts, c->current.private);
99205b261ecSmrg		if (--aliascount <= 0)
99305b261ecSmrg		{
99405b261ecSmrg		    err = BadFontName;
99505b261ecSmrg		    goto ContBadFontName;
99605b261ecSmrg		}
99705b261ecSmrg	    }
99805b261ecSmrg	    else
99905b261ecSmrg	    {
100005b261ecSmrg		c->saved = c->current;
100105b261ecSmrg		c->haveSaved = TRUE;
100205b261ecSmrg		c->savedNumFonts = numFonts;
100305b261ecSmrg		if (c->savedName)
100405b261ecSmrg		  xfree(c->savedName);
100505b261ecSmrg		c->savedName = (char *)xalloc(namelen + 1);
100605b261ecSmrg		if (c->savedName)
100705b261ecSmrg		  memmove(c->savedName, name, namelen + 1);
100805b261ecSmrg		aliascount = 20;
100905b261ecSmrg	    }
101005b261ecSmrg	    memmove(c->current.pattern, name, namelen);
101105b261ecSmrg	    c->current.patlen = namelen;
101205b261ecSmrg	    c->current.max_names = 1;
101305b261ecSmrg	    c->current.current_fpe = 0;
101405b261ecSmrg	    c->current.private = 0;
101505b261ecSmrg	    c->current.list_started = FALSE;
101605b261ecSmrg	}
101705b261ecSmrg	/*
101805b261ecSmrg	 * At the end of this FPE, step to the next.  If we've finished
101905b261ecSmrg	 * processing an alias, pop state back.  If we've sent enough font
102005b261ecSmrg	 * names, quit.  Always wait for BadFontName to let the FPE
102105b261ecSmrg	 * have a chance to clean up.
102205b261ecSmrg	 */
102305b261ecSmrg	else if (err == BadFontName)
102405b261ecSmrg 	{
102505b261ecSmrg	  ContBadFontName: ;
102605b261ecSmrg	    c->current.list_started = FALSE;
102705b261ecSmrg	    c->current.current_fpe++;
102805b261ecSmrg	    err = Successful;
102905b261ecSmrg	    if (c->haveSaved)
103005b261ecSmrg 	    {
103105b261ecSmrg		if (c->current.max_names == 0 ||
103205b261ecSmrg			c->current.current_fpe == c->num_fpes)
103305b261ecSmrg 		{
103405b261ecSmrg		    c->haveSaved = FALSE;
103505b261ecSmrg		    c->saved.max_names -= (1 - c->current.max_names);
103605b261ecSmrg		    c->current = c->saved;
103705b261ecSmrg		}
103805b261ecSmrg	    }
103905b261ecSmrg	    else if (c->current.max_names == 0)
104005b261ecSmrg		break;
104105b261ecSmrg	}
104205b261ecSmrg 	else if (err == Successful)
104305b261ecSmrg 	{
104405b261ecSmrg	    length = sizeof(*reply) + pFontInfo->nprops * sizeof(xFontProp);
104505b261ecSmrg	    reply = c->reply;
104605b261ecSmrg	    if (c->length < length)
104705b261ecSmrg 	    {
104805b261ecSmrg		reply = (xListFontsWithInfoReply *) xrealloc(c->reply, length);
104905b261ecSmrg		if (!reply)
105005b261ecSmrg 		{
105105b261ecSmrg		    err = AllocError;
105205b261ecSmrg		    break;
105305b261ecSmrg		}
105405b261ecSmrg		c->reply = reply;
105505b261ecSmrg		c->length = length;
105605b261ecSmrg	    }
105705b261ecSmrg	    if (c->haveSaved)
105805b261ecSmrg 	    {
105905b261ecSmrg		numFonts = c->savedNumFonts;
106005b261ecSmrg		name = c->savedName;
106105b261ecSmrg		namelen = strlen(name);
106205b261ecSmrg	    }
106305b261ecSmrg	    reply->type = X_Reply;
106405b261ecSmrg	    reply->length = (sizeof *reply - sizeof(xGenericReply) +
106505b261ecSmrg			     pFontInfo->nprops * sizeof(xFontProp) +
106605b261ecSmrg			     namelen + 3) >> 2;
106705b261ecSmrg	    reply->sequenceNumber = client->sequence;
106805b261ecSmrg	    reply->nameLength = namelen;
106905b261ecSmrg	    reply->minBounds = pFontInfo->ink_minbounds;
107005b261ecSmrg	    reply->maxBounds = pFontInfo->ink_maxbounds;
107105b261ecSmrg	    reply->minCharOrByte2 = pFontInfo->firstCol;
107205b261ecSmrg	    reply->maxCharOrByte2 = pFontInfo->lastCol;
107305b261ecSmrg	    reply->defaultChar = pFontInfo->defaultCh;
107405b261ecSmrg	    reply->nFontProps = pFontInfo->nprops;
107505b261ecSmrg	    reply->drawDirection = pFontInfo->drawDirection;
107605b261ecSmrg	    reply->minByte1 = pFontInfo->firstRow;
107705b261ecSmrg	    reply->maxByte1 = pFontInfo->lastRow;
107805b261ecSmrg	    reply->allCharsExist = pFontInfo->allExist;
107905b261ecSmrg	    reply->fontAscent = pFontInfo->fontAscent;
108005b261ecSmrg	    reply->fontDescent = pFontInfo->fontDescent;
108105b261ecSmrg	    reply->nReplies = numFonts;
108205b261ecSmrg	    pFP = (xFontProp *) (reply + 1);
108305b261ecSmrg	    for (i = 0; i < pFontInfo->nprops; i++)
108405b261ecSmrg 	    {
108505b261ecSmrg		pFP->name = pFontInfo->props[i].name;
108605b261ecSmrg		pFP->value = pFontInfo->props[i].value;
108705b261ecSmrg		pFP++;
108805b261ecSmrg	    }
108905b261ecSmrg	    WriteSwappedDataToClient(client, length, reply);
109005b261ecSmrg	    (void) WriteToClient(client, namelen, name);
109105b261ecSmrg	    if (pFontInfo == &fontInfo)
109205b261ecSmrg 	    {
109305b261ecSmrg		xfree(fontInfo.props);
109405b261ecSmrg		xfree(fontInfo.isStringProp);
109505b261ecSmrg	    }
109605b261ecSmrg	    --c->current.max_names;
109705b261ecSmrg	}
109805b261ecSmrg    }
109905b261ecSmrgfinish:
110005b261ecSmrg    length = sizeof(xListFontsWithInfoReply);
110105b261ecSmrg    bzero((char *) &finalReply, sizeof(xListFontsWithInfoReply));
110205b261ecSmrg    finalReply.type = X_Reply;
110305b261ecSmrg    finalReply.sequenceNumber = client->sequence;
110405b261ecSmrg    finalReply.length = (sizeof(xListFontsWithInfoReply)
110505b261ecSmrg		     - sizeof(xGenericReply)) >> 2;
110605b261ecSmrg    WriteSwappedDataToClient(client, length, &finalReply);
110705b261ecSmrgbail:
110805b261ecSmrg    if (c->slept)
110905b261ecSmrg	ClientWakeup(client);
111005b261ecSmrg    for (i = 0; i < c->num_fpes; i++)
111105b261ecSmrg	FreeFPE(c->fpe_list[i]);
111205b261ecSmrg    xfree(c->reply);
111305b261ecSmrg    xfree(c->fpe_list);
111405b261ecSmrg    if (c->savedName) xfree(c->savedName);
111505b261ecSmrg    xfree(c);
111605b261ecSmrg    return TRUE;
111705b261ecSmrg}
111805b261ecSmrg
111905b261ecSmrgint
112005b261ecSmrgStartListFontsWithInfo(ClientPtr client, int length, unsigned char *pattern,
112105b261ecSmrg                       int max_names)
112205b261ecSmrg{
112305b261ecSmrg    int		    i;
112405b261ecSmrg    LFWIclosurePtr  c;
112505b261ecSmrg
112605b261ecSmrg    /*
112705b261ecSmrg     * The right error to return here would be BadName, however the
112805b261ecSmrg     * specification does not allow for a Name error on this request.
112905b261ecSmrg     * Perhaps a better solution would be to return a nil list, i.e.
113005b261ecSmrg     * a list containing zero fontnames.
113105b261ecSmrg     */
113205b261ecSmrg    if (length > XLFDMAXFONTNAMELEN)
113305b261ecSmrg	return BadAlloc;
113405b261ecSmrg
11354642e01fSmrg    i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess);
11364642e01fSmrg    if (i != Success)
11374642e01fSmrg	return i;
11384642e01fSmrg
113905b261ecSmrg    if (!(c = (LFWIclosurePtr) xalloc(sizeof *c)))
114005b261ecSmrg	goto badAlloc;
114105b261ecSmrg    c->fpe_list = (FontPathElementPtr *)
114205b261ecSmrg	xalloc(sizeof(FontPathElementPtr) * num_fpes);
114305b261ecSmrg    if (!c->fpe_list)
114405b261ecSmrg    {
114505b261ecSmrg	xfree(c);
114605b261ecSmrg	goto badAlloc;
114705b261ecSmrg    }
114805b261ecSmrg    memmove(c->current.pattern, pattern, length);
114905b261ecSmrg    for (i = 0; i < num_fpes; i++)
115005b261ecSmrg    {
115105b261ecSmrg	c->fpe_list[i] = font_path_elements[i];
115205b261ecSmrg	UseFPE(c->fpe_list[i]);
115305b261ecSmrg    }
115405b261ecSmrg    c->client = client;
115505b261ecSmrg    c->num_fpes = num_fpes;
115605b261ecSmrg    c->reply = 0;
115705b261ecSmrg    c->length = 0;
115805b261ecSmrg    c->current.patlen = length;
115905b261ecSmrg    c->current.current_fpe = 0;
116005b261ecSmrg    c->current.max_names = max_names;
116105b261ecSmrg    c->current.list_started = FALSE;
116205b261ecSmrg    c->current.private = 0;
116305b261ecSmrg    c->savedNumFonts = 0;
116405b261ecSmrg    c->haveSaved = FALSE;
116505b261ecSmrg    c->slept = FALSE;
116605b261ecSmrg    c->savedName = 0;
116705b261ecSmrg    doListFontsWithInfo(client, c);
116805b261ecSmrg    return Success;
116905b261ecSmrgbadAlloc:
117005b261ecSmrg    return BadAlloc;
117105b261ecSmrg}
117205b261ecSmrg
117305b261ecSmrg#define TextEltHeader 2
117405b261ecSmrg#define FontShiftSize 5
117505b261ecSmrgstatic XID clearGC[] = { CT_NONE };
117605b261ecSmrg#define clearGCmask (GCClipMask)
117705b261ecSmrg
117805b261ecSmrgint
117905b261ecSmrgdoPolyText(ClientPtr client, PTclosurePtr c)
118005b261ecSmrg{
118105b261ecSmrg    FontPtr pFont = c->pGC->font, oldpFont;
118205b261ecSmrg    Font	fid, oldfid;
118305b261ecSmrg    int err = Success, lgerr;	/* err is in X error, not font error, space */
118405b261ecSmrg    enum { NEVER_SLEPT, START_SLEEP, SLEEPING } client_state = NEVER_SLEPT;
118505b261ecSmrg    FontPathElementPtr fpe;
118605b261ecSmrg    GC *origGC = NULL;
118705b261ecSmrg
118805b261ecSmrg    if (client->clientGone)
118905b261ecSmrg    {
119005b261ecSmrg	fpe = c->pGC->font->fpe;
119105b261ecSmrg	(*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
119205b261ecSmrg
119305b261ecSmrg	if (c->slept)
119405b261ecSmrg	{
119505b261ecSmrg	    /* Client has died, but we cannot bail out right now.  We
119605b261ecSmrg	       need to clean up after the work we did when going to
119705b261ecSmrg	       sleep.  Setting the drawable pointer to 0 makes this
119805b261ecSmrg	       happen without any attempts to render or perform other
119905b261ecSmrg	       unnecessary activities.  */
120005b261ecSmrg	    c->pDraw = (DrawablePtr)0;
120105b261ecSmrg	}
120205b261ecSmrg	else
120305b261ecSmrg	{
120405b261ecSmrg	    err = Success;
120505b261ecSmrg	    goto bail;
120605b261ecSmrg	}
120705b261ecSmrg    }
120805b261ecSmrg
120905b261ecSmrg    /* Make sure our drawable hasn't disappeared while we slept. */
121005b261ecSmrg    if (c->slept &&
121105b261ecSmrg	c->pDraw &&
121205b261ecSmrg	c->pDraw != (DrawablePtr)SecurityLookupIDByClass(client, c->did,
121305b261ecSmrg					RC_DRAWABLE, DixWriteAccess))
121405b261ecSmrg    {
121505b261ecSmrg	/* Our drawable has disappeared.  Treat like client died... ask
121605b261ecSmrg	   the FPE code to clean up after client and avoid further
121705b261ecSmrg	   rendering while we clean up after ourself.  */
121805b261ecSmrg	fpe = c->pGC->font->fpe;
121905b261ecSmrg	(*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
122005b261ecSmrg	c->pDraw = (DrawablePtr)0;
122105b261ecSmrg    }
122205b261ecSmrg
122305b261ecSmrg    client_state = c->slept ? SLEEPING : NEVER_SLEPT;
122405b261ecSmrg
122505b261ecSmrg    while (c->endReq - c->pElt > TextEltHeader)
122605b261ecSmrg    {
122705b261ecSmrg	if (*c->pElt == FontChange)
122805b261ecSmrg        {
122905b261ecSmrg	    if (c->endReq - c->pElt < FontShiftSize)
123005b261ecSmrg	    {
123105b261ecSmrg		 err = BadLength;
123205b261ecSmrg		 goto bail;
123305b261ecSmrg	    }
123405b261ecSmrg
123505b261ecSmrg	    oldpFont = pFont;
123605b261ecSmrg	    oldfid = fid;
123705b261ecSmrg
123805b261ecSmrg	    fid =  ((Font)*(c->pElt+4))		/* big-endian */
123905b261ecSmrg		 | ((Font)*(c->pElt+3)) << 8
124005b261ecSmrg		 | ((Font)*(c->pElt+2)) << 16
124105b261ecSmrg		 | ((Font)*(c->pElt+1)) << 24;
124205b261ecSmrg	    pFont = (FontPtr)SecurityLookupIDByType(client, fid, RT_FONT,
124305b261ecSmrg						    DixReadAccess);
124405b261ecSmrg	    if (!pFont)
124505b261ecSmrg	    {
124605b261ecSmrg		client->errorValue = fid;
124705b261ecSmrg		err = BadFont;
124805b261ecSmrg		/* restore pFont and fid for step 4 (described below) */
124905b261ecSmrg		pFont = oldpFont;
125005b261ecSmrg		fid = oldfid;
125105b261ecSmrg
125205b261ecSmrg		/* If we're in START_SLEEP mode, the following step
125305b261ecSmrg		   shortens the request...  in the unlikely event that
125405b261ecSmrg		   the fid somehow becomes valid before we come through
125505b261ecSmrg		   again to actually execute the polytext, which would
125605b261ecSmrg		   then mess up our refcounting scheme badly.  */
125705b261ecSmrg		c->err = err;
125805b261ecSmrg		c->endReq = c->pElt;
125905b261ecSmrg
126005b261ecSmrg		goto bail;
126105b261ecSmrg	    }
126205b261ecSmrg
126305b261ecSmrg	    /* Step 3 (described below) on our new font */
126405b261ecSmrg	    if (client_state == START_SLEEP)
126505b261ecSmrg		pFont->refcnt++;
126605b261ecSmrg	    else
126705b261ecSmrg	    {
126805b261ecSmrg		if (pFont != c->pGC->font && c->pDraw)
126905b261ecSmrg		{
127005b261ecSmrg		    ChangeGC( c->pGC, GCFont, &fid);
127105b261ecSmrg		    ValidateGC(c->pDraw, c->pGC);
127205b261ecSmrg		    if (c->reqType == X_PolyText8)
127305b261ecSmrg			c->polyText = (PolyTextPtr) c->pGC->ops->PolyText8;
127405b261ecSmrg		    else
127505b261ecSmrg			c->polyText = (PolyTextPtr) c->pGC->ops->PolyText16;
127605b261ecSmrg		}
127705b261ecSmrg
127805b261ecSmrg		/* Undo the refcnt++ we performed when going to sleep */
127905b261ecSmrg		if (client_state == SLEEPING)
128005b261ecSmrg		    (void)CloseFont(c->pGC->font, (Font)0);
128105b261ecSmrg	    }
128205b261ecSmrg	    c->pElt += FontShiftSize;
128305b261ecSmrg	}
128405b261ecSmrg	else	/* print a string */
128505b261ecSmrg	{
128605b261ecSmrg	    unsigned char *pNextElt;
128705b261ecSmrg	    pNextElt = c->pElt + TextEltHeader + (*c->pElt)*c->itemSize;
128805b261ecSmrg	    if ( pNextElt > c->endReq)
128905b261ecSmrg	    {
129005b261ecSmrg		err = BadLength;
129105b261ecSmrg		goto bail;
129205b261ecSmrg	    }
129305b261ecSmrg	    if (client_state == START_SLEEP)
129405b261ecSmrg	    {
129505b261ecSmrg		c->pElt = pNextElt;
129605b261ecSmrg		continue;
129705b261ecSmrg	    }
129805b261ecSmrg	    if (c->pDraw)
129905b261ecSmrg	    {
130005b261ecSmrg		lgerr = LoadGlyphs(client, c->pGC->font, *c->pElt, c->itemSize,
130105b261ecSmrg				   c->pElt + TextEltHeader);
130205b261ecSmrg	    }
130305b261ecSmrg	    else lgerr = Successful;
130405b261ecSmrg
130505b261ecSmrg	    if (lgerr == Suspended)
130605b261ecSmrg	    {
130705b261ecSmrg		if (!c->slept) {
130805b261ecSmrg		    int len;
130905b261ecSmrg		    GC *pGC;
131005b261ecSmrg		    PTclosurePtr new_closure;
131105b261ecSmrg
131205b261ecSmrg    /*  We're putting the client to sleep.  We need to do a few things
131305b261ecSmrg	to ensure successful and atomic-appearing execution of the
131405b261ecSmrg	remainder of the request.  First, copy the remainder of the
131505b261ecSmrg	request into a safe malloc'd area.  Second, create a scratch GC
131605b261ecSmrg	to use for the remainder of the request.  Third, mark all fonts
131705b261ecSmrg	referenced in the remainder of the request to prevent their
131805b261ecSmrg	deallocation.  Fourth, make the original GC look like the
131905b261ecSmrg	request has completed...  set its font to the final font value
132005b261ecSmrg	from this request.  These GC manipulations are for the unlikely
132105b261ecSmrg	(but possible) event that some other client is using the GC.
132205b261ecSmrg	Steps 3 and 4 are performed by running this procedure through
132305b261ecSmrg	the remainder of the request in a special no-render mode
132405b261ecSmrg	indicated by client_state = START_SLEEP.  */
132505b261ecSmrg
132605b261ecSmrg		    /* Step 1 */
132705b261ecSmrg		    /* Allocate a malloc'd closure structure to replace
132805b261ecSmrg		       the local one we were passed */
132905b261ecSmrg		    new_closure = (PTclosurePtr) xalloc(sizeof(PTclosureRec));
133005b261ecSmrg		    if (!new_closure)
133105b261ecSmrg		    {
133205b261ecSmrg			err = BadAlloc;
133305b261ecSmrg			goto bail;
133405b261ecSmrg		    }
133505b261ecSmrg		    *new_closure = *c;
133605b261ecSmrg		    c = new_closure;
133705b261ecSmrg
133805b261ecSmrg		    len = c->endReq - c->pElt;
133905b261ecSmrg		    c->data = (unsigned char *)xalloc(len);
134005b261ecSmrg		    if (!c->data)
134105b261ecSmrg		    {
134205b261ecSmrg			xfree(c);
134305b261ecSmrg			err = BadAlloc;
134405b261ecSmrg			goto bail;
134505b261ecSmrg		    }
134605b261ecSmrg		    memmove(c->data, c->pElt, len);
134705b261ecSmrg		    c->pElt = c->data;
134805b261ecSmrg		    c->endReq = c->pElt + len;
134905b261ecSmrg
135005b261ecSmrg		    /* Step 2 */
135105b261ecSmrg
135205b261ecSmrg		    pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen);
135305b261ecSmrg		    if (!pGC)
135405b261ecSmrg		    {
135505b261ecSmrg			xfree(c->data);
135605b261ecSmrg			xfree(c);
135705b261ecSmrg			err = BadAlloc;
135805b261ecSmrg			goto bail;
135905b261ecSmrg		    }
136005b261ecSmrg		    if ((err = CopyGC(c->pGC, pGC, GCFunction |
136105b261ecSmrg				      GCPlaneMask | GCForeground |
136205b261ecSmrg				      GCBackground | GCFillStyle |
136305b261ecSmrg				      GCTile | GCStipple |
136405b261ecSmrg				      GCTileStipXOrigin |
136505b261ecSmrg				      GCTileStipYOrigin | GCFont |
136605b261ecSmrg				      GCSubwindowMode | GCClipXOrigin |
136705b261ecSmrg				      GCClipYOrigin | GCClipMask)) !=
136805b261ecSmrg				      Success)
136905b261ecSmrg		    {
137005b261ecSmrg			FreeScratchGC(pGC);
137105b261ecSmrg			xfree(c->data);
137205b261ecSmrg			xfree(c);
137305b261ecSmrg			err = BadAlloc;
137405b261ecSmrg			goto bail;
137505b261ecSmrg		    }
137605b261ecSmrg		    origGC = c->pGC;
137705b261ecSmrg		    c->pGC = pGC;
137805b261ecSmrg		    ValidateGC(c->pDraw, c->pGC);
137905b261ecSmrg
138005b261ecSmrg		    c->slept = TRUE;
138105b261ecSmrg		    ClientSleep(client,
138205b261ecSmrg		    	     (ClientSleepProcPtr)doPolyText,
138305b261ecSmrg			     (pointer) c);
138405b261ecSmrg
138505b261ecSmrg		    /* Set up to perform steps 3 and 4 */
138605b261ecSmrg		    client_state = START_SLEEP;
138705b261ecSmrg		    continue;	/* on to steps 3 and 4 */
138805b261ecSmrg		}
138905b261ecSmrg		return TRUE;
139005b261ecSmrg	    }
139105b261ecSmrg	    else if (lgerr != Successful)
139205b261ecSmrg	    {
139305b261ecSmrg		err = FontToXError(lgerr);
139405b261ecSmrg		goto bail;
139505b261ecSmrg	    }
139605b261ecSmrg	    if (c->pDraw)
139705b261ecSmrg	    {
139805b261ecSmrg		c->xorg += *((INT8 *)(c->pElt + 1));	/* must be signed */
139905b261ecSmrg		c->xorg = (* c->polyText)(c->pDraw, c->pGC, c->xorg, c->yorg,
140005b261ecSmrg		    *c->pElt, c->pElt + TextEltHeader);
140105b261ecSmrg	    }
140205b261ecSmrg	    c->pElt = pNextElt;
140305b261ecSmrg	}
140405b261ecSmrg    }
140505b261ecSmrg
140605b261ecSmrgbail:
140705b261ecSmrg
140805b261ecSmrg    if (client_state == START_SLEEP)
140905b261ecSmrg    {
141005b261ecSmrg	/* Step 4 */
141105b261ecSmrg	if (pFont != origGC->font)
141205b261ecSmrg	{
141305b261ecSmrg	    ChangeGC(origGC, GCFont, &fid);
141405b261ecSmrg	    ValidateGC(c->pDraw, origGC);
141505b261ecSmrg	}
141605b261ecSmrg
141705b261ecSmrg	/* restore pElt pointer for execution of remainder of the request */
141805b261ecSmrg	c->pElt = c->data;
141905b261ecSmrg	return TRUE;
142005b261ecSmrg    }
142105b261ecSmrg
142205b261ecSmrg    if (c->err != Success) err = c->err;
142305b261ecSmrg    if (err != Success && c->client != serverClient) {
142405b261ecSmrg#ifdef PANORAMIX
142505b261ecSmrg        if (noPanoramiXExtension || !c->pGC->pScreen->myNum)
142605b261ecSmrg#endif
142705b261ecSmrg	    SendErrorToClient(c->client, c->reqType, 0, 0, err);
142805b261ecSmrg    }
142905b261ecSmrg    if (c->slept)
143005b261ecSmrg    {
143105b261ecSmrg	ClientWakeup(c->client);
143205b261ecSmrg	ChangeGC(c->pGC, clearGCmask, clearGC);
143305b261ecSmrg
143405b261ecSmrg	/* Unreference the font from the scratch GC */
143505b261ecSmrg	CloseFont(c->pGC->font, (Font)0);
143605b261ecSmrg	c->pGC->font = NullFont;
143705b261ecSmrg
143805b261ecSmrg	FreeScratchGC(c->pGC);
143905b261ecSmrg	xfree(c->data);
144005b261ecSmrg	xfree(c);
144105b261ecSmrg    }
144205b261ecSmrg    return TRUE;
144305b261ecSmrg}
144405b261ecSmrg
144505b261ecSmrgint
144605b261ecSmrgPolyText(ClientPtr client, DrawablePtr pDraw, GC *pGC, unsigned char *pElt,
144705b261ecSmrg         unsigned char *endReq, int xorg, int yorg, int reqType, XID did)
144805b261ecSmrg{
144905b261ecSmrg    PTclosureRec local_closure;
145005b261ecSmrg
145105b261ecSmrg    local_closure.pElt = pElt;
145205b261ecSmrg    local_closure.endReq = endReq;
145305b261ecSmrg    local_closure.client = client;
145405b261ecSmrg    local_closure.pDraw = pDraw;
145505b261ecSmrg    local_closure.xorg = xorg;
145605b261ecSmrg    local_closure.yorg = yorg;
145705b261ecSmrg    if ((local_closure.reqType = reqType) == X_PolyText8)
145805b261ecSmrg    {
145905b261ecSmrg	local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText8;
146005b261ecSmrg	local_closure.itemSize = 1;
146105b261ecSmrg    }
146205b261ecSmrg    else
146305b261ecSmrg    {
146405b261ecSmrg	local_closure.polyText =  (PolyTextPtr) pGC->ops->PolyText16;
146505b261ecSmrg	local_closure.itemSize = 2;
146605b261ecSmrg    }
146705b261ecSmrg    local_closure.pGC = pGC;
146805b261ecSmrg    local_closure.did = did;
146905b261ecSmrg    local_closure.err = Success;
147005b261ecSmrg    local_closure.slept = FALSE;
147105b261ecSmrg
147205b261ecSmrg    (void) doPolyText(client, &local_closure);
147305b261ecSmrg    return Success;
147405b261ecSmrg}
147505b261ecSmrg
147605b261ecSmrg
147705b261ecSmrg#undef TextEltHeader
147805b261ecSmrg#undef FontShiftSize
147905b261ecSmrg
148005b261ecSmrgint
148105b261ecSmrgdoImageText(ClientPtr client, ITclosurePtr c)
148205b261ecSmrg{
148305b261ecSmrg    int err = Success, lgerr;	/* err is in X error, not font error, space */
148405b261ecSmrg    FontPathElementPtr fpe;
148505b261ecSmrg
148605b261ecSmrg    if (client->clientGone)
148705b261ecSmrg    {
148805b261ecSmrg	fpe = c->pGC->font->fpe;
148905b261ecSmrg	(*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
149005b261ecSmrg	err = Success;
149105b261ecSmrg	goto bail;
149205b261ecSmrg    }
149305b261ecSmrg
149405b261ecSmrg    /* Make sure our drawable hasn't disappeared while we slept. */
149505b261ecSmrg    if (c->slept &&
149605b261ecSmrg	c->pDraw &&
149705b261ecSmrg	c->pDraw != (DrawablePtr)SecurityLookupIDByClass(client, c->did,
149805b261ecSmrg					RC_DRAWABLE, DixWriteAccess))
149905b261ecSmrg    {
150005b261ecSmrg	/* Our drawable has disappeared.  Treat like client died... ask
150105b261ecSmrg	   the FPE code to clean up after client. */
150205b261ecSmrg	fpe = c->pGC->font->fpe;
150305b261ecSmrg	(*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
150405b261ecSmrg	err = Success;
150505b261ecSmrg	goto bail;
150605b261ecSmrg    }
150705b261ecSmrg
150805b261ecSmrg    lgerr = LoadGlyphs(client, c->pGC->font, c->nChars, c->itemSize, c->data);
150905b261ecSmrg    if (lgerr == Suspended)
151005b261ecSmrg    {
151105b261ecSmrg        if (!c->slept) {
151205b261ecSmrg	    GC *pGC;
151305b261ecSmrg	    unsigned char *data;
151405b261ecSmrg	    ITclosurePtr new_closure;
151505b261ecSmrg
151605b261ecSmrg	    /* We're putting the client to sleep.  We need to
151705b261ecSmrg	       save some state.  Similar problem to that handled
151805b261ecSmrg	       in doPolyText, but much simpler because the
151905b261ecSmrg	       request structure is much simpler. */
152005b261ecSmrg
152105b261ecSmrg	    new_closure = (ITclosurePtr) xalloc(sizeof(ITclosureRec));
152205b261ecSmrg	    if (!new_closure)
152305b261ecSmrg	    {
152405b261ecSmrg		err = BadAlloc;
152505b261ecSmrg		goto bail;
152605b261ecSmrg	    }
152705b261ecSmrg	    *new_closure = *c;
152805b261ecSmrg	    c = new_closure;
152905b261ecSmrg
153005b261ecSmrg	    data = (unsigned char *)xalloc(c->nChars * c->itemSize);
153105b261ecSmrg	    if (!data)
153205b261ecSmrg	    {
153305b261ecSmrg		xfree(c);
153405b261ecSmrg		err = BadAlloc;
153505b261ecSmrg		goto bail;
153605b261ecSmrg	    }
153705b261ecSmrg	    memmove(data, c->data, c->nChars * c->itemSize);
153805b261ecSmrg	    c->data = data;
153905b261ecSmrg
154005b261ecSmrg	    pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen);
154105b261ecSmrg	    if (!pGC)
154205b261ecSmrg	    {
154305b261ecSmrg		xfree(c->data);
154405b261ecSmrg		xfree(c);
154505b261ecSmrg		err = BadAlloc;
154605b261ecSmrg		goto bail;
154705b261ecSmrg	    }
154805b261ecSmrg	    if ((err = CopyGC(c->pGC, pGC, GCFunction | GCPlaneMask |
154905b261ecSmrg			      GCForeground | GCBackground | GCFillStyle |
155005b261ecSmrg			      GCTile | GCStipple | GCTileStipXOrigin |
155105b261ecSmrg			      GCTileStipYOrigin | GCFont |
155205b261ecSmrg			      GCSubwindowMode | GCClipXOrigin |
155305b261ecSmrg			      GCClipYOrigin | GCClipMask)) != Success)
155405b261ecSmrg	    {
155505b261ecSmrg		FreeScratchGC(pGC);
155605b261ecSmrg		xfree(c->data);
155705b261ecSmrg		xfree(c);
155805b261ecSmrg		err = BadAlloc;
155905b261ecSmrg		goto bail;
156005b261ecSmrg	    }
156105b261ecSmrg	    c->pGC = pGC;
156205b261ecSmrg	    ValidateGC(c->pDraw, c->pGC);
156305b261ecSmrg
156405b261ecSmrg	    c->slept = TRUE;
156505b261ecSmrg            ClientSleep(client, (ClientSleepProcPtr)doImageText, (pointer) c);
156605b261ecSmrg        }
156705b261ecSmrg        return TRUE;
156805b261ecSmrg    }
156905b261ecSmrg    else if (lgerr != Successful)
157005b261ecSmrg    {
157105b261ecSmrg        err = FontToXError(lgerr);
157205b261ecSmrg        goto bail;
157305b261ecSmrg    }
157405b261ecSmrg    if (c->pDraw)
157505b261ecSmrg    {
157605b261ecSmrg	(* c->imageText)(c->pDraw, c->pGC, c->xorg, c->yorg,
157705b261ecSmrg	    c->nChars, c->data);
157805b261ecSmrg    }
157905b261ecSmrg
158005b261ecSmrgbail:
158105b261ecSmrg
158205b261ecSmrg    if (err != Success && c->client != serverClient) {
158305b261ecSmrg	SendErrorToClient(c->client, c->reqType, 0, 0, err);
158405b261ecSmrg    }
158505b261ecSmrg    if (c->slept)
158605b261ecSmrg    {
158705b261ecSmrg	ClientWakeup(c->client);
158805b261ecSmrg	ChangeGC(c->pGC, clearGCmask, clearGC);
158905b261ecSmrg
159005b261ecSmrg	/* Unreference the font from the scratch GC */
159105b261ecSmrg	CloseFont(c->pGC->font, (Font)0);
159205b261ecSmrg	c->pGC->font = NullFont;
159305b261ecSmrg
159405b261ecSmrg	FreeScratchGC(c->pGC);
159505b261ecSmrg	xfree(c->data);
159605b261ecSmrg	xfree(c);
159705b261ecSmrg    }
159805b261ecSmrg    return TRUE;
159905b261ecSmrg}
160005b261ecSmrg
160105b261ecSmrgint
160205b261ecSmrgImageText(ClientPtr client, DrawablePtr pDraw, GC *pGC, int nChars,
160305b261ecSmrg          unsigned char *data, int xorg, int yorg, int reqType, XID did)
160405b261ecSmrg{
160505b261ecSmrg    ITclosureRec local_closure;
160605b261ecSmrg
160705b261ecSmrg    local_closure.client = client;
160805b261ecSmrg    local_closure.pDraw = pDraw;
160905b261ecSmrg    local_closure.pGC = pGC;
161005b261ecSmrg    local_closure.nChars = nChars;
161105b261ecSmrg    local_closure.data = data;
161205b261ecSmrg    local_closure.xorg = xorg;
161305b261ecSmrg    local_closure.yorg = yorg;
161405b261ecSmrg    if ((local_closure.reqType = reqType) == X_ImageText8)
161505b261ecSmrg    {
161605b261ecSmrg	local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText8;
161705b261ecSmrg	local_closure.itemSize = 1;
161805b261ecSmrg    }
161905b261ecSmrg    else
162005b261ecSmrg    {
162105b261ecSmrg	local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText16;
162205b261ecSmrg	local_closure.itemSize = 2;
162305b261ecSmrg    }
162405b261ecSmrg    local_closure.did = did;
162505b261ecSmrg    local_closure.slept = FALSE;
162605b261ecSmrg
162705b261ecSmrg    (void) doImageText(client, &local_closure);
162805b261ecSmrg    return Success;
162905b261ecSmrg}
163005b261ecSmrg
163105b261ecSmrg
163205b261ecSmrg/* does the necessary magic to figure out the fpe type */
163305b261ecSmrgstatic int
163405b261ecSmrgDetermineFPEType(char *pathname)
163505b261ecSmrg{
163605b261ecSmrg    int         i;
163705b261ecSmrg
163805b261ecSmrg    for (i = 0; i < num_fpe_types; i++) {
163905b261ecSmrg	if ((*fpe_functions[i].name_check) (pathname))
164005b261ecSmrg	    return i;
164105b261ecSmrg    }
164205b261ecSmrg    return -1;
164305b261ecSmrg}
164405b261ecSmrg
164505b261ecSmrg
164605b261ecSmrgstatic void
164705b261ecSmrgFreeFontPath(FontPathElementPtr *list, int n, Bool force)
164805b261ecSmrg{
164905b261ecSmrg    int         i;
165005b261ecSmrg
165105b261ecSmrg    for (i = 0; i < n; i++) {
165205b261ecSmrg	if (force) {
165305b261ecSmrg	    /* Sanity check that all refcounts will be 0 by the time
165405b261ecSmrg	       we get to the end of the list. */
165505b261ecSmrg	    int found = 1;	/* the first reference is us */
165605b261ecSmrg	    int j;
165705b261ecSmrg	    for (j = i+1; j < n; j++) {
165805b261ecSmrg		if (list[j] == list[i])
165905b261ecSmrg		    found++;
166005b261ecSmrg	    }
166105b261ecSmrg	    if (list[i]->refcount != found) {
166205b261ecSmrg		list[i]->refcount = found; /* ensure it will get freed */
166305b261ecSmrg	    }
166405b261ecSmrg	}
166505b261ecSmrg	FreeFPE(list[i]);
166605b261ecSmrg    }
166705b261ecSmrg    xfree((char *) list);
166805b261ecSmrg}
166905b261ecSmrg
167005b261ecSmrgstatic FontPathElementPtr
167105b261ecSmrgfind_existing_fpe(FontPathElementPtr *list, int num, unsigned char *name, int len)
167205b261ecSmrg{
167305b261ecSmrg    FontPathElementPtr fpe;
167405b261ecSmrg    int         i;
167505b261ecSmrg
167605b261ecSmrg    for (i = 0; i < num; i++) {
167705b261ecSmrg	fpe = list[i];
167805b261ecSmrg	if (fpe->name_length == len && memcmp(name, fpe->name, len) == 0)
167905b261ecSmrg	    return fpe;
168005b261ecSmrg    }
168105b261ecSmrg    return (FontPathElementPtr) 0;
168205b261ecSmrg}
168305b261ecSmrg
168405b261ecSmrg
168505b261ecSmrgstatic int
168605b261ecSmrgSetFontPathElements(int npaths, unsigned char *paths, int *bad, Bool persist)
168705b261ecSmrg{
168805b261ecSmrg    int         i, err = 0;
168905b261ecSmrg    int         valid_paths = 0;
169005b261ecSmrg    unsigned int len;
169105b261ecSmrg    unsigned char *cp = paths;
169205b261ecSmrg    FontPathElementPtr fpe = NULL, *fplist;
169305b261ecSmrg
169405b261ecSmrg    fplist = (FontPathElementPtr *)
169505b261ecSmrg	xalloc(sizeof(FontPathElementPtr) * npaths);
169605b261ecSmrg    if (!fplist) {
169705b261ecSmrg	*bad = 0;
169805b261ecSmrg	return BadAlloc;
169905b261ecSmrg    }
170005b261ecSmrg    for (i = 0; i < num_fpe_types; i++) {
170105b261ecSmrg	if (fpe_functions[i].set_path_hook)
170205b261ecSmrg	    (*fpe_functions[i].set_path_hook) ();
170305b261ecSmrg    }
170405b261ecSmrg    for (i = 0; i < npaths; i++)
170505b261ecSmrg    {
170605b261ecSmrg	len = (unsigned int) (*cp++);
170705b261ecSmrg
170805b261ecSmrg	if (len == 0)
170905b261ecSmrg	{
171005b261ecSmrg	    if (persist)
17114642e01fSmrg		ErrorF("[dix] Removing empty element from the valid list of fontpaths\n");
171205b261ecSmrg	    err = BadValue;
171305b261ecSmrg	}
171405b261ecSmrg	else
171505b261ecSmrg	{
171605b261ecSmrg	    /* if it's already in our active list, just reset it */
171705b261ecSmrg	    /*
171805b261ecSmrg	     * note that this can miss FPE's in limbo -- may be worth catching
171905b261ecSmrg	     * them, though it'd muck up refcounting
172005b261ecSmrg	     */
172105b261ecSmrg	    fpe = find_existing_fpe(font_path_elements, num_fpes, cp, len);
172205b261ecSmrg	    if (fpe)
172305b261ecSmrg	    {
172405b261ecSmrg		err = (*fpe_functions[fpe->type].reset_fpe) (fpe);
172505b261ecSmrg		if (err == Successful)
172605b261ecSmrg		{
172705b261ecSmrg		    UseFPE(fpe);/* since it'll be decref'd later when freed
172805b261ecSmrg				 * from the old list */
172905b261ecSmrg		}
173005b261ecSmrg		else
173105b261ecSmrg		    fpe = 0;
173205b261ecSmrg	    }
173305b261ecSmrg	    /* if error or can't do it, act like it's a new one */
173405b261ecSmrg	    if (!fpe)
173505b261ecSmrg	    {
173605b261ecSmrg		fpe = (FontPathElementPtr) xalloc(sizeof(FontPathElementRec));
173705b261ecSmrg		if (!fpe)
173805b261ecSmrg		{
173905b261ecSmrg		    err = BadAlloc;
174005b261ecSmrg		    goto bail;
174105b261ecSmrg		}
174205b261ecSmrg		fpe->name = (char *) xalloc(len + 1);
174305b261ecSmrg		if (!fpe->name)
174405b261ecSmrg		{
174505b261ecSmrg		    xfree(fpe);
174605b261ecSmrg		    err = BadAlloc;
174705b261ecSmrg		    goto bail;
174805b261ecSmrg		}
174905b261ecSmrg		fpe->refcount = 1;
175005b261ecSmrg
175105b261ecSmrg		strncpy(fpe->name, (char *) cp, (int) len);
175205b261ecSmrg		fpe->name[len] = '\0';
175305b261ecSmrg		fpe->name_length = len;
175405b261ecSmrg		fpe->type = DetermineFPEType(fpe->name);
175505b261ecSmrg		if (fpe->type == -1)
175605b261ecSmrg		    err = BadValue;
175705b261ecSmrg		else
175805b261ecSmrg		    err = (*fpe_functions[fpe->type].init_fpe) (fpe);
175905b261ecSmrg		if (err != Successful)
176005b261ecSmrg		{
176105b261ecSmrg		    if (persist)
176205b261ecSmrg		    {
17634642e01fSmrg			ErrorF("[dix] Could not init font path element %s, removing from list!\n",
176405b261ecSmrg			       fpe->name);
176505b261ecSmrg		    }
176605b261ecSmrg		    xfree (fpe->name);
176705b261ecSmrg		    xfree (fpe);
176805b261ecSmrg		}
176905b261ecSmrg	    }
177005b261ecSmrg	}
177105b261ecSmrg	if (err != Successful)
177205b261ecSmrg	{
177305b261ecSmrg	    if (!persist)
177405b261ecSmrg		goto bail;
177505b261ecSmrg	}
177605b261ecSmrg	else
177705b261ecSmrg	{
177805b261ecSmrg	    fplist[valid_paths++] = fpe;
177905b261ecSmrg	}
178005b261ecSmrg	cp += len;
178105b261ecSmrg    }
178205b261ecSmrg
178305b261ecSmrg    FreeFontPath(font_path_elements, num_fpes, FALSE);
178405b261ecSmrg    font_path_elements = fplist;
178505b261ecSmrg    if (patternCache)
178605b261ecSmrg	EmptyFontPatternCache(patternCache);
178705b261ecSmrg    num_fpes = valid_paths;
178805b261ecSmrg
178905b261ecSmrg    return Success;
179005b261ecSmrgbail:
179105b261ecSmrg    *bad = i;
179205b261ecSmrg    while (--valid_paths >= 0)
179305b261ecSmrg	FreeFPE(fplist[valid_paths]);
179405b261ecSmrg    xfree(fplist);
179505b261ecSmrg    return FontToXError(err);
179605b261ecSmrg}
179705b261ecSmrg
179805b261ecSmrg/* XXX -- do we need to pass error down to each renderer? */
179905b261ecSmrgint
180005b261ecSmrgSetFontPath(ClientPtr client, int npaths, unsigned char *paths, int *error)
180105b261ecSmrg{
18024642e01fSmrg    int err = XaceHook(XACE_SERVER_ACCESS, client, DixManageAccess);
18034642e01fSmrg    if (err != Success)
18044642e01fSmrg	return err;
180505b261ecSmrg
180605b261ecSmrg    if (npaths == 0) {
180705b261ecSmrg	if (SetDefaultFontPath(defaultFontPath) != Success)
180805b261ecSmrg	    return BadValue;
180905b261ecSmrg    } else {
181005b261ecSmrg	err = SetFontPathElements(npaths, paths, error, FALSE);
181105b261ecSmrg    }
181205b261ecSmrg    return err;
181305b261ecSmrg}
181405b261ecSmrg
181505b261ecSmrgint
181605b261ecSmrgSetDefaultFontPath(char *path)
181705b261ecSmrg{
1818b1d344b3Smrg    char       *temp_path,
1819b1d344b3Smrg               *start,
1820b1d344b3Smrg               *end;
182105b261ecSmrg    unsigned char *cp,
182205b261ecSmrg               *pp,
182305b261ecSmrg               *nump,
182405b261ecSmrg               *newpath;
182505b261ecSmrg    int         num = 1,
182605b261ecSmrg                len,
182705b261ecSmrg                err,
182805b261ecSmrg                size = 0,
182905b261ecSmrg                bad;
183005b261ecSmrg
1831b1d344b3Smrg    /* ensure temp_path contains "built-ins" */
1832b1d344b3Smrg    start = path;
1833b1d344b3Smrg    while (1) {
1834b1d344b3Smrg	start = strstr(start, "built-ins");
1835b1d344b3Smrg	if (start == NULL)
1836b1d344b3Smrg	    break;
1837b1d344b3Smrg	end = start + strlen("built-ins");
1838b1d344b3Smrg	if ((start == path || start[-1] == ',') && (!*end || *end == ','))
1839b1d344b3Smrg	    break;
1840b1d344b3Smrg	start = end;
1841b1d344b3Smrg    }
1842b1d344b3Smrg    if (!start) {
1843b1d344b3Smrg	temp_path = Xprintf("%s%sbuilt-ins", path, *path ? "," : "");
1844b1d344b3Smrg    } else {
1845b1d344b3Smrg	temp_path = Xstrdup(path);
1846b1d344b3Smrg    }
1847b1d344b3Smrg    if (!temp_path)
1848b1d344b3Smrg        return BadAlloc;
1849b1d344b3Smrg
185005b261ecSmrg    /* get enough for string, plus values -- use up commas */
1851b1d344b3Smrg    len = strlen(temp_path) + 1;
1852b1d344b3Smrg    nump = cp = newpath = xalloc(len);
185305b261ecSmrg    if (!newpath)
185405b261ecSmrg	return BadAlloc;
1855b1d344b3Smrg    pp = (unsigned char *) temp_path;
185605b261ecSmrg    cp++;
185705b261ecSmrg    while (*pp) {
185805b261ecSmrg	if (*pp == ',') {
185905b261ecSmrg	    *nump = (unsigned char) size;
186005b261ecSmrg	    nump = cp++;
186105b261ecSmrg	    pp++;
186205b261ecSmrg	    num++;
186305b261ecSmrg	    size = 0;
186405b261ecSmrg	} else {
186505b261ecSmrg	    *cp++ = *pp++;
186605b261ecSmrg	    size++;
186705b261ecSmrg	}
186805b261ecSmrg    }
186905b261ecSmrg    *nump = (unsigned char) size;
187005b261ecSmrg
187105b261ecSmrg    err = SetFontPathElements(num, newpath, &bad, TRUE);
187205b261ecSmrg
18734642e01fSmrg    xfree(newpath);
1874b1d344b3Smrg    xfree(temp_path);
187505b261ecSmrg
187605b261ecSmrg    return err;
187705b261ecSmrg}
187805b261ecSmrg
18794642e01fSmrgint
18804642e01fSmrgGetFontPath(ClientPtr client, int *count, int *length, unsigned char **result)
188105b261ecSmrg{
188205b261ecSmrg    int			i;
188305b261ecSmrg    unsigned char       *c;
188405b261ecSmrg    int			len;
188505b261ecSmrg    FontPathElementPtr	fpe;
188605b261ecSmrg
18874642e01fSmrg    i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess);
18884642e01fSmrg    if (i != Success)
18894642e01fSmrg	return i;
18904642e01fSmrg
189105b261ecSmrg    len = 0;
189205b261ecSmrg    for (i = 0; i < num_fpes; i++) {
189305b261ecSmrg	fpe = font_path_elements[i];
189405b261ecSmrg	len += fpe->name_length + 1;
189505b261ecSmrg    }
189605b261ecSmrg    font_path_string = (unsigned char *) xrealloc(font_path_string, len);
189705b261ecSmrg    if (!font_path_string)
18984642e01fSmrg	return BadAlloc;
189905b261ecSmrg
190005b261ecSmrg    c = font_path_string;
190105b261ecSmrg    *length = 0;
190205b261ecSmrg    for (i = 0; i < num_fpes; i++) {
190305b261ecSmrg	fpe = font_path_elements[i];
190405b261ecSmrg	*c = fpe->name_length;
190505b261ecSmrg	*length += *c++;
190605b261ecSmrg	memmove(c, fpe->name, fpe->name_length);
190705b261ecSmrg	c += fpe->name_length;
190805b261ecSmrg    }
190905b261ecSmrg    *count = num_fpes;
19104642e01fSmrg    *result = font_path_string;
19114642e01fSmrg    return Success;
191205b261ecSmrg}
191305b261ecSmrg
191405b261ecSmrgvoid
191505b261ecSmrgDeleteClientFontStuff(ClientPtr client)
191605b261ecSmrg{
191705b261ecSmrg    int			i;
191805b261ecSmrg    FontPathElementPtr	fpe;
191905b261ecSmrg
192005b261ecSmrg    for (i = 0; i < num_fpes; i++)
192105b261ecSmrg    {
192205b261ecSmrg	fpe = font_path_elements[i];
192305b261ecSmrg	if (fpe_functions[fpe->type].client_died)
192405b261ecSmrg	    (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
192505b261ecSmrg    }
192605b261ecSmrg}
192705b261ecSmrg
192805b261ecSmrgvoid
192905b261ecSmrgInitFonts (void)
193005b261ecSmrg{
193105b261ecSmrg    patternCache = MakeFontPatternCache();
193205b261ecSmrg
19334642e01fSmrg    BuiltinRegisterFpeFunctions();
19344642e01fSmrg    FontFileRegisterFpeFunctions();
19354642e01fSmrg    fs_register_fpe_functions();
193605b261ecSmrg}
193705b261ecSmrg
193805b261ecSmrgint
193905b261ecSmrgGetDefaultPointSize ()
194005b261ecSmrg{
194105b261ecSmrg    return 120;
194205b261ecSmrg}
194305b261ecSmrg
194405b261ecSmrg
194505b261ecSmrgFontResolutionPtr
194605b261ecSmrgGetClientResolutions (int *num)
194705b261ecSmrg{
19484642e01fSmrg    static struct _FontResolution res;
19494642e01fSmrg    ScreenPtr   pScreen;
195005b261ecSmrg
19514642e01fSmrg    pScreen = screenInfo.screens[0];
19524642e01fSmrg    res.x_resolution = (pScreen->width * 25.4) / pScreen->mmWidth;
19534642e01fSmrg    /*
19544642e01fSmrg     * XXX - we'll want this as long as bitmap instances are prevalent
19554642e01fSmrg     so that we can match them from scalable fonts
19564642e01fSmrg     */
19574642e01fSmrg    if (res.x_resolution < 88)
19584642e01fSmrg	res.x_resolution = 75;
19594642e01fSmrg    else
19604642e01fSmrg	res.x_resolution = 100;
19614642e01fSmrg    res.y_resolution = (pScreen->height * 25.4) / pScreen->mmHeight;
19624642e01fSmrg    if (res.y_resolution < 88)
19634642e01fSmrg	res.y_resolution = 75;
19644642e01fSmrg    else
19654642e01fSmrg	res.y_resolution = 100;
19664642e01fSmrg    res.point_size = 120;
19674642e01fSmrg    *num = 1;
19684642e01fSmrg    return &res;
196905b261ecSmrg}
197005b261ecSmrg
197105b261ecSmrg/*
197205b261ecSmrg * returns the type index of the new fpe
197305b261ecSmrg *
197405b261ecSmrg * should be called (only once!) by each type of fpe when initialized
197505b261ecSmrg */
197605b261ecSmrg
197705b261ecSmrgint
197805b261ecSmrgRegisterFPEFunctions(NameCheckFunc name_func,
197905b261ecSmrg		     InitFpeFunc init_func,
198005b261ecSmrg		     FreeFpeFunc free_func,
198105b261ecSmrg		     ResetFpeFunc reset_func,
198205b261ecSmrg		     OpenFontFunc open_func,
198305b261ecSmrg		     CloseFontFunc close_func,
198405b261ecSmrg		     ListFontsFunc list_func,
198505b261ecSmrg		     StartLfwiFunc start_lfwi_func,
198605b261ecSmrg		     NextLfwiFunc next_lfwi_func,
198705b261ecSmrg		     WakeupFpeFunc wakeup_func,
198805b261ecSmrg		     ClientDiedFunc client_died,
198905b261ecSmrg		     LoadGlyphsFunc load_glyphs,
199005b261ecSmrg		     StartLaFunc start_list_alias_func,
199105b261ecSmrg		     NextLaFunc next_list_alias_func,
199205b261ecSmrg		     SetPathFunc set_path_func)
199305b261ecSmrg{
199405b261ecSmrg    FPEFunctions *new;
199505b261ecSmrg
199605b261ecSmrg    /* grow the list */
199705b261ecSmrg    new = (FPEFunctions *) xrealloc(fpe_functions,
199805b261ecSmrg				 (num_fpe_types + 1) * sizeof(FPEFunctions));
199905b261ecSmrg    if (!new)
200005b261ecSmrg	return -1;
200105b261ecSmrg    fpe_functions = new;
200205b261ecSmrg
200305b261ecSmrg    fpe_functions[num_fpe_types].name_check = name_func;
200405b261ecSmrg    fpe_functions[num_fpe_types].open_font = open_func;
200505b261ecSmrg    fpe_functions[num_fpe_types].close_font = close_func;
200605b261ecSmrg    fpe_functions[num_fpe_types].wakeup_fpe = wakeup_func;
200705b261ecSmrg    fpe_functions[num_fpe_types].list_fonts = list_func;
200805b261ecSmrg    fpe_functions[num_fpe_types].start_list_fonts_with_info =
200905b261ecSmrg	start_lfwi_func;
201005b261ecSmrg    fpe_functions[num_fpe_types].list_next_font_with_info =
201105b261ecSmrg	next_lfwi_func;
201205b261ecSmrg    fpe_functions[num_fpe_types].init_fpe = init_func;
201305b261ecSmrg    fpe_functions[num_fpe_types].free_fpe = free_func;
201405b261ecSmrg    fpe_functions[num_fpe_types].reset_fpe = reset_func;
201505b261ecSmrg    fpe_functions[num_fpe_types].client_died = client_died;
201605b261ecSmrg    fpe_functions[num_fpe_types].load_glyphs = load_glyphs;
201705b261ecSmrg    fpe_functions[num_fpe_types].start_list_fonts_and_aliases =
201805b261ecSmrg	start_list_alias_func;
201905b261ecSmrg    fpe_functions[num_fpe_types].list_next_font_or_alias =
202005b261ecSmrg	next_list_alias_func;
202105b261ecSmrg    fpe_functions[num_fpe_types].set_path_hook = set_path_func;
202205b261ecSmrg
202305b261ecSmrg    return num_fpe_types++;
202405b261ecSmrg}
202505b261ecSmrg
202605b261ecSmrgvoid
202705b261ecSmrgFreeFonts(void)
202805b261ecSmrg{
202905b261ecSmrg    if (patternCache) {
203005b261ecSmrg	FreeFontPatternCache(patternCache);
203105b261ecSmrg	patternCache = 0;
203205b261ecSmrg    }
203305b261ecSmrg    FreeFontPath(font_path_elements, num_fpes, TRUE);
203405b261ecSmrg    font_path_elements = 0;
203505b261ecSmrg    num_fpes = 0;
203605b261ecSmrg    xfree(fpe_functions);
203705b261ecSmrg    num_fpe_types = 0;
203805b261ecSmrg    fpe_functions = (FPEFunctions *) 0;
203905b261ecSmrg}
204005b261ecSmrg
204105b261ecSmrg/* convenience functions for FS interface */
204205b261ecSmrg
204305b261ecSmrgFontPtr
204405b261ecSmrgfind_old_font(XID id)
204505b261ecSmrg{
204605b261ecSmrg    return (FontPtr) SecurityLookupIDByType(NullClient, id, RT_NONE,
204705b261ecSmrg					    DixUnknownAccess);
204805b261ecSmrg}
204905b261ecSmrg
205005b261ecSmrgFont
205105b261ecSmrgGetNewFontClientID()
205205b261ecSmrg{
205305b261ecSmrg    return FakeClientID(0);
205405b261ecSmrg}
205505b261ecSmrg
205605b261ecSmrgint
205705b261ecSmrgStoreFontClientFont(FontPtr pfont, Font id)
205805b261ecSmrg{
205905b261ecSmrg    return AddResource(id, RT_NONE, (pointer) pfont);
206005b261ecSmrg}
206105b261ecSmrg
206205b261ecSmrgvoid
206305b261ecSmrgDeleteFontClientID(Font id)
206405b261ecSmrg{
206505b261ecSmrg    FreeResource(id, RT_NONE);
206605b261ecSmrg}
206705b261ecSmrg
206805b261ecSmrgint
206905b261ecSmrgclient_auth_generation(ClientPtr client)
207005b261ecSmrg{
207105b261ecSmrg    return 0;
207205b261ecSmrg}
207305b261ecSmrg
207405b261ecSmrgstatic int  fs_handlers_installed = 0;
207505b261ecSmrgstatic unsigned int last_server_gen;
207605b261ecSmrg
207705b261ecSmrgint
207805b261ecSmrginit_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler)
207905b261ecSmrg{
208005b261ecSmrg    /* if server has reset, make sure the b&w handlers are reinstalled */
208105b261ecSmrg    if (last_server_gen < serverGeneration) {
208205b261ecSmrg	last_server_gen = serverGeneration;
208305b261ecSmrg	fs_handlers_installed = 0;
208405b261ecSmrg    }
208505b261ecSmrg    if (fs_handlers_installed == 0) {
208605b261ecSmrg	if (!RegisterBlockAndWakeupHandlers(block_handler,
208705b261ecSmrg					    FontWakeup, (pointer) 0))
208805b261ecSmrg	    return AllocError;
208905b261ecSmrg	fs_handlers_installed++;
209005b261ecSmrg    }
209105b261ecSmrg    QueueFontWakeup(fpe);
209205b261ecSmrg    return Successful;
209305b261ecSmrg}
209405b261ecSmrg
209505b261ecSmrgvoid
209605b261ecSmrgremove_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler, Bool all)
209705b261ecSmrg{
209805b261ecSmrg    if (all) {
209905b261ecSmrg	/* remove the handlers if no one else is using them */
210005b261ecSmrg	if (--fs_handlers_installed == 0) {
210105b261ecSmrg	    RemoveBlockAndWakeupHandlers(block_handler, FontWakeup,
210205b261ecSmrg					 (pointer) 0);
210305b261ecSmrg	}
210405b261ecSmrg    }
210505b261ecSmrg    RemoveFontWakeup(fpe);
210605b261ecSmrg}
2107