diff options
Diffstat (limited to 'xorg-server/dix/dixfonts.c')
| -rw-r--r-- | xorg-server/dix/dixfonts.c | 4206 | 
1 files changed, 2104 insertions, 2102 deletions
| diff --git a/xorg-server/dix/dixfonts.c b/xorg-server/dix/dixfonts.c index 329318d5d..77c166ee5 100644 --- a/xorg-server/dix/dixfonts.c +++ b/xorg-server/dix/dixfonts.c @@ -1,2102 +1,2104 @@ -/************************************************************************ -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - -                        All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -************************************************************************/ -/* The panoramix components contained the following notice */ -/* -Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL -DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, -BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of Digital Equipment Corporation -shall not be used in advertising or otherwise to promote the sale, use or other -dealings in this Software without prior written authorization from Digital -Equipment Corporation. - -******************************************************************/ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include <X11/X.h> -#include <X11/Xmd.h> -#include <X11/Xproto.h> -#include "scrnintstr.h" -#include "resource.h" -#include "dixstruct.h" -#include "cursorstr.h" -#include "misc.h" -#include "opaque.h" -#include "dixfontstr.h" -#include "closestr.h" -#include "dixfont.h" -#include "xace.h" - -#ifdef DEBUG -#include	<stdio.h> -#endif - -#ifdef XF86BIGFONT -#define _XF86BIGFONT_SERVER_ -#include <X11/extensions/xf86bigfont.h> -#endif - -#define QUERYCHARINFO(pci, pr)  *(pr) = (pci)->metrics - -extern pointer fosNaturalParams; -extern FontPtr defaultFont; - -static FontPathElementPtr *font_path_elements = (FontPathElementPtr *) 0; -static int  num_fpes = 0; -static FPEFunctions *fpe_functions = (FPEFunctions *) 0; -static int  num_fpe_types = 0; - -static unsigned char *font_path_string; - -static int  num_slept_fpes = 0; -static int  size_slept_fpes = 0; -static FontPathElementPtr *slept_fpes = (FontPathElementPtr *) 0; -static FontPatternCachePtr patternCache; - -static int -FontToXError(int err) -{ -    switch (err) { -    case Successful: -	return Success; -    case AllocError: -	return BadAlloc; -    case BadFontName: -	return BadName; -    case BadFontPath: -    case BadFontFormat:	/* is there something better? */ -    case BadCharRange: -	return BadValue; -    default: -	return err; -    } -} - -static int -LoadGlyphs(ClientPtr client, FontPtr pfont, unsigned nchars, int item_size, -	   unsigned char *data) -{ -    if (fpe_functions[pfont->fpe->type].load_glyphs) -	return (*fpe_functions[pfont->fpe->type].load_glyphs) -	    (client, pfont, 0, nchars, item_size, data); -    else -	return Successful; -} - -/* - * adding RT_FONT prevents conflict with default cursor font - */ -Bool -SetDefaultFont(char *defaultfontname) -{ -    int         err; -    FontPtr     pf; -    XID         fid; - -    fid = FakeClientID(0); -    err = OpenFont(serverClient, fid, FontLoadAll | FontOpenSync, -		   (unsigned) strlen(defaultfontname), defaultfontname); -    if (err != Success) -	return FALSE; -    err = dixLookupResourceByType((pointer *)&pf, fid, RT_FONT, serverClient, -				  DixReadAccess); -    if (err != Success) -	return FALSE; -    defaultFont = pf; -    return TRUE; -} - -/* - * note that the font wakeup queue is not refcounted.  this is because - * an fpe needs to be added when it's inited, and removed when it's finally - * freed, in order to handle any data that isn't requested, like FS events. - * - * since the only thing that should call these routines is the renderer's - * init_fpe() and free_fpe(), there shouldn't be any problem in using - * freed data. - */ -void -QueueFontWakeup(FontPathElementPtr fpe) -{ -    int         i; -    FontPathElementPtr *new; - -    for (i = 0; i < num_slept_fpes; i++) { -	if (slept_fpes[i] == fpe) { -	    return; -	} -    } -    if (num_slept_fpes == size_slept_fpes) { -	new = (FontPathElementPtr *) -	    xrealloc(slept_fpes, -		     sizeof(FontPathElementPtr) * (size_slept_fpes + 4)); -	if (!new) -	    return; -	slept_fpes = new; -	size_slept_fpes += 4; -    } -    slept_fpes[num_slept_fpes] = fpe; -    num_slept_fpes++; -} - -void -RemoveFontWakeup(FontPathElementPtr fpe) -{ -    int         i, -                j; - -    for (i = 0; i < num_slept_fpes; i++) { -	if (slept_fpes[i] == fpe) { -	    for (j = i; j < num_slept_fpes; j++) { -		slept_fpes[j] = slept_fpes[j + 1]; -	    } -	    num_slept_fpes--; -	    return; -	} -    } -} - -void -FontWakeup(pointer data, int count, pointer LastSelectMask) -{ -    int         i; -    FontPathElementPtr fpe; - -    if (count < 0) -	return; -    /* wake up any fpe's that may be waiting for information */ -    for (i = 0; i < num_slept_fpes; i++) { -	fpe = slept_fpes[i]; -	(void) (*fpe_functions[fpe->type].wakeup_fpe) (fpe, LastSelectMask); -    } -} - -/* XXX -- these two funcs may want to be broken into macros */ -static void -UseFPE(FontPathElementPtr fpe) -{ -    fpe->refcount++; -} - -static void -FreeFPE (FontPathElementPtr fpe) -{ -    fpe->refcount--; -    if (fpe->refcount == 0) { -	(*fpe_functions[fpe->type].free_fpe) (fpe); -	xfree(fpe->name); -	xfree(fpe); -    } -} - -static Bool -doOpenFont(ClientPtr client, OFclosurePtr c) -{ -    FontPtr     pfont = NullFont; -    FontPathElementPtr fpe = NULL; -    ScreenPtr   pScr; -    int         err = Successful; -    int         i; -    char       *alias, -               *newname; -    int         newlen; -    int		aliascount = 20; -    /* -     * Decide at runtime what FontFormat to use. -     */ -    Mask FontFormat =  - -	((screenInfo.imageByteOrder == LSBFirst) ? -	    BitmapFormatByteOrderLSB : BitmapFormatByteOrderMSB) | - -	((screenInfo.bitmapBitOrder == LSBFirst) ? -	    BitmapFormatBitOrderLSB : BitmapFormatBitOrderMSB) | - -	BitmapFormatImageRectMin | - -#if GLYPHPADBYTES == 1 -	BitmapFormatScanlinePad8 | -#endif - -#if GLYPHPADBYTES == 2 -	BitmapFormatScanlinePad16 | -#endif - -#if GLYPHPADBYTES == 4 -	BitmapFormatScanlinePad32 | -#endif - -#if GLYPHPADBYTES == 8 -	BitmapFormatScanlinePad64 | -#endif - -	BitmapFormatScanlineUnit8; - -    if (client->clientGone) -    { -	if (c->current_fpe < c->num_fpes) -	{ -	    fpe = c->fpe_list[c->current_fpe]; -	    (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); -	} -	err = Successful; -	goto bail; -    } -    while (c->current_fpe < c->num_fpes) { -	fpe = c->fpe_list[c->current_fpe]; -	err = (*fpe_functions[fpe->type].open_font) -	    ((pointer) client, fpe, c->flags, -	     c->fontname, c->fnamelen, FontFormat, -	     BitmapFormatMaskByte | -	     BitmapFormatMaskBit | -	     BitmapFormatMaskImageRectangle | -	     BitmapFormatMaskScanLinePad | -	     BitmapFormatMaskScanLineUnit, -	     c->fontid, &pfont, &alias, -	     c->non_cachable_font && c->non_cachable_font->fpe == fpe ? -		 c->non_cachable_font : -		 (FontPtr)0); - -	if (err == FontNameAlias && alias) { -	    newlen = strlen(alias); -	    newname = (char *) xrealloc(c->fontname, newlen); -	    if (!newname) { -		err = AllocError; -		break; -	    } -	    memmove(newname, alias, newlen); -	    c->fontname = newname; -	    c->fnamelen = newlen; -	    c->current_fpe = 0; -	    if (--aliascount <= 0) { -		/* We've tried resolving this alias 20 times, we're - 		 * probably stuck in an infinite loop of aliases pointing - 		 * to each other - time to take emergency exit! - 		 */ - 		err = BadImplementation; -		break; -	    } -	    continue; -	} -	if (err == BadFontName) { -	    c->current_fpe++; -	    continue; -	} -	if (err == Suspended) { -	    if (!c->slept) { -		c->slept = TRUE; -		ClientSleep(client, (ClientSleepProcPtr)doOpenFont, (pointer) c); -	    } -	    return TRUE; -	} -	break; -    } - -    if (err != Successful) -	goto bail; -    if (!pfont) { -	err = BadFontName; -	goto bail; -    } -    /* check values for firstCol, lastCol, firstRow, and lastRow */ -    if (pfont->info.firstCol > pfont->info.lastCol || -       pfont->info.firstRow > pfont->info.lastRow || -       pfont->info.lastCol - pfont->info.firstCol > 255) { -       err = AllocError; -       goto bail; -    } -    if (!pfont->fpe) -	pfont->fpe = fpe; -    pfont->refcnt++; -    if (pfont->refcnt == 1) { -	UseFPE(pfont->fpe); -	for (i = 0; i < screenInfo.numScreens; i++) { -	    pScr = screenInfo.screens[i]; -	    if (pScr->RealizeFont) -	    { -		if (!(*pScr->RealizeFont) (pScr, pfont)) -		{ -		    CloseFont (pfont, (Font) 0); -		    err = AllocError; -		    goto bail; -		} -	    } -	} -    } -    if (!AddResource(c->fontid, RT_FONT, (pointer) pfont)) { -	err = AllocError; -	goto bail; -    } -    if (patternCache && pfont != c->non_cachable_font) -	CacheFontPattern(patternCache, c->origFontName, c->origFontNameLen, -			 pfont); -bail: -    if (err != Successful && c->client != serverClient) { -	SendErrorToClient(c->client, X_OpenFont, 0, -			  c->fontid, FontToXError(err)); -    } -    if (c->slept) -	ClientWakeup(c->client); -    for (i = 0; i < c->num_fpes; i++) { -	FreeFPE(c->fpe_list[i]); -    } -    xfree(c->fpe_list); -    xfree(c->fontname); -    xfree(c); -    return TRUE; -} - -int -OpenFont(ClientPtr client, XID fid, Mask flags, unsigned lenfname, char *pfontname) -{ -    OFclosurePtr c; -    int         i; -    FontPtr     cached = (FontPtr)0; - -#ifdef FONTDEBUG -    char *f; -    f = xalloc(lenfname + 1); -    memmove(f, pfontname, lenfname); -    f[lenfname] = '\0'; -    ErrorF("[dix] OpenFont: fontname is \"%s\"\n", f); -    xfree(f); -#endif -    if (!lenfname || lenfname > XLFDMAXFONTNAMELEN) -	return BadName; -    if (patternCache) -    { - -    /* -    ** Check name cache.  If we find a cached version of this font that -    ** is cachable, immediately satisfy the request with it.  If we find -    ** a cached version of this font that is non-cachable, we do not -    ** satisfy the request with it.  Instead, we pass the FontPtr to the -    ** FPE's open_font code (the fontfile FPE in turn passes the -    ** information to the rasterizer; the fserve FPE ignores it). -    ** -    ** Presumably, the font is marked non-cachable because the FPE has -    ** put some licensing restrictions on it.  If the FPE, using -    ** whatever logic it relies on, determines that it is willing to -    ** share this existing font with the client, then it has the option -    ** to return the FontPtr we passed it as the newly-opened font. -    ** This allows the FPE to exercise its licensing logic without -    ** having to create another instance of a font that already exists. -    */ - -	cached = FindCachedFontPattern(patternCache, pfontname, lenfname); -	if (cached && cached->info.cachable) -	{ -	    if (!AddResource(fid, RT_FONT, (pointer) cached)) -		return BadAlloc; -	    cached->refcnt++; -	    return Success; -	} -    } -    c = xalloc(sizeof(OFclosureRec)); -    if (!c) -	return BadAlloc; -    c->fontname = xalloc(lenfname); -    c->origFontName = pfontname; -    c->origFontNameLen = lenfname; -    if (!c->fontname) { -	xfree(c); -	return BadAlloc; -    } -    /* -     * copy the current FPE list, so that if it gets changed by another client -     * while we're blocking, the request still appears atomic -     */ -    c->fpe_list = xalloc(sizeof(FontPathElementPtr) * num_fpes); -    if (!c->fpe_list) { -	xfree(c->fontname); -	xfree(c); -	return BadAlloc; -    } -    memmove(c->fontname, pfontname, lenfname); -    for (i = 0; i < num_fpes; i++) { -	c->fpe_list[i] = font_path_elements[i]; -	UseFPE(c->fpe_list[i]); -    } -    c->client = client; -    c->fontid = fid; -    c->current_fpe = 0; -    c->num_fpes = num_fpes; -    c->fnamelen = lenfname; -    c->slept = FALSE; -    c->flags = flags; -    c->non_cachable_font = cached; - -    (void) doOpenFont(client, c); -    return Success; -} - -/** - * Decrement font's ref count, and free storage if ref count equals zero - * - *  \param value must conform to DeleteType - */ -int -CloseFont(pointer value, XID fid) -{ -    int         nscr; -    ScreenPtr   pscr; -    FontPathElementPtr fpe; -    FontPtr     pfont = (FontPtr)value; - -    if (pfont == NullFont) -	return (Success); -    if (--pfont->refcnt == 0) { -	if (patternCache) -	    RemoveCachedFontPattern (patternCache, pfont); -	/* -	 * since the last reference is gone, ask each screen to free any -	 * storage it may have allocated locally for it. -	 */ -	for (nscr = 0; nscr < screenInfo.numScreens; nscr++) { -	    pscr = screenInfo.screens[nscr]; -	    if (pscr->UnrealizeFont) -		(*pscr->UnrealizeFont) (pscr, pfont); -	} -	if (pfont == defaultFont) -	    defaultFont = NULL; -#ifdef XF86BIGFONT -	XF86BigfontFreeFontShm(pfont); -#endif -	fpe = pfont->fpe; -	(*fpe_functions[fpe->type].close_font) (fpe, pfont); -	FreeFPE(fpe); -    } -    return (Success); -} - - -/***====================================================================***/ - -/** - * Sets up pReply as the correct QueryFontReply for pFont with the first - * nProtoCCIStructs char infos. - * - *  \param pReply caller must allocate this storage -  */ -void -QueryFont(FontPtr pFont, xQueryFontReply *pReply, int nProtoCCIStructs) -{ -    FontPropPtr      pFP; -    int              r, -                     c, -                     i; -    xFontProp       *prFP; -    xCharInfo       *prCI; -    xCharInfo       *charInfos[256]; -    unsigned char    chars[512]; -    int              ninfos; -    unsigned long    ncols; -    unsigned long    count; - -    /* pr->length set in dispatch */ -    pReply->minCharOrByte2 = pFont->info.firstCol; -    pReply->defaultChar = pFont->info.defaultCh; -    pReply->maxCharOrByte2 = pFont->info.lastCol; -    pReply->drawDirection = pFont->info.drawDirection; -    pReply->allCharsExist = pFont->info.allExist; -    pReply->minByte1 = pFont->info.firstRow; -    pReply->maxByte1 = pFont->info.lastRow; -    pReply->fontAscent = pFont->info.fontAscent; -    pReply->fontDescent = pFont->info.fontDescent; - -    pReply->minBounds = pFont->info.ink_minbounds; -    pReply->maxBounds = pFont->info.ink_maxbounds; - -    pReply->nFontProps = pFont->info.nprops; -    pReply->nCharInfos = nProtoCCIStructs; - -    for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) (&pReply[1]); -	    i < pFont->info.nprops; -	    i++, pFP++, prFP++) { -	prFP->name = pFP->name; -	prFP->value = pFP->value; -    } - -    ninfos = 0; -    ncols = (unsigned long) (pFont->info.lastCol - pFont->info.firstCol + 1); -    prCI = (xCharInfo *) (prFP); -    for (r = pFont->info.firstRow; -	    ninfos < nProtoCCIStructs && r <= (int)pFont->info.lastRow; -	    r++) { -	i = 0; -	for (c = pFont->info.firstCol; c <= (int)pFont->info.lastCol; c++) { -	    chars[i++] = r; -	    chars[i++] = c; -	} -	(*pFont->get_metrics) (pFont, ncols, chars,  -				TwoD16Bit, &count, charInfos); -	i = 0; -	for (i = 0; i < (int) count && ninfos < nProtoCCIStructs; i++) { -	    *prCI = *charInfos[i]; -	    prCI++; -	    ninfos++; -	} -    } -    return; -} - -static Bool -doListFontsAndAliases(ClientPtr client, LFclosurePtr c) -{ -    FontPathElementPtr fpe; -    int         err = Successful; -    FontNamesPtr names = NULL; -    char       *name, *resolved=NULL; -    int         namelen, resolvedlen; -    int		nnames; -    int         stringLens; -    int         i; -    xListFontsReply reply; -    char	*bufptr; -    char	*bufferStart; -    int		aliascount = 0; - -    if (client->clientGone) -    { -	if (c->current.current_fpe < c->num_fpes) -	{ -	    fpe = c->fpe_list[c->current.current_fpe]; -	    (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); -	} -	err = Successful; -	goto bail; -    } - -    if (!c->current.patlen) -	goto finish; - -    while (c->current.current_fpe < c->num_fpes) { -	fpe = c->fpe_list[c->current.current_fpe]; -	err = Successful; - -	if (!fpe_functions[fpe->type].start_list_fonts_and_aliases) -	{ -	    /* This FPE doesn't support/require list_fonts_and_aliases */ - -	    err = (*fpe_functions[fpe->type].list_fonts) -		((pointer) c->client, fpe, c->current.pattern, -		 c->current.patlen, c->current.max_names - c->names->nnames, -		 c->names); - -	    if (err == Suspended) { -		if (!c->slept) { -		    c->slept = TRUE; -		    ClientSleep(client, -			(ClientSleepProcPtr)doListFontsAndAliases, -			(pointer) c); -		} -		return TRUE; -	    } - -	    err = BadFontName; -	} -	else -	{ -	    /* Start of list_fonts_and_aliases functionality.  Modeled -	       after list_fonts_with_info in that it resolves aliases, -	       except that the information collected from FPEs is just -	       names, not font info.  Each list_next_font_or_alias() -	       returns either a name into name/namelen or an alias into -	       name/namelen and its target name into resolved/resolvedlen. -	       The code at this level then resolves the alias by polling -	       the FPEs.  */ - -	    if (!c->current.list_started) { -		err = (*fpe_functions[fpe->type].start_list_fonts_and_aliases) -		    ((pointer) c->client, fpe, c->current.pattern, -		     c->current.patlen, c->current.max_names - c->names->nnames, -		     &c->current.private); -		if (err == Suspended) { -		    if (!c->slept) { -			ClientSleep(client, -				    (ClientSleepProcPtr)doListFontsAndAliases, -				    (pointer) c); -			c->slept = TRUE; -		    } -		    return TRUE; -		} -		if (err == Successful) -		    c->current.list_started = TRUE; -	    } -	    if (err == Successful) { -		char    *tmpname; -		name = 0; -		err = (*fpe_functions[fpe->type].list_next_font_or_alias) -		    ((pointer) c->client, fpe, &name, &namelen, &tmpname, -		     &resolvedlen, c->current.private); -		if (err == Suspended) { -		    if (!c->slept) { -			ClientSleep(client, -				    (ClientSleepProcPtr)doListFontsAndAliases, -				    (pointer) c); -			c->slept = TRUE; -		    } -		    return TRUE; -		} -		if (err == FontNameAlias) { -		    if (resolved) xfree(resolved); -		    resolved = xalloc(resolvedlen + 1); -		    if (resolved) -			memmove(resolved, tmpname, resolvedlen + 1); -		} -	    } - -	    if (err == Successful) -	    { -		if (c->haveSaved) -		{ -		    if (c->savedName) -			(void)AddFontNamesName(c->names, c->savedName, -					       c->savedNameLen); -		} -		else -		    (void)AddFontNamesName(c->names, name, namelen); -	    } - -	    /* -	     * When we get an alias back, save our state and reset back to -	     * the start of the FPE looking for the specified name.  As -	     * soon as a real font is found for the alias, pop back to the -	     * old state -	     */ -	    else if (err == FontNameAlias) { -		char	tmp_pattern[XLFDMAXFONTNAMELEN]; -		/* -		 * when an alias recurses, we need to give -		 * the last FPE a chance to clean up; so we call -		 * it again, and assume that the error returned -		 * is BadFontName, indicating the alias resolution -		 * is complete. -		 */ -		memmove(tmp_pattern, resolved, resolvedlen); -		if (c->haveSaved) -		{ -		    char    *tmpname; -		    int     tmpnamelen; - -		    tmpname = 0; -		    (void) (*fpe_functions[fpe->type].list_next_font_or_alias) -			((pointer) c->client, fpe, &tmpname, &tmpnamelen, -			 &tmpname, &tmpnamelen, c->current.private); -		    if (--aliascount <= 0) -		    { -			err = BadFontName; -			goto ContBadFontName; -		    } -		} -		else -		{ -		    c->saved = c->current; -		    c->haveSaved = TRUE; -		    if (c->savedName) -			xfree(c->savedName); -		    c->savedName = xalloc(namelen + 1); -		    if (c->savedName) -			memmove(c->savedName, name, namelen + 1); -		    c->savedNameLen = namelen; -		    aliascount = 20; -		} -		memmove(c->current.pattern, tmp_pattern, resolvedlen); -		c->current.patlen = resolvedlen; -		c->current.max_names = c->names->nnames + 1; -		c->current.current_fpe = -1; -		c->current.private = 0; -		err = BadFontName; -	    } -	} -	/* -	 * At the end of this FPE, step to the next.  If we've finished -	 * processing an alias, pop state back. If we've collected enough -	 * font names, quit. -	 */ -	if (err == BadFontName) { -	  ContBadFontName: ; -	    c->current.list_started = FALSE; -	    c->current.current_fpe++; -	    err = Successful; -	    if (c->haveSaved) -	    { -		if (c->names->nnames == c->current.max_names || -			c->current.current_fpe == c->num_fpes) { -		    c->haveSaved = FALSE; -		    c->current = c->saved; -		    /* Give the saved namelist a chance to clean itself up */ -		    continue; -		} -	    } -	    if (c->names->nnames == c->current.max_names) -		break; -	} -    } - -    /* -     * send the reply -     */ -    if (err != Successful) { -	SendErrorToClient(client, X_ListFonts, 0, 0, FontToXError(err)); -	goto bail; -    } - -finish: - -    names = c->names; -    nnames = names->nnames; -    client = c->client; -    stringLens = 0; -    for (i = 0; i < nnames; i++) -	stringLens += (names->length[i] <= 255) ? names->length[i] : 0; - -    memset(&reply, 0, sizeof(xListFontsReply)); -    reply.type = X_Reply; -    reply.length = bytes_to_int32(stringLens + nnames); -    reply.nFonts = nnames; -    reply.sequenceNumber = client->sequence; - -    bufptr = bufferStart = xalloc(reply.length << 2); - -    if (!bufptr && reply.length) { -	SendErrorToClient(client, X_ListFonts, 0, 0, BadAlloc); -	goto bail; -    } -    /* -     * since WriteToClient long word aligns things, copy to temp buffer and -     * write all at once -     */ -    for (i = 0; i < nnames; i++) { -	if (names->length[i] > 255) -	    reply.nFonts--; -	else -	{ -	    *bufptr++ = names->length[i]; -	    memmove( bufptr, names->names[i], names->length[i]); -	    bufptr += names->length[i]; -	} -    } -    nnames = reply.nFonts; -    reply.length = bytes_to_int32(stringLens + nnames); -    client->pSwapReplyFunc = ReplySwapVector[X_ListFonts]; -    WriteSwappedDataToClient(client, sizeof(xListFontsReply), &reply); -    (void) WriteToClient(client, stringLens + nnames, bufferStart); -    xfree(bufferStart); - -bail: -    if (c->slept) -	ClientWakeup(client); -    for (i = 0; i < c->num_fpes; i++) -	FreeFPE(c->fpe_list[i]); -    xfree(c->fpe_list); -    if (c->savedName) xfree(c->savedName); -    FreeFontNames(names); -    xfree(c); -    if (resolved) xfree(resolved); -    return TRUE; -} - -int -ListFonts(ClientPtr client, unsigned char *pattern, unsigned length,  -          unsigned max_names) -{ -    int         i; -    LFclosurePtr c; - -    /*  -     * The right error to return here would be BadName, however the -     * specification does not allow for a Name error on this request. -     * Perhaps a better solution would be to return a nil list, i.e. -     * a list containing zero fontnames. -     */ -    if (length > XLFDMAXFONTNAMELEN) -	return BadAlloc; - -    i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess); -    if (i != Success) -	return i; - -    if (!(c = xalloc(sizeof *c))) -	return BadAlloc; -    c->fpe_list = xalloc(sizeof(FontPathElementPtr) * num_fpes); -    if (!c->fpe_list) { -	xfree(c); -	return BadAlloc; -    } -    c->names = MakeFontNamesRecord(max_names < 100 ? max_names : 100); -    if (!c->names) -    { -	xfree(c->fpe_list); -	xfree(c); -	return BadAlloc; -    } -    memmove( c->current.pattern, pattern, length); -    for (i = 0; i < num_fpes; i++) { -	c->fpe_list[i] = font_path_elements[i]; -	UseFPE(c->fpe_list[i]); -    } -    c->client = client; -    c->num_fpes = num_fpes; -    c->current.patlen = length; -    c->current.current_fpe = 0; -    c->current.max_names = max_names; -    c->current.list_started = FALSE; -    c->current.private = 0; -    c->haveSaved = FALSE; -    c->slept = FALSE; -    c->savedName = 0; -    doListFontsAndAliases(client, c); -    return Success; -} - -int -doListFontsWithInfo(ClientPtr client, LFWIclosurePtr c) -{ -    FontPathElementPtr fpe; -    int         err = Successful; -    char       *name; -    int         namelen; -    int         numFonts; -    FontInfoRec fontInfo, -               *pFontInfo; -    xListFontsWithInfoReply *reply; -    int         length; -    xFontProp  *pFP; -    int         i; -    int		aliascount = 0; -    xListFontsWithInfoReply finalReply; - -    if (client->clientGone) -    { -	if (c->current.current_fpe < c->num_fpes) - 	{ -	    fpe = c->fpe_list[c->current.current_fpe]; -	    (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); -	} -	err = Successful; -	goto bail; -    } -    client->pSwapReplyFunc = ReplySwapVector[X_ListFontsWithInfo]; -    if (!c->current.patlen) -	goto finish; -    while (c->current.current_fpe < c->num_fpes) -    { -	fpe = c->fpe_list[c->current.current_fpe]; -	err = Successful; -	if (!c->current.list_started) - 	{ -	    err = (*fpe_functions[fpe->type].start_list_fonts_with_info) -		(client, fpe, c->current.pattern, c->current.patlen, -		 c->current.max_names, &c->current.private); -	    if (err == Suspended) - 	    { -		if (!c->slept) - 		{ -		    ClientSleep(client, (ClientSleepProcPtr)doListFontsWithInfo, c); -		    c->slept = TRUE; -		} -		return TRUE; -	    } -	    if (err == Successful) -		c->current.list_started = TRUE; -	} -	if (err == Successful) - 	{ -	    name = 0; -	    pFontInfo = &fontInfo; -	    err = (*fpe_functions[fpe->type].list_next_font_with_info) -		(client, fpe, &name, &namelen, &pFontInfo, -		 &numFonts, c->current.private); -	    if (err == Suspended) - 	    { -		if (!c->slept) - 		{ -		    ClientSleep(client, -		    	     (ClientSleepProcPtr)doListFontsWithInfo, -			     c); -		    c->slept = TRUE; -		} -		return TRUE; -	    } -	} -	/* -	 * When we get an alias back, save our state and reset back to the -	 * start of the FPE looking for the specified name.  As soon as a real -	 * font is found for the alias, pop back to the old state -	 */ -	if (err == FontNameAlias) - 	{ -	    /* -	     * when an alias recurses, we need to give -	     * the last FPE a chance to clean up; so we call -	     * it again, and assume that the error returned -	     * is BadFontName, indicating the alias resolution -	     * is complete. -	     */ -	    if (c->haveSaved) -	    { -		char	*tmpname; -		int	tmpnamelen; -		FontInfoPtr tmpFontInfo; - -	    	tmpname = 0; -	    	tmpFontInfo = &fontInfo; -	    	(void) (*fpe_functions[fpe->type].list_next_font_with_info) -		    (client, fpe, &tmpname, &tmpnamelen, &tmpFontInfo, -		     &numFonts, c->current.private); -		if (--aliascount <= 0) -		{ -		    err = BadFontName; -		    goto ContBadFontName; -		} -	    } -	    else -	    { -		c->saved = c->current; -		c->haveSaved = TRUE; -		c->savedNumFonts = numFonts; -		if (c->savedName) -		  xfree(c->savedName); -		c->savedName = xalloc(namelen + 1); -		if (c->savedName) -		  memmove(c->savedName, name, namelen + 1); -		aliascount = 20; -	    } -	    memmove(c->current.pattern, name, namelen); -	    c->current.patlen = namelen; -	    c->current.max_names = 1; -	    c->current.current_fpe = 0; -	    c->current.private = 0; -	    c->current.list_started = FALSE; -	} -	/* -	 * At the end of this FPE, step to the next.  If we've finished -	 * processing an alias, pop state back.  If we've sent enough font -	 * names, quit.  Always wait for BadFontName to let the FPE -	 * have a chance to clean up. -	 */ -	else if (err == BadFontName) - 	{ -	  ContBadFontName: ; -	    c->current.list_started = FALSE; -	    c->current.current_fpe++; -	    err = Successful; -	    if (c->haveSaved) - 	    { -		if (c->current.max_names == 0 || -			c->current.current_fpe == c->num_fpes) - 		{ -		    c->haveSaved = FALSE; -		    c->saved.max_names -= (1 - c->current.max_names); -		    c->current = c->saved; -		} -	    } -	    else if (c->current.max_names == 0) -		break; -	} - 	else if (err == Successful) - 	{ -	    length = sizeof(*reply) + pFontInfo->nprops * sizeof(xFontProp); -	    reply = c->reply; -	    if (c->length < length) - 	    { -		reply = (xListFontsWithInfoReply *) xrealloc(c->reply, length); -		if (!reply) - 		{ -		    err = AllocError; -		    break; -		} -		memset((char*)reply + c->length, 0, length - c->length); -		c->reply = reply; -		c->length = length; -	    } -	    if (c->haveSaved) - 	    { -		numFonts = c->savedNumFonts; -		name = c->savedName; -		namelen = strlen(name); -	    } -	    reply->type = X_Reply; -	    reply->length = bytes_to_int32(sizeof *reply - sizeof(xGenericReply) + -			     pFontInfo->nprops * sizeof(xFontProp) + -			     namelen); -	    reply->sequenceNumber = client->sequence; -	    reply->nameLength = namelen; -	    reply->minBounds = pFontInfo->ink_minbounds; -	    reply->maxBounds = pFontInfo->ink_maxbounds; -	    reply->minCharOrByte2 = pFontInfo->firstCol; -	    reply->maxCharOrByte2 = pFontInfo->lastCol; -	    reply->defaultChar = pFontInfo->defaultCh; -	    reply->nFontProps = pFontInfo->nprops; -	    reply->drawDirection = pFontInfo->drawDirection; -	    reply->minByte1 = pFontInfo->firstRow; -	    reply->maxByte1 = pFontInfo->lastRow; -	    reply->allCharsExist = pFontInfo->allExist; -	    reply->fontAscent = pFontInfo->fontAscent; -	    reply->fontDescent = pFontInfo->fontDescent; -	    reply->nReplies = numFonts; -	    pFP = (xFontProp *) (reply + 1); -	    for (i = 0; i < pFontInfo->nprops; i++) - 	    { -		pFP->name = pFontInfo->props[i].name; -		pFP->value = pFontInfo->props[i].value; -		pFP++; -	    } -	    WriteSwappedDataToClient(client, length, reply); -	    (void) WriteToClient(client, namelen, name); -	    if (pFontInfo == &fontInfo) - 	    { -		xfree(fontInfo.props); -		xfree(fontInfo.isStringProp); -	    } -	    --c->current.max_names; -	} -    } -finish: -    length = sizeof(xListFontsWithInfoReply); -    bzero((char *) &finalReply, sizeof(xListFontsWithInfoReply)); -    finalReply.type = X_Reply; -    finalReply.sequenceNumber = client->sequence; -    finalReply.length = bytes_to_int32(sizeof(xListFontsWithInfoReply) -		     - sizeof(xGenericReply)); -    WriteSwappedDataToClient(client, length, &finalReply); -bail: -    if (c->slept) -	ClientWakeup(client); -    for (i = 0; i < c->num_fpes; i++) -	FreeFPE(c->fpe_list[i]); -    xfree(c->reply); -    xfree(c->fpe_list); -    if (c->savedName) xfree(c->savedName); -    xfree(c); -    return TRUE; -} - -int -StartListFontsWithInfo(ClientPtr client, int length, unsigned char *pattern,  -                       int max_names) -{ -    int		    i; -    LFWIclosurePtr  c; - -    /*  -     * The right error to return here would be BadName, however the -     * specification does not allow for a Name error on this request. -     * Perhaps a better solution would be to return a nil list, i.e. -     * a list containing zero fontnames. -     */ -    if (length > XLFDMAXFONTNAMELEN) -	return BadAlloc; - -    i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess); -    if (i != Success) -	return i; - -    if (!(c = xalloc(sizeof *c))) -	goto badAlloc; -    c->fpe_list = xalloc(sizeof(FontPathElementPtr) * num_fpes); -    if (!c->fpe_list) -    { -	xfree(c); -	goto badAlloc; -    } -    memmove(c->current.pattern, pattern, length); -    for (i = 0; i < num_fpes; i++) -    { -	c->fpe_list[i] = font_path_elements[i]; -	UseFPE(c->fpe_list[i]); -    } -    c->client = client; -    c->num_fpes = num_fpes; -    c->reply = 0; -    c->length = 0; -    c->current.patlen = length; -    c->current.current_fpe = 0; -    c->current.max_names = max_names; -    c->current.list_started = FALSE; -    c->current.private = 0; -    c->savedNumFonts = 0; -    c->haveSaved = FALSE; -    c->slept = FALSE; -    c->savedName = 0; -    doListFontsWithInfo(client, c); -    return Success; -badAlloc: -    return BadAlloc; -} - -#define TextEltHeader 2 -#define FontShiftSize 5 -static XID clearGC[] = { CT_NONE }; -#define clearGCmask (GCClipMask) - -int -doPolyText(ClientPtr client, PTclosurePtr c) -{ -    FontPtr pFont = c->pGC->font, oldpFont; -    Font	fid, oldfid; -    int err = Success, lgerr;	/* err is in X error, not font error, space */ -    enum { NEVER_SLEPT, START_SLEEP, SLEEPING } client_state = NEVER_SLEPT; -    FontPathElementPtr fpe; -    GC *origGC = NULL; - -    if (client->clientGone) -    { -	fpe = c->pGC->font->fpe; -	(*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); - -	if (c->slept) -	{ -	    /* Client has died, but we cannot bail out right now.  We -	       need to clean up after the work we did when going to -	       sleep.  Setting the drawable pointer to 0 makes this -	       happen without any attempts to render or perform other -	       unnecessary activities.  */ -	    c->pDraw = (DrawablePtr)0; -	} -	else -	{ -	    err = Success; -	    goto bail; -	} -    } - -    /* Make sure our drawable hasn't disappeared while we slept. */ -    if (c->slept && c->pDraw) -    { -	DrawablePtr pDraw; -	dixLookupDrawable(&pDraw, c->did, client, 0, DixWriteAccess); -	if (c->pDraw != pDraw) { -	    /* Our drawable has disappeared.  Treat like client died... ask -	       the FPE code to clean up after client and avoid further -	       rendering while we clean up after ourself.  */ -	    fpe = c->pGC->font->fpe; -	    (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); -	    c->pDraw = (DrawablePtr)0; -	} -    } - -    client_state = c->slept ? SLEEPING : NEVER_SLEPT; - -    while (c->endReq - c->pElt > TextEltHeader) -    { -	if (*c->pElt == FontChange) -        { -	    if (c->endReq - c->pElt < FontShiftSize) -	    { -		 err = BadLength; -		 goto bail; -	    } - -	    oldpFont = pFont; -	    oldfid = fid; - -	    fid =  ((Font)*(c->pElt+4))		/* big-endian */ -		 | ((Font)*(c->pElt+3)) << 8 -		 | ((Font)*(c->pElt+2)) << 16 -		 | ((Font)*(c->pElt+1)) << 24; -	    err = dixLookupResourceByType((pointer *)&pFont, fid, RT_FONT, -					  client, DixReadAccess); -	    if (err != Success) -	    { -		err = (err == BadValue) ? BadFont : err; -		/* restore pFont and fid for step 4 (described below) */ -		pFont = oldpFont; -		fid = oldfid; - -		/* If we're in START_SLEEP mode, the following step -		   shortens the request...  in the unlikely event that -		   the fid somehow becomes valid before we come through -		   again to actually execute the polytext, which would -		   then mess up our refcounting scheme badly.  */ -		c->err = err; -		c->endReq = c->pElt; - -		goto bail; -	    } - -	    /* Step 3 (described below) on our new font */ -	    if (client_state == START_SLEEP) -		pFont->refcnt++; -	    else -	    { -		if (pFont != c->pGC->font && c->pDraw) -		{ -		    ChangeGC( c->pGC, GCFont, &fid); -		    ValidateGC(c->pDraw, c->pGC); -		    if (c->reqType == X_PolyText8) -			c->polyText = (PolyTextPtr) c->pGC->ops->PolyText8; -		    else -			c->polyText = (PolyTextPtr) c->pGC->ops->PolyText16; -		} - -		/* Undo the refcnt++ we performed when going to sleep */ -		if (client_state == SLEEPING) -		    (void)CloseFont(c->pGC->font, (Font)0); -	    } -	    c->pElt += FontShiftSize; -	} -	else	/* print a string */ -	{ -	    unsigned char *pNextElt; -	    pNextElt = c->pElt + TextEltHeader + (*c->pElt)*c->itemSize; -	    if ( pNextElt > c->endReq) -	    { -		err = BadLength; -		goto bail; -	    } -	    if (client_state == START_SLEEP) -	    { -		c->pElt = pNextElt; -		continue; -	    } -	    if (c->pDraw) -	    { -		lgerr = LoadGlyphs(client, c->pGC->font, *c->pElt, c->itemSize, -				   c->pElt + TextEltHeader); -	    } -	    else lgerr = Successful; - -	    if (lgerr == Suspended) -	    { -		if (!c->slept) { -		    int len; -		    GC *pGC; -		    PTclosurePtr new_closure; - -    /*  We're putting the client to sleep.  We need to do a few things -	to ensure successful and atomic-appearing execution of the -	remainder of the request.  First, copy the remainder of the -	request into a safe malloc'd area.  Second, create a scratch GC -	to use for the remainder of the request.  Third, mark all fonts -	referenced in the remainder of the request to prevent their -	deallocation.  Fourth, make the original GC look like the -	request has completed...  set its font to the final font value -	from this request.  These GC manipulations are for the unlikely -	(but possible) event that some other client is using the GC. -	Steps 3 and 4 are performed by running this procedure through -	the remainder of the request in a special no-render mode -	indicated by client_state = START_SLEEP.  */ - -		    /* Step 1 */ -		    /* Allocate a malloc'd closure structure to replace -		       the local one we were passed */ -		    new_closure = xalloc(sizeof(PTclosureRec)); -		    if (!new_closure) -		    { -			err = BadAlloc; -			goto bail; -		    } -		    *new_closure = *c; -		    c = new_closure; - -		    len = c->endReq - c->pElt; -		    c->data = xalloc(len); -		    if (!c->data) -		    { -			xfree(c); -			err = BadAlloc; -			goto bail; -		    } -		    memmove(c->data, c->pElt, len); -		    c->pElt = c->data; -		    c->endReq = c->pElt + len; - -		    /* Step 2 */ - -		    pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen); -		    if (!pGC) -		    { -			xfree(c->data); -			xfree(c); -			err = BadAlloc; -			goto bail; -		    } -		    if ((err = CopyGC(c->pGC, pGC, GCFunction | -				      GCPlaneMask | GCForeground | -				      GCBackground | GCFillStyle | -				      GCTile | GCStipple | -				      GCTileStipXOrigin | -				      GCTileStipYOrigin | GCFont | -				      GCSubwindowMode | GCClipXOrigin | -				      GCClipYOrigin | GCClipMask)) != -				      Success) -		    { -			FreeScratchGC(pGC); -			xfree(c->data); -			xfree(c); -			err = BadAlloc; -			goto bail; -		    } -		    origGC = c->pGC; -		    c->pGC = pGC; -		    ValidateGC(c->pDraw, c->pGC); -		     -		    c->slept = TRUE; -		    ClientSleep(client, -		    	     (ClientSleepProcPtr)doPolyText, -			     (pointer) c); - -		    /* Set up to perform steps 3 and 4 */ -		    client_state = START_SLEEP; -		    continue;	/* on to steps 3 and 4 */ -		} -		return TRUE; -	    } -	    else if (lgerr != Successful) -	    { -		err = FontToXError(lgerr); -		goto bail; -	    } -	    if (c->pDraw) -	    { -		c->xorg += *((INT8 *)(c->pElt + 1));	/* must be signed */ -		c->xorg = (* c->polyText)(c->pDraw, c->pGC, c->xorg, c->yorg, -		    *c->pElt, c->pElt + TextEltHeader); -	    } -	    c->pElt = pNextElt; -	} -    } - -bail: - -    if (client_state == START_SLEEP) -    { -	/* Step 4 */ -	if (pFont != origGC->font) -	{ -	    ChangeGC(origGC, GCFont, &fid); -	    ValidateGC(c->pDraw, origGC); -	} - -	/* restore pElt pointer for execution of remainder of the request */ -	c->pElt = c->data; -	return TRUE; -    } - -    if (c->err != Success) err = c->err; -    if (err != Success && c->client != serverClient) { -#ifdef PANORAMIX -        if (noPanoramiXExtension || !c->pGC->pScreen->myNum) -#endif -	    SendErrorToClient(c->client, c->reqType, 0, 0, err); -    } -    if (c->slept) -    { -	ClientWakeup(c->client); -	ChangeGC(c->pGC, clearGCmask, clearGC); - -	/* Unreference the font from the scratch GC */ -	CloseFont(c->pGC->font, (Font)0); -	c->pGC->font = NullFont; - -	FreeScratchGC(c->pGC); -	xfree(c->data); -	xfree(c); -    } -    return TRUE; -} - -int -PolyText(ClientPtr client, DrawablePtr pDraw, GC *pGC, unsigned char *pElt,  -         unsigned char *endReq, int xorg, int yorg, int reqType, XID did) -{ -    PTclosureRec local_closure; - -    local_closure.pElt = pElt; -    local_closure.endReq = endReq; -    local_closure.client = client; -    local_closure.pDraw = pDraw; -    local_closure.xorg = xorg; -    local_closure.yorg = yorg; -    if ((local_closure.reqType = reqType) == X_PolyText8) -    { -	local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText8; -	local_closure.itemSize = 1; -    } -    else -    { -	local_closure.polyText =  (PolyTextPtr) pGC->ops->PolyText16; -	local_closure.itemSize = 2; -    } -    local_closure.pGC = pGC; -    local_closure.did = did; -    local_closure.err = Success; -    local_closure.slept = FALSE; - -    (void) doPolyText(client, &local_closure); -    return Success; -} - - -#undef TextEltHeader -#undef FontShiftSize - -int -doImageText(ClientPtr client, ITclosurePtr c) -{ -    int err = Success, lgerr;	/* err is in X error, not font error, space */ -    FontPathElementPtr fpe; - -    if (client->clientGone) -    { -	fpe = c->pGC->font->fpe; -	(*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); -	err = Success; -	goto bail; -    } - -    /* Make sure our drawable hasn't disappeared while we slept. */ -    if (c->slept && c->pDraw) -    { -	DrawablePtr pDraw; -	dixLookupDrawable(&pDraw, c->did, client, 0, DixWriteAccess); -	if (c->pDraw != pDraw) { -	    /* Our drawable has disappeared.  Treat like client died... ask -	       the FPE code to clean up after client. */ -	    fpe = c->pGC->font->fpe; -	    (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); -	    err = Success; -	    goto bail; -	} -    } - -    lgerr = LoadGlyphs(client, c->pGC->font, c->nChars, c->itemSize, c->data); -    if (lgerr == Suspended) -    { -        if (!c->slept) { -	    GC *pGC; -	    unsigned char *data; -	    ITclosurePtr new_closure; - -	    /* We're putting the client to sleep.  We need to -	       save some state.  Similar problem to that handled -	       in doPolyText, but much simpler because the -	       request structure is much simpler. */ - -	    new_closure = xalloc(sizeof(ITclosureRec)); -	    if (!new_closure) -	    { -		err = BadAlloc; -		goto bail; -	    } -	    *new_closure = *c; -	    c = new_closure; - -	    data = xalloc(c->nChars * c->itemSize); -	    if (!data) -	    { -		xfree(c); -		err = BadAlloc; -		goto bail; -	    } -	    memmove(data, c->data, c->nChars * c->itemSize); -	    c->data = data; - -	    pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen); -	    if (!pGC) -	    { -		xfree(c->data); -		xfree(c); -		err = BadAlloc; -		goto bail; -	    } -	    if ((err = CopyGC(c->pGC, pGC, GCFunction | GCPlaneMask | -			      GCForeground | GCBackground | GCFillStyle | -			      GCTile | GCStipple | GCTileStipXOrigin | -			      GCTileStipYOrigin | GCFont | -			      GCSubwindowMode | GCClipXOrigin | -			      GCClipYOrigin | GCClipMask)) != Success) -	    { -		FreeScratchGC(pGC); -		xfree(c->data); -		xfree(c); -		err = BadAlloc; -		goto bail; -	    } -	    c->pGC = pGC; -	    ValidateGC(c->pDraw, c->pGC); - -	    c->slept = TRUE; -            ClientSleep(client, (ClientSleepProcPtr)doImageText, (pointer) c); -        } -        return TRUE; -    } -    else if (lgerr != Successful) -    { -        err = FontToXError(lgerr); -        goto bail; -    } -    if (c->pDraw) -    { -	(* c->imageText)(c->pDraw, c->pGC, c->xorg, c->yorg, -	    c->nChars, c->data); -    } - -bail: - -    if (err != Success && c->client != serverClient) { -	SendErrorToClient(c->client, c->reqType, 0, 0, err); -    } -    if (c->slept) -    { -	ClientWakeup(c->client); -	ChangeGC(c->pGC, clearGCmask, clearGC); - -	/* Unreference the font from the scratch GC */ -	CloseFont(c->pGC->font, (Font)0); -	c->pGC->font = NullFont; - -	FreeScratchGC(c->pGC); -	xfree(c->data); -	xfree(c); -    } -    return TRUE; -} - -int -ImageText(ClientPtr client, DrawablePtr pDraw, GC *pGC, int nChars,  -          unsigned char *data, int xorg, int yorg, int reqType, XID did) -{ -    ITclosureRec local_closure; - -    local_closure.client = client; -    local_closure.pDraw = pDraw; -    local_closure.pGC = pGC; -    local_closure.nChars = nChars; -    local_closure.data = data; -    local_closure.xorg = xorg; -    local_closure.yorg = yorg; -    if ((local_closure.reqType = reqType) == X_ImageText8) -    { -	local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText8; -	local_closure.itemSize = 1; -    } -    else -    { -	local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText16; -	local_closure.itemSize = 2; -    } -    local_closure.did = did; -    local_closure.slept = FALSE; - -    (void) doImageText(client, &local_closure); -    return Success; -} - - -/* does the necessary magic to figure out the fpe type */ -static int -DetermineFPEType(char *pathname) -{ -    int         i; - -    for (i = 0; i < num_fpe_types; i++) { -	if ((*fpe_functions[i].name_check) (pathname)) -	    return i; -    } -    return -1; -} - - -static void -FreeFontPath(FontPathElementPtr *list, int n, Bool force) -{ -    int         i; - -    for (i = 0; i < n; i++) { -	if (force) { -	    /* Sanity check that all refcounts will be 0 by the time -	       we get to the end of the list. */ -	    int found = 1;	/* the first reference is us */ -	    int j; -	    for (j = i+1; j < n; j++) { -		if (list[j] == list[i]) -		    found++; -	    } -	    if (list[i]->refcount != found) { -		list[i]->refcount = found; /* ensure it will get freed */ -	    } -	} -	FreeFPE(list[i]); -    } -    xfree(list); -} - -static FontPathElementPtr -find_existing_fpe(FontPathElementPtr *list, int num, unsigned char *name, int len) -{ -    FontPathElementPtr fpe; -    int         i; - -    for (i = 0; i < num; i++) { -	fpe = list[i]; -	if (fpe->name_length == len && memcmp(name, fpe->name, len) == 0) -	    return fpe; -    } -    return (FontPathElementPtr) 0; -} - - -static int -SetFontPathElements(int npaths, unsigned char *paths, int *bad, Bool persist) -{ -    int         i, err = 0; -    int         valid_paths = 0; -    unsigned int len; -    unsigned char *cp = paths; -    FontPathElementPtr fpe = NULL, *fplist; - -    fplist = xalloc(sizeof(FontPathElementPtr) * npaths); -    if (!fplist) { -	*bad = 0; -	return BadAlloc; -    } -    for (i = 0; i < num_fpe_types; i++) { -	if (fpe_functions[i].set_path_hook) -	    (*fpe_functions[i].set_path_hook) (); -    } -    for (i = 0; i < npaths; i++)  -    { -	len = (unsigned int) (*cp++); - -	if (len == 0)  -	{ -	    if (persist) -		ErrorF("[dix] Removing empty element from the valid list of fontpaths\n"); -	    err = BadValue; -	} -	else -	{ -	    /* if it's already in our active list, just reset it */ -	    /* -	     * note that this can miss FPE's in limbo -- may be worth catching -	     * them, though it'd muck up refcounting -	     */ -	    fpe = find_existing_fpe(font_path_elements, num_fpes, cp, len); -	    if (fpe)  -	    { -		err = (*fpe_functions[fpe->type].reset_fpe) (fpe); -		if (err == Successful)  -		{ -		    UseFPE(fpe);/* since it'll be decref'd later when freed -				 * from the old list */ -		} -		else -		    fpe = 0; -	    } -	    /* if error or can't do it, act like it's a new one */ -	    if (!fpe) -	    { -		fpe = xalloc(sizeof(FontPathElementRec)); -		if (!fpe)  -		{ -		    err = BadAlloc; -		    goto bail; -		} -		fpe->name = xalloc(len + 1); -		if (!fpe->name)  -		{ -		    xfree(fpe); -		    err = BadAlloc; -		    goto bail; -		} -		fpe->refcount = 1; -     -		strncpy(fpe->name, (char *) cp, (int) len); -		fpe->name[len] = '\0'; -		fpe->name_length = len; -		fpe->type = DetermineFPEType(fpe->name); -		if (fpe->type == -1) -		    err = BadValue; -		else -		    err = (*fpe_functions[fpe->type].init_fpe) (fpe); -		if (err != Successful) -		{ -		    if (persist) -		    { -			ErrorF("[dix] Could not init font path element %s, removing from list!\n", -			       fpe->name); -		    } -		    xfree (fpe->name); -		    xfree (fpe); -		} -	    } -	} -	if (err != Successful) -	{ -	    if (!persist) -		goto bail; -	} -	else -	{ -	    fplist[valid_paths++] = fpe; -	} -	cp += len; -    } - -    FreeFontPath(font_path_elements, num_fpes, FALSE); -    font_path_elements = fplist; -    if (patternCache) -	EmptyFontPatternCache(patternCache); -    num_fpes = valid_paths; - -    return Success; -bail: -    *bad = i; -    while (--valid_paths >= 0) -	FreeFPE(fplist[valid_paths]); -    xfree(fplist); -    return FontToXError(err); -} - -/* XXX -- do we need to pass error down to each renderer? */ -int -SetFontPath(ClientPtr client, int npaths, unsigned char *paths, int *error) -{ -    int err = XaceHook(XACE_SERVER_ACCESS, client, DixManageAccess); -    if (err != Success) -	return err; - -    if (npaths == 0) { -	if (SetDefaultFontPath(defaultFontPath) != Success) -	    return BadValue; -    } else { -	err = SetFontPathElements(npaths, paths, error, FALSE); -    } -    return err; -} - -int -SetDefaultFontPath(char *path) -{ -    char       *temp_path, -               *start, -               *end; -    unsigned char *cp, -               *pp, -               *nump, -               *newpath; -    int         num = 1, -                len, -                err, -                size = 0, -                bad; - -    /* ensure temp_path contains "built-ins" */ -    start = path; -    while (1) { -	start = strstr(start, "built-ins"); -	if (start == NULL) -	    break; -	end = start + strlen("built-ins"); -	if ((start == path || start[-1] == ',') && (!*end || *end == ',')) -	    break; -	start = end; -    } -    if (!start) { -	temp_path = Xprintf("%s%sbuilt-ins", path, *path ? "," : ""); -    } else { -	temp_path = Xstrdup(path); -    } -    if (!temp_path) -        return BadAlloc; - -    /* get enough for string, plus values -- use up commas */ -    len = strlen(temp_path) + 1; -    nump = cp = newpath = xalloc(len); -    if (!newpath) -	return BadAlloc; -    pp = (unsigned char *) temp_path; -    cp++; -    while (*pp) { -	if (*pp == ',') { -	    *nump = (unsigned char) size; -	    nump = cp++; -	    pp++; -	    num++; -	    size = 0; -	} else { -	    *cp++ = *pp++; -	    size++; -	} -    } -    *nump = (unsigned char) size; - -    err = SetFontPathElements(num, newpath, &bad, TRUE); - -    xfree(newpath); -    xfree(temp_path); - -    return err; -} - -int -GetFontPath(ClientPtr client, int *count, int *length, unsigned char **result) -{ -    int			i; -    unsigned char       *c; -    int			len; -    FontPathElementPtr	fpe; - -    i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess); -    if (i != Success) -	return i; - -    len = 0; -    for (i = 0; i < num_fpes; i++) { -	fpe = font_path_elements[i]; -	len += fpe->name_length + 1; -    } -    font_path_string = (unsigned char *) xrealloc(font_path_string, len); -    if (!font_path_string) -	return BadAlloc; - -    c = font_path_string; -    *length = 0; -    for (i = 0; i < num_fpes; i++) { -	fpe = font_path_elements[i]; -	*c = fpe->name_length; -	*length += *c++; -	memmove(c, fpe->name, fpe->name_length); -	c += fpe->name_length; -    } -    *count = num_fpes; -    *result = font_path_string; -    return Success; -} - -void -DeleteClientFontStuff(ClientPtr client) -{ -    int			i; -    FontPathElementPtr	fpe; - -    for (i = 0; i < num_fpes; i++) -    { -	fpe = font_path_elements[i]; -	if (fpe_functions[fpe->type].client_died) -	    (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); -    } -} - -void -InitFonts (void) -{ -    patternCache = MakeFontPatternCache(); - -    BuiltinRegisterFpeFunctions(); -    FontFileRegisterFpeFunctions(); -    fs_register_fpe_functions(); -} - -int -GetDefaultPointSize (void) -{ -    return 120; -} - - -FontResolutionPtr -GetClientResolutions (int *num) -{ -    static struct _FontResolution res; -    ScreenPtr   pScreen; - -    pScreen = screenInfo.screens[0]; -    res.x_resolution = (pScreen->width * 25.4) / pScreen->mmWidth; -    /* -     * XXX - we'll want this as long as bitmap instances are prevalent  -     so that we can match them from scalable fonts -     */ -    if (res.x_resolution < 88) -	res.x_resolution = 75; -    else -	res.x_resolution = 100; -    res.y_resolution = (pScreen->height * 25.4) / pScreen->mmHeight; -    if (res.y_resolution < 88) -	res.y_resolution = 75; -    else -	res.y_resolution = 100; -    res.point_size = 120; -    *num = 1; -    return &res; -} - -/* - * returns the type index of the new fpe - * - * should be called (only once!) by each type of fpe when initialized - */ - -int -RegisterFPEFunctions(NameCheckFunc name_func,  -		     InitFpeFunc init_func,  -		     FreeFpeFunc free_func,  -		     ResetFpeFunc reset_func,  -		     OpenFontFunc open_func,  -		     CloseFontFunc close_func,  -		     ListFontsFunc list_func,  -		     StartLfwiFunc start_lfwi_func,  -		     NextLfwiFunc next_lfwi_func,  -		     WakeupFpeFunc wakeup_func,  -		     ClientDiedFunc client_died,  -		     LoadGlyphsFunc load_glyphs,  -		     StartLaFunc start_list_alias_func,  -		     NextLaFunc next_list_alias_func,  -		     SetPathFunc set_path_func) -{ -    FPEFunctions *new; - -    /* grow the list */ -    new = (FPEFunctions *) xrealloc(fpe_functions, -				 (num_fpe_types + 1) * sizeof(FPEFunctions)); -    if (!new) -	return -1; -    fpe_functions = new; - -    fpe_functions[num_fpe_types].name_check = name_func; -    fpe_functions[num_fpe_types].open_font = open_func; -    fpe_functions[num_fpe_types].close_font = close_func; -    fpe_functions[num_fpe_types].wakeup_fpe = wakeup_func; -    fpe_functions[num_fpe_types].list_fonts = list_func; -    fpe_functions[num_fpe_types].start_list_fonts_with_info = -	start_lfwi_func; -    fpe_functions[num_fpe_types].list_next_font_with_info = -	next_lfwi_func; -    fpe_functions[num_fpe_types].init_fpe = init_func; -    fpe_functions[num_fpe_types].free_fpe = free_func; -    fpe_functions[num_fpe_types].reset_fpe = reset_func; -    fpe_functions[num_fpe_types].client_died = client_died; -    fpe_functions[num_fpe_types].load_glyphs = load_glyphs; -    fpe_functions[num_fpe_types].start_list_fonts_and_aliases = -	start_list_alias_func; -    fpe_functions[num_fpe_types].list_next_font_or_alias = -	next_list_alias_func; -    fpe_functions[num_fpe_types].set_path_hook = set_path_func; - -    return num_fpe_types++; -} - -void -FreeFonts(void) -{ -    if (patternCache) { -	FreeFontPatternCache(patternCache); -	patternCache = 0; -    } -    FreeFontPath(font_path_elements, num_fpes, TRUE); -    font_path_elements = 0; -    num_fpes = 0; -    xfree(fpe_functions); -    num_fpe_types = 0; -    fpe_functions = (FPEFunctions *) 0; -} - -/* convenience functions for FS interface */ - -FontPtr -find_old_font(XID id) -{ -    pointer pFont; -    dixLookupResourceByType(&pFont, id, RT_NONE, serverClient, DixReadAccess); -    return (FontPtr)pFont; -} - -Font -GetNewFontClientID(void) -{ -    return FakeClientID(0); -} - -int -StoreFontClientFont(FontPtr pfont, Font id) -{ -    return AddResource(id, RT_NONE, (pointer) pfont); -} - -void -DeleteFontClientID(Font id) -{ -    FreeResource(id, RT_NONE); -} - -int -client_auth_generation(ClientPtr client) -{ -    return 0; -} - -static int  fs_handlers_installed = 0; -static unsigned int last_server_gen; - -int -init_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler) -{ -    /* if server has reset, make sure the b&w handlers are reinstalled */ -    if (last_server_gen < serverGeneration) { -	last_server_gen = serverGeneration; -	fs_handlers_installed = 0; -    } -    if (fs_handlers_installed == 0) { -	if (!RegisterBlockAndWakeupHandlers(block_handler, -					    FontWakeup, (pointer) 0)) -	    return AllocError; -	fs_handlers_installed++; -    } -    QueueFontWakeup(fpe); -    return Successful; -} - -void -remove_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler, Bool all) -{ -    if (all) { -	/* remove the handlers if no one else is using them */ -	if (--fs_handlers_installed == 0) { -	    RemoveBlockAndWakeupHandlers(block_handler, FontWakeup, -					 (pointer) 0); -	} -    } -    RemoveFontWakeup(fpe); -} +/************************************************************************
 +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
 +
 +                        All Rights Reserved
 +
 +Permission to use, copy, modify, and distribute this software and its
 +documentation for any purpose and without fee is hereby granted,
 +provided that the above copyright notice appear in all copies and that
 +both that copyright notice and this permission notice appear in
 +supporting documentation, and that the name of Digital not be
 +used in advertising or publicity pertaining to distribution of the
 +software without specific, written prior permission.
 +
 +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
 +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
 +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 +SOFTWARE.
 +
 +************************************************************************/
 +/* The panoramix components contained the following notice */
 +/*
 +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
 +
 +Permission is hereby granted, free of charge, to any person obtaining a copy
 +of this software and associated documentation files (the "Software"), to deal
 +in the Software without restriction, including without limitation the rights
 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 +copies of the Software.
 +
 +The above copyright notice and this permission notice shall be included in
 +all copies or substantial portions of the Software.
 +
 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
 +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
 +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
 +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 +
 +Except as contained in this notice, the name of Digital Equipment Corporation
 +shall not be used in advertising or otherwise to promote the sale, use or other
 +dealings in this Software without prior written authorization from Digital
 +Equipment Corporation.
 +
 +******************************************************************/
 +
 +#ifdef HAVE_DIX_CONFIG_H
 +#include <dix-config.h>
 +#endif
 +
 +#include <X11/X.h>
 +#include <X11/Xmd.h>
 +#include <X11/Xproto.h>
 +#include "scrnintstr.h"
 +#include "resource.h"
 +#include "dixstruct.h"
 +#include "cursorstr.h"
 +#include "misc.h"
 +#include "opaque.h"
 +#include "dixfontstr.h"
 +#include "closestr.h"
 +#include "dixfont.h"
 +#include "xace.h"
 +
 +#ifdef DEBUG
 +#include	<stdio.h>
 +#endif
 +
 +#ifdef XF86BIGFONT
 +#define _XF86BIGFONT_SERVER_
 +#include <X11/extensions/xf86bigfont.h>
 +#endif
 +
 +#define QUERYCHARINFO(pci, pr)  *(pr) = (pci)->metrics
 +
 +extern pointer fosNaturalParams;
 +extern FontPtr defaultFont;
 +
 +static FontPathElementPtr *font_path_elements = (FontPathElementPtr *) 0;
 +static int  num_fpes = 0;
 +static FPEFunctions *fpe_functions = (FPEFunctions *) 0;
 +static int  num_fpe_types = 0;
 +
 +static unsigned char *font_path_string;
 +
 +static int  num_slept_fpes = 0;
 +static int  size_slept_fpes = 0;
 +static FontPathElementPtr *slept_fpes = (FontPathElementPtr *) 0;
 +static FontPatternCachePtr patternCache;
 +
 +static int
 +FontToXError(int err)
 +{
 +    switch (err) {
 +    case Successful:
 +	return Success;
 +    case AllocError:
 +	return BadAlloc;
 +    case BadFontName:
 +	return BadName;
 +    case BadFontPath:
 +    case BadFontFormat:	/* is there something better? */
 +    case BadCharRange:
 +	return BadValue;
 +    default:
 +	return err;
 +    }
 +}
 +
 +static int
 +LoadGlyphs(ClientPtr client, FontPtr pfont, unsigned nchars, int item_size,
 +	   unsigned char *data)
 +{
 +    if (fpe_functions[pfont->fpe->type].load_glyphs)
 +	return (*fpe_functions[pfont->fpe->type].load_glyphs)
 +	    (client, pfont, 0, nchars, item_size, data);
 +    else
 +	return Successful;
 +}
 +
 +/*
 + * adding RT_FONT prevents conflict with default cursor font
 + */
 +Bool
 +SetDefaultFont(char *defaultfontname)
 +{
 +    int         err;
 +    FontPtr     pf;
 +    XID         fid;
 +    static FontPtr last_pf;
 +
 +    fid = FakeClientID(0);
 +    err = OpenFont(serverClient, fid, FontLoadAll | FontOpenSync,
 +		   (unsigned) strlen(defaultfontname), defaultfontname);
 +    if (err != Success)
 +	return FALSE;
 +    err = dixLookupResourceByType((pointer *)&pf, fid, RT_FONT, serverClient,
 +				  DixReadAccess);
 +    if (err == Success) last_pf = pf;
 +    if (last_pf == (FontPtr) NULL)
 +	return FALSE;
 +    defaultFont = last_pf;
 +    return TRUE;
 +}
 +
 +/*
 + * note that the font wakeup queue is not refcounted.  this is because
 + * an fpe needs to be added when it's inited, and removed when it's finally
 + * freed, in order to handle any data that isn't requested, like FS events.
 + *
 + * since the only thing that should call these routines is the renderer's
 + * init_fpe() and free_fpe(), there shouldn't be any problem in using
 + * freed data.
 + */
 +void
 +QueueFontWakeup(FontPathElementPtr fpe)
 +{
 +    int         i;
 +    FontPathElementPtr *new;
 +
 +    for (i = 0; i < num_slept_fpes; i++) {
 +	if (slept_fpes[i] == fpe) {
 +	    return;
 +	}
 +    }
 +    if (num_slept_fpes == size_slept_fpes) {
 +	new = (FontPathElementPtr *)
 +	    xrealloc(slept_fpes,
 +		     sizeof(FontPathElementPtr) * (size_slept_fpes + 4));
 +	if (!new)
 +	    return;
 +	slept_fpes = new;
 +	size_slept_fpes += 4;
 +    }
 +    slept_fpes[num_slept_fpes] = fpe;
 +    num_slept_fpes++;
 +}
 +
 +void
 +RemoveFontWakeup(FontPathElementPtr fpe)
 +{
 +    int         i,
 +                j;
 +
 +    for (i = 0; i < num_slept_fpes; i++) {
 +	if (slept_fpes[i] == fpe) {
 +	    for (j = i; j < num_slept_fpes; j++) {
 +		slept_fpes[j] = slept_fpes[j + 1];
 +	    }
 +	    num_slept_fpes--;
 +	    return;
 +	}
 +    }
 +}
 +
 +void
 +FontWakeup(pointer data, int count, pointer LastSelectMask)
 +{
 +    int         i;
 +    FontPathElementPtr fpe;
 +
 +    if (count < 0)
 +	return;
 +    /* wake up any fpe's that may be waiting for information */
 +    for (i = 0; i < num_slept_fpes; i++) {
 +	fpe = slept_fpes[i];
 +	(void) (*fpe_functions[fpe->type].wakeup_fpe) (fpe, LastSelectMask);
 +    }
 +}
 +
 +/* XXX -- these two funcs may want to be broken into macros */
 +static void
 +UseFPE(FontPathElementPtr fpe)
 +{
 +    fpe->refcount++;
 +}
 +
 +static void
 +FreeFPE (FontPathElementPtr fpe)
 +{
 +    fpe->refcount--;
 +    if (fpe->refcount == 0) {
 +	(*fpe_functions[fpe->type].free_fpe) (fpe);
 +	xfree(fpe->name);
 +	xfree(fpe);
 +    }
 +}
 +
 +static Bool
 +doOpenFont(ClientPtr client, OFclosurePtr c)
 +{
 +    FontPtr     pfont = NullFont;
 +    FontPathElementPtr fpe = NULL;
 +    ScreenPtr   pScr;
 +    int         err = Successful;
 +    int         i;
 +    char       *alias,
 +               *newname;
 +    int         newlen;
 +    int		aliascount = 20;
 +    /*
 +     * Decide at runtime what FontFormat to use.
 +     */
 +    Mask FontFormat = 
 +
 +	((screenInfo.imageByteOrder == LSBFirst) ?
 +	    BitmapFormatByteOrderLSB : BitmapFormatByteOrderMSB) |
 +
 +	((screenInfo.bitmapBitOrder == LSBFirst) ?
 +	    BitmapFormatBitOrderLSB : BitmapFormatBitOrderMSB) |
 +
 +	BitmapFormatImageRectMin |
 +
 +#if GLYPHPADBYTES == 1
 +	BitmapFormatScanlinePad8 |
 +#endif
 +
 +#if GLYPHPADBYTES == 2
 +	BitmapFormatScanlinePad16 |
 +#endif
 +
 +#if GLYPHPADBYTES == 4
 +	BitmapFormatScanlinePad32 |
 +#endif
 +
 +#if GLYPHPADBYTES == 8
 +	BitmapFormatScanlinePad64 |
 +#endif
 +
 +	BitmapFormatScanlineUnit8;
 +
 +    if (client->clientGone)
 +    {
 +	if (c->current_fpe < c->num_fpes)
 +	{
 +	    fpe = c->fpe_list[c->current_fpe];
 +	    (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
 +	}
 +	err = Successful;
 +	goto bail;
 +    }
 +    while (c->current_fpe < c->num_fpes) {
 +	fpe = c->fpe_list[c->current_fpe];
 +	err = (*fpe_functions[fpe->type].open_font)
 +	    ((pointer) client, fpe, c->flags,
 +	     c->fontname, c->fnamelen, FontFormat,
 +	     BitmapFormatMaskByte |
 +	     BitmapFormatMaskBit |
 +	     BitmapFormatMaskImageRectangle |
 +	     BitmapFormatMaskScanLinePad |
 +	     BitmapFormatMaskScanLineUnit,
 +	     c->fontid, &pfont, &alias,
 +	     c->non_cachable_font && c->non_cachable_font->fpe == fpe ?
 +		 c->non_cachable_font :
 +		 (FontPtr)0);
 +
 +	if (err == FontNameAlias && alias) {
 +	    newlen = strlen(alias);
 +	    newname = (char *) xrealloc(c->fontname, newlen);
 +	    if (!newname) {
 +		err = AllocError;
 +		break;
 +	    }
 +	    memmove(newname, alias, newlen);
 +	    c->fontname = newname;
 +	    c->fnamelen = newlen;
 +	    c->current_fpe = 0;
 +	    if (--aliascount <= 0) {
 +		/* We've tried resolving this alias 20 times, we're
 + 		 * probably stuck in an infinite loop of aliases pointing
 + 		 * to each other - time to take emergency exit!
 + 		 */
 + 		err = BadImplementation;
 +		break;
 +	    }
 +	    continue;
 +	}
 +	if (err == BadFontName) {
 +	    c->current_fpe++;
 +	    continue;
 +	}
 +	if (err == Suspended) {
 +	    if (!c->slept) {
 +		c->slept = TRUE;
 +		ClientSleep(client, (ClientSleepProcPtr)doOpenFont, (pointer) c);
 +	    }
 +	    return TRUE;
 +	}
 +	break;
 +    }
 +
 +    if (err != Successful)
 +	goto bail;
 +    if (!pfont) {
 +	err = BadFontName;
 +	goto bail;
 +    }
 +    /* check values for firstCol, lastCol, firstRow, and lastRow */
 +    if (pfont->info.firstCol > pfont->info.lastCol ||
 +       pfont->info.firstRow > pfont->info.lastRow ||
 +       pfont->info.lastCol - pfont->info.firstCol > 255) {
 +       err = AllocError;
 +       goto bail;
 +    }
 +    if (!pfont->fpe)
 +	pfont->fpe = fpe;
 +    pfont->refcnt++;
 +    if (pfont->refcnt == 1) {
 +	UseFPE(pfont->fpe);
 +	for (i = 0; i < screenInfo.numScreens; i++) {
 +	    pScr = screenInfo.screens[i];
 +	    if (pScr->RealizeFont)
 +	    {
 +		if (!(*pScr->RealizeFont) (pScr, pfont))
 +		{
 +		    CloseFont (pfont, (Font) 0);
 +		    err = AllocError;
 +		    goto bail;
 +		}
 +	    }
 +	}
 +    }
 +    if (!AddResource(c->fontid, RT_FONT, (pointer) pfont)) {
 +	err = AllocError;
 +	goto bail;
 +    }
 +    if (patternCache && pfont != c->non_cachable_font)
 +	CacheFontPattern(patternCache, c->origFontName, c->origFontNameLen,
 +			 pfont);
 +bail:
 +    if (err != Successful && c->client != serverClient) {
 +	SendErrorToClient(c->client, X_OpenFont, 0,
 +			  c->fontid, FontToXError(err));
 +    }
 +    if (c->slept)
 +	ClientWakeup(c->client);
 +    for (i = 0; i < c->num_fpes; i++) {
 +	FreeFPE(c->fpe_list[i]);
 +    }
 +    xfree(c->fpe_list);
 +    xfree(c->fontname);
 +    xfree(c);
 +    return TRUE;
 +}
 +
 +int
 +OpenFont(ClientPtr client, XID fid, Mask flags, unsigned lenfname, char *pfontname)
 +{
 +    OFclosurePtr c;
 +    int         i;
 +    FontPtr     cached = (FontPtr)0;
 +
 +#ifdef FONTDEBUG
 +    char *f;
 +    f = xalloc(lenfname + 1);
 +    memmove(f, pfontname, lenfname);
 +    f[lenfname] = '\0';
 +    ErrorF("[dix] OpenFont: fontname is \"%s\"\n", f);
 +    xfree(f);
 +#endif
 +    if (!lenfname || lenfname > XLFDMAXFONTNAMELEN)
 +	return BadName;
 +    if (patternCache)
 +    {
 +
 +    /*
 +    ** Check name cache.  If we find a cached version of this font that
 +    ** is cachable, immediately satisfy the request with it.  If we find
 +    ** a cached version of this font that is non-cachable, we do not
 +    ** satisfy the request with it.  Instead, we pass the FontPtr to the
 +    ** FPE's open_font code (the fontfile FPE in turn passes the
 +    ** information to the rasterizer; the fserve FPE ignores it).
 +    **
 +    ** Presumably, the font is marked non-cachable because the FPE has
 +    ** put some licensing restrictions on it.  If the FPE, using
 +    ** whatever logic it relies on, determines that it is willing to
 +    ** share this existing font with the client, then it has the option
 +    ** to return the FontPtr we passed it as the newly-opened font.
 +    ** This allows the FPE to exercise its licensing logic without
 +    ** having to create another instance of a font that already exists.
 +    */
 +
 +	cached = FindCachedFontPattern(patternCache, pfontname, lenfname);
 +	if (cached && cached->info.cachable)
 +	{
 +	    if (!AddResource(fid, RT_FONT, (pointer) cached))
 +		return BadAlloc;
 +	    cached->refcnt++;
 +	    return Success;
 +	}
 +    }
 +    c = xalloc(sizeof(OFclosureRec));
 +    if (!c)
 +	return BadAlloc;
 +    c->fontname = xalloc(lenfname);
 +    c->origFontName = pfontname;
 +    c->origFontNameLen = lenfname;
 +    if (!c->fontname) {
 +	xfree(c);
 +	return BadAlloc;
 +    }
 +    /*
 +     * copy the current FPE list, so that if it gets changed by another client
 +     * while we're blocking, the request still appears atomic
 +     */
 +    c->fpe_list = xalloc(sizeof(FontPathElementPtr) * num_fpes);
 +    if (!c->fpe_list) {
 +	xfree(c->fontname);
 +	xfree(c);
 +	return BadAlloc;
 +    }
 +    memmove(c->fontname, pfontname, lenfname);
 +    for (i = 0; i < num_fpes; i++) {
 +	c->fpe_list[i] = font_path_elements[i];
 +	UseFPE(c->fpe_list[i]);
 +    }
 +    c->client = client;
 +    c->fontid = fid;
 +    c->current_fpe = 0;
 +    c->num_fpes = num_fpes;
 +    c->fnamelen = lenfname;
 +    c->slept = FALSE;
 +    c->flags = flags;
 +    c->non_cachable_font = cached;
 +
 +    (void) doOpenFont(client, c);
 +    return Success;
 +}
 +
 +/**
 + * Decrement font's ref count, and free storage if ref count equals zero
 + *
 + *  \param value must conform to DeleteType
 + */
 +int
 +CloseFont(pointer value, XID fid)
 +{
 +    int         nscr;
 +    ScreenPtr   pscr;
 +    FontPathElementPtr fpe;
 +    FontPtr     pfont = (FontPtr)value;
 +
 +    if (pfont == NullFont)
 +	return (Success);
 +    if (--pfont->refcnt == 0) {
 +	if (patternCache)
 +	    RemoveCachedFontPattern (patternCache, pfont);
 +	/*
 +	 * since the last reference is gone, ask each screen to free any
 +	 * storage it may have allocated locally for it.
 +	 */
 +	for (nscr = 0; nscr < screenInfo.numScreens; nscr++) {
 +	    pscr = screenInfo.screens[nscr];
 +	    if (pscr->UnrealizeFont)
 +		(*pscr->UnrealizeFont) (pscr, pfont);
 +	}
 +	if (pfont == defaultFont)
 +	    defaultFont = NULL;
 +#ifdef XF86BIGFONT
 +	XF86BigfontFreeFontShm(pfont);
 +#endif
 +	fpe = pfont->fpe;
 +	(*fpe_functions[fpe->type].close_font) (fpe, pfont);
 +	FreeFPE(fpe);
 +    }
 +    return (Success);
 +}
 +
 +
 +/***====================================================================***/
 +
 +/**
 + * Sets up pReply as the correct QueryFontReply for pFont with the first
 + * nProtoCCIStructs char infos.
 + *
 + *  \param pReply caller must allocate this storage
 +  */
 +void
 +QueryFont(FontPtr pFont, xQueryFontReply *pReply, int nProtoCCIStructs)
 +{
 +    FontPropPtr      pFP;
 +    int              r,
 +                     c,
 +                     i;
 +    xFontProp       *prFP;
 +    xCharInfo       *prCI;
 +    xCharInfo       *charInfos[256];
 +    unsigned char    chars[512];
 +    int              ninfos;
 +    unsigned long    ncols;
 +    unsigned long    count;
 +
 +    /* pr->length set in dispatch */
 +    pReply->minCharOrByte2 = pFont->info.firstCol;
 +    pReply->defaultChar = pFont->info.defaultCh;
 +    pReply->maxCharOrByte2 = pFont->info.lastCol;
 +    pReply->drawDirection = pFont->info.drawDirection;
 +    pReply->allCharsExist = pFont->info.allExist;
 +    pReply->minByte1 = pFont->info.firstRow;
 +    pReply->maxByte1 = pFont->info.lastRow;
 +    pReply->fontAscent = pFont->info.fontAscent;
 +    pReply->fontDescent = pFont->info.fontDescent;
 +
 +    pReply->minBounds = pFont->info.ink_minbounds;
 +    pReply->maxBounds = pFont->info.ink_maxbounds;
 +
 +    pReply->nFontProps = pFont->info.nprops;
 +    pReply->nCharInfos = nProtoCCIStructs;
 +
 +    for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) (&pReply[1]);
 +	    i < pFont->info.nprops;
 +	    i++, pFP++, prFP++) {
 +	prFP->name = pFP->name;
 +	prFP->value = pFP->value;
 +    }
 +
 +    ninfos = 0;
 +    ncols = (unsigned long) (pFont->info.lastCol - pFont->info.firstCol + 1);
 +    prCI = (xCharInfo *) (prFP);
 +    for (r = pFont->info.firstRow;
 +	    ninfos < nProtoCCIStructs && r <= (int)pFont->info.lastRow;
 +	    r++) {
 +	i = 0;
 +	for (c = pFont->info.firstCol; c <= (int)pFont->info.lastCol; c++) {
 +	    chars[i++] = r;
 +	    chars[i++] = c;
 +	}
 +	(*pFont->get_metrics) (pFont, ncols, chars, 
 +				TwoD16Bit, &count, charInfos);
 +	i = 0;
 +	for (i = 0; i < (int) count && ninfos < nProtoCCIStructs; i++) {
 +	    *prCI = *charInfos[i];
 +	    prCI++;
 +	    ninfos++;
 +	}
 +    }
 +    return;
 +}
 +
 +static Bool
 +doListFontsAndAliases(ClientPtr client, LFclosurePtr c)
 +{
 +    FontPathElementPtr fpe;
 +    int         err = Successful;
 +    FontNamesPtr names = NULL;
 +    char       *name, *resolved=NULL;
 +    int         namelen, resolvedlen;
 +    int		nnames;
 +    int         stringLens;
 +    int         i;
 +    xListFontsReply reply;
 +    char	*bufptr;
 +    char	*bufferStart;
 +    int		aliascount = 0;
 +
 +    if (client->clientGone)
 +    {
 +	if (c->current.current_fpe < c->num_fpes)
 +	{
 +	    fpe = c->fpe_list[c->current.current_fpe];
 +	    (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
 +	}
 +	err = Successful;
 +	goto bail;
 +    }
 +
 +    if (!c->current.patlen)
 +	goto finish;
 +
 +    while (c->current.current_fpe < c->num_fpes) {
 +	fpe = c->fpe_list[c->current.current_fpe];
 +	err = Successful;
 +
 +	if (!fpe_functions[fpe->type].start_list_fonts_and_aliases)
 +	{
 +	    /* This FPE doesn't support/require list_fonts_and_aliases */
 +
 +	    err = (*fpe_functions[fpe->type].list_fonts)
 +		((pointer) c->client, fpe, c->current.pattern,
 +		 c->current.patlen, c->current.max_names - c->names->nnames,
 +		 c->names);
 +
 +	    if (err == Suspended) {
 +		if (!c->slept) {
 +		    c->slept = TRUE;
 +		    ClientSleep(client,
 +			(ClientSleepProcPtr)doListFontsAndAliases,
 +			(pointer) c);
 +		}
 +		return TRUE;
 +	    }
 +
 +	    err = BadFontName;
 +	}
 +	else
 +	{
 +	    /* Start of list_fonts_and_aliases functionality.  Modeled
 +	       after list_fonts_with_info in that it resolves aliases,
 +	       except that the information collected from FPEs is just
 +	       names, not font info.  Each list_next_font_or_alias()
 +	       returns either a name into name/namelen or an alias into
 +	       name/namelen and its target name into resolved/resolvedlen.
 +	       The code at this level then resolves the alias by polling
 +	       the FPEs.  */
 +
 +	    if (!c->current.list_started) {
 +		err = (*fpe_functions[fpe->type].start_list_fonts_and_aliases)
 +		    ((pointer) c->client, fpe, c->current.pattern,
 +		     c->current.patlen, c->current.max_names - c->names->nnames,
 +		     &c->current.private);
 +		if (err == Suspended) {
 +		    if (!c->slept) {
 +			ClientSleep(client,
 +				    (ClientSleepProcPtr)doListFontsAndAliases,
 +				    (pointer) c);
 +			c->slept = TRUE;
 +		    }
 +		    return TRUE;
 +		}
 +		if (err == Successful)
 +		    c->current.list_started = TRUE;
 +	    }
 +	    if (err == Successful) {
 +		char    *tmpname;
 +		name = 0;
 +		err = (*fpe_functions[fpe->type].list_next_font_or_alias)
 +		    ((pointer) c->client, fpe, &name, &namelen, &tmpname,
 +		     &resolvedlen, c->current.private);
 +		if (err == Suspended) {
 +		    if (!c->slept) {
 +			ClientSleep(client,
 +				    (ClientSleepProcPtr)doListFontsAndAliases,
 +				    (pointer) c);
 +			c->slept = TRUE;
 +		    }
 +		    return TRUE;
 +		}
 +		if (err == FontNameAlias) {
 +		    if (resolved) xfree(resolved);
 +		    resolved = xalloc(resolvedlen + 1);
 +		    if (resolved)
 +			memmove(resolved, tmpname, resolvedlen + 1);
 +		}
 +	    }
 +
 +	    if (err == Successful)
 +	    {
 +		if (c->haveSaved)
 +		{
 +		    if (c->savedName)
 +			(void)AddFontNamesName(c->names, c->savedName,
 +					       c->savedNameLen);
 +		}
 +		else
 +		    (void)AddFontNamesName(c->names, name, namelen);
 +	    }
 +
 +	    /*
 +	     * When we get an alias back, save our state and reset back to
 +	     * the start of the FPE looking for the specified name.  As
 +	     * soon as a real font is found for the alias, pop back to the
 +	     * old state
 +	     */
 +	    else if (err == FontNameAlias) {
 +		char	tmp_pattern[XLFDMAXFONTNAMELEN];
 +		/*
 +		 * when an alias recurses, we need to give
 +		 * the last FPE a chance to clean up; so we call
 +		 * it again, and assume that the error returned
 +		 * is BadFontName, indicating the alias resolution
 +		 * is complete.
 +		 */
 +		memmove(tmp_pattern, resolved, resolvedlen);
 +		if (c->haveSaved)
 +		{
 +		    char    *tmpname;
 +		    int     tmpnamelen;
 +
 +		    tmpname = 0;
 +		    (void) (*fpe_functions[fpe->type].list_next_font_or_alias)
 +			((pointer) c->client, fpe, &tmpname, &tmpnamelen,
 +			 &tmpname, &tmpnamelen, c->current.private);
 +		    if (--aliascount <= 0)
 +		    {
 +			err = BadFontName;
 +			goto ContBadFontName;
 +		    }
 +		}
 +		else
 +		{
 +		    c->saved = c->current;
 +		    c->haveSaved = TRUE;
 +		    if (c->savedName)
 +			xfree(c->savedName);
 +		    c->savedName = xalloc(namelen + 1);
 +		    if (c->savedName)
 +			memmove(c->savedName, name, namelen + 1);
 +		    c->savedNameLen = namelen;
 +		    aliascount = 20;
 +		}
 +		memmove(c->current.pattern, tmp_pattern, resolvedlen);
 +		c->current.patlen = resolvedlen;
 +		c->current.max_names = c->names->nnames + 1;
 +		c->current.current_fpe = -1;
 +		c->current.private = 0;
 +		err = BadFontName;
 +	    }
 +	}
 +	/*
 +	 * At the end of this FPE, step to the next.  If we've finished
 +	 * processing an alias, pop state back. If we've collected enough
 +	 * font names, quit.
 +	 */
 +	if (err == BadFontName) {
 +	  ContBadFontName: ;
 +	    c->current.list_started = FALSE;
 +	    c->current.current_fpe++;
 +	    err = Successful;
 +	    if (c->haveSaved)
 +	    {
 +		if (c->names->nnames == c->current.max_names ||
 +			c->current.current_fpe == c->num_fpes) {
 +		    c->haveSaved = FALSE;
 +		    c->current = c->saved;
 +		    /* Give the saved namelist a chance to clean itself up */
 +		    continue;
 +		}
 +	    }
 +	    if (c->names->nnames == c->current.max_names)
 +		break;
 +	}
 +    }
 +
 +    /*
 +     * send the reply
 +     */
 +    if (err != Successful) {
 +	SendErrorToClient(client, X_ListFonts, 0, 0, FontToXError(err));
 +	goto bail;
 +    }
 +
 +finish:
 +
 +    names = c->names;
 +    nnames = names->nnames;
 +    client = c->client;
 +    stringLens = 0;
 +    for (i = 0; i < nnames; i++)
 +	stringLens += (names->length[i] <= 255) ? names->length[i] : 0;
 +
 +    memset(&reply, 0, sizeof(xListFontsReply));
 +    reply.type = X_Reply;
 +    reply.length = bytes_to_int32(stringLens + nnames);
 +    reply.nFonts = nnames;
 +    reply.sequenceNumber = client->sequence;
 +
 +    bufptr = bufferStart = xalloc(reply.length << 2);
 +
 +    if (!bufptr && reply.length) {
 +	SendErrorToClient(client, X_ListFonts, 0, 0, BadAlloc);
 +	goto bail;
 +    }
 +    /*
 +     * since WriteToClient long word aligns things, copy to temp buffer and
 +     * write all at once
 +     */
 +    for (i = 0; i < nnames; i++) {
 +	if (names->length[i] > 255)
 +	    reply.nFonts--;
 +	else
 +	{
 +	    *bufptr++ = names->length[i];
 +	    memmove( bufptr, names->names[i], names->length[i]);
 +	    bufptr += names->length[i];
 +	}
 +    }
 +    nnames = reply.nFonts;
 +    reply.length = bytes_to_int32(stringLens + nnames);
 +    client->pSwapReplyFunc = ReplySwapVector[X_ListFonts];
 +    WriteSwappedDataToClient(client, sizeof(xListFontsReply), &reply);
 +    (void) WriteToClient(client, stringLens + nnames, bufferStart);
 +    xfree(bufferStart);
 +
 +bail:
 +    if (c->slept)
 +	ClientWakeup(client);
 +    for (i = 0; i < c->num_fpes; i++)
 +	FreeFPE(c->fpe_list[i]);
 +    xfree(c->fpe_list);
 +    if (c->savedName) xfree(c->savedName);
 +    FreeFontNames(names);
 +    xfree(c);
 +    if (resolved) xfree(resolved);
 +    return TRUE;
 +}
 +
 +int
 +ListFonts(ClientPtr client, unsigned char *pattern, unsigned length, 
 +          unsigned max_names)
 +{
 +    int         i;
 +    LFclosurePtr c;
 +
 +    /* 
 +     * The right error to return here would be BadName, however the
 +     * specification does not allow for a Name error on this request.
 +     * Perhaps a better solution would be to return a nil list, i.e.
 +     * a list containing zero fontnames.
 +     */
 +    if (length > XLFDMAXFONTNAMELEN)
 +	return BadAlloc;
 +
 +    i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess);
 +    if (i != Success)
 +	return i;
 +
 +    if (!(c = xalloc(sizeof *c)))
 +	return BadAlloc;
 +    c->fpe_list = xalloc(sizeof(FontPathElementPtr) * num_fpes);
 +    if (!c->fpe_list) {
 +	xfree(c);
 +	return BadAlloc;
 +    }
 +    c->names = MakeFontNamesRecord(max_names < 100 ? max_names : 100);
 +    if (!c->names)
 +    {
 +	xfree(c->fpe_list);
 +	xfree(c);
 +	return BadAlloc;
 +    }
 +    memmove( c->current.pattern, pattern, length);
 +    for (i = 0; i < num_fpes; i++) {
 +	c->fpe_list[i] = font_path_elements[i];
 +	UseFPE(c->fpe_list[i]);
 +    }
 +    c->client = client;
 +    c->num_fpes = num_fpes;
 +    c->current.patlen = length;
 +    c->current.current_fpe = 0;
 +    c->current.max_names = max_names;
 +    c->current.list_started = FALSE;
 +    c->current.private = 0;
 +    c->haveSaved = FALSE;
 +    c->slept = FALSE;
 +    c->savedName = 0;
 +    doListFontsAndAliases(client, c);
 +    return Success;
 +}
 +
 +int
 +doListFontsWithInfo(ClientPtr client, LFWIclosurePtr c)
 +{
 +    FontPathElementPtr fpe;
 +    int         err = Successful;
 +    char       *name;
 +    int         namelen;
 +    int         numFonts;
 +    FontInfoRec fontInfo,
 +               *pFontInfo;
 +    xListFontsWithInfoReply *reply;
 +    int         length;
 +    xFontProp  *pFP;
 +    int         i;
 +    int		aliascount = 0;
 +    xListFontsWithInfoReply finalReply;
 +
 +    if (client->clientGone)
 +    {
 +	if (c->current.current_fpe < c->num_fpes)
 + 	{
 +	    fpe = c->fpe_list[c->current.current_fpe];
 +	    (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
 +	}
 +	err = Successful;
 +	goto bail;
 +    }
 +    client->pSwapReplyFunc = ReplySwapVector[X_ListFontsWithInfo];
 +    if (!c->current.patlen)
 +	goto finish;
 +    while (c->current.current_fpe < c->num_fpes)
 +    {
 +	fpe = c->fpe_list[c->current.current_fpe];
 +	err = Successful;
 +	if (!c->current.list_started)
 + 	{
 +	    err = (*fpe_functions[fpe->type].start_list_fonts_with_info)
 +		(client, fpe, c->current.pattern, c->current.patlen,
 +		 c->current.max_names, &c->current.private);
 +	    if (err == Suspended)
 + 	    {
 +		if (!c->slept)
 + 		{
 +		    ClientSleep(client, (ClientSleepProcPtr)doListFontsWithInfo, c);
 +		    c->slept = TRUE;
 +		}
 +		return TRUE;
 +	    }
 +	    if (err == Successful)
 +		c->current.list_started = TRUE;
 +	}
 +	if (err == Successful)
 + 	{
 +	    name = 0;
 +	    pFontInfo = &fontInfo;
 +	    err = (*fpe_functions[fpe->type].list_next_font_with_info)
 +		(client, fpe, &name, &namelen, &pFontInfo,
 +		 &numFonts, c->current.private);
 +	    if (err == Suspended)
 + 	    {
 +		if (!c->slept)
 + 		{
 +		    ClientSleep(client,
 +		    	     (ClientSleepProcPtr)doListFontsWithInfo,
 +			     c);
 +		    c->slept = TRUE;
 +		}
 +		return TRUE;
 +	    }
 +	}
 +	/*
 +	 * When we get an alias back, save our state and reset back to the
 +	 * start of the FPE looking for the specified name.  As soon as a real
 +	 * font is found for the alias, pop back to the old state
 +	 */
 +	if (err == FontNameAlias)
 + 	{
 +	    /*
 +	     * when an alias recurses, we need to give
 +	     * the last FPE a chance to clean up; so we call
 +	     * it again, and assume that the error returned
 +	     * is BadFontName, indicating the alias resolution
 +	     * is complete.
 +	     */
 +	    if (c->haveSaved)
 +	    {
 +		char	*tmpname;
 +		int	tmpnamelen;
 +		FontInfoPtr tmpFontInfo;
 +
 +	    	tmpname = 0;
 +	    	tmpFontInfo = &fontInfo;
 +	    	(void) (*fpe_functions[fpe->type].list_next_font_with_info)
 +		    (client, fpe, &tmpname, &tmpnamelen, &tmpFontInfo,
 +		     &numFonts, c->current.private);
 +		if (--aliascount <= 0)
 +		{
 +		    err = BadFontName;
 +		    goto ContBadFontName;
 +		}
 +	    }
 +	    else
 +	    {
 +		c->saved = c->current;
 +		c->haveSaved = TRUE;
 +		c->savedNumFonts = numFonts;
 +		if (c->savedName)
 +		  xfree(c->savedName);
 +		c->savedName = xalloc(namelen + 1);
 +		if (c->savedName)
 +		  memmove(c->savedName, name, namelen + 1);
 +		aliascount = 20;
 +	    }
 +	    memmove(c->current.pattern, name, namelen);
 +	    c->current.patlen = namelen;
 +	    c->current.max_names = 1;
 +	    c->current.current_fpe = 0;
 +	    c->current.private = 0;
 +	    c->current.list_started = FALSE;
 +	}
 +	/*
 +	 * At the end of this FPE, step to the next.  If we've finished
 +	 * processing an alias, pop state back.  If we've sent enough font
 +	 * names, quit.  Always wait for BadFontName to let the FPE
 +	 * have a chance to clean up.
 +	 */
 +	else if (err == BadFontName)
 + 	{
 +	  ContBadFontName: ;
 +	    c->current.list_started = FALSE;
 +	    c->current.current_fpe++;
 +	    err = Successful;
 +	    if (c->haveSaved)
 + 	    {
 +		if (c->current.max_names == 0 ||
 +			c->current.current_fpe == c->num_fpes)
 + 		{
 +		    c->haveSaved = FALSE;
 +		    c->saved.max_names -= (1 - c->current.max_names);
 +		    c->current = c->saved;
 +		}
 +	    }
 +	    else if (c->current.max_names == 0)
 +		break;
 +	}
 + 	else if (err == Successful)
 + 	{
 +	    length = sizeof(*reply) + pFontInfo->nprops * sizeof(xFontProp);
 +	    reply = c->reply;
 +	    if (c->length < length)
 + 	    {
 +		reply = (xListFontsWithInfoReply *) xrealloc(c->reply, length);
 +		if (!reply)
 + 		{
 +		    err = AllocError;
 +		    break;
 +		}
 +		memset((char*)reply + c->length, 0, length - c->length);
 +		c->reply = reply;
 +		c->length = length;
 +	    }
 +	    if (c->haveSaved)
 + 	    {
 +		numFonts = c->savedNumFonts;
 +		name = c->savedName;
 +		namelen = strlen(name);
 +	    }
 +	    reply->type = X_Reply;
 +	    reply->length = bytes_to_int32(sizeof *reply - sizeof(xGenericReply) +
 +			     pFontInfo->nprops * sizeof(xFontProp) +
 +			     namelen);
 +	    reply->sequenceNumber = client->sequence;
 +	    reply->nameLength = namelen;
 +	    reply->minBounds = pFontInfo->ink_minbounds;
 +	    reply->maxBounds = pFontInfo->ink_maxbounds;
 +	    reply->minCharOrByte2 = pFontInfo->firstCol;
 +	    reply->maxCharOrByte2 = pFontInfo->lastCol;
 +	    reply->defaultChar = pFontInfo->defaultCh;
 +	    reply->nFontProps = pFontInfo->nprops;
 +	    reply->drawDirection = pFontInfo->drawDirection;
 +	    reply->minByte1 = pFontInfo->firstRow;
 +	    reply->maxByte1 = pFontInfo->lastRow;
 +	    reply->allCharsExist = pFontInfo->allExist;
 +	    reply->fontAscent = pFontInfo->fontAscent;
 +	    reply->fontDescent = pFontInfo->fontDescent;
 +	    reply->nReplies = numFonts;
 +	    pFP = (xFontProp *) (reply + 1);
 +	    for (i = 0; i < pFontInfo->nprops; i++)
 + 	    {
 +		pFP->name = pFontInfo->props[i].name;
 +		pFP->value = pFontInfo->props[i].value;
 +		pFP++;
 +	    }
 +	    WriteSwappedDataToClient(client, length, reply);
 +	    (void) WriteToClient(client, namelen, name);
 +	    if (pFontInfo == &fontInfo)
 + 	    {
 +		xfree(fontInfo.props);
 +		xfree(fontInfo.isStringProp);
 +	    }
 +	    --c->current.max_names;
 +	}
 +    }
 +finish:
 +    length = sizeof(xListFontsWithInfoReply);
 +    bzero((char *) &finalReply, sizeof(xListFontsWithInfoReply));
 +    finalReply.type = X_Reply;
 +    finalReply.sequenceNumber = client->sequence;
 +    finalReply.length = bytes_to_int32(sizeof(xListFontsWithInfoReply)
 +		     - sizeof(xGenericReply));
 +    WriteSwappedDataToClient(client, length, &finalReply);
 +bail:
 +    if (c->slept)
 +	ClientWakeup(client);
 +    for (i = 0; i < c->num_fpes; i++)
 +	FreeFPE(c->fpe_list[i]);
 +    xfree(c->reply);
 +    xfree(c->fpe_list);
 +    if (c->savedName) xfree(c->savedName);
 +    xfree(c);
 +    return TRUE;
 +}
 +
 +int
 +StartListFontsWithInfo(ClientPtr client, int length, unsigned char *pattern, 
 +                       int max_names)
 +{
 +    int		    i;
 +    LFWIclosurePtr  c;
 +
 +    /* 
 +     * The right error to return here would be BadName, however the
 +     * specification does not allow for a Name error on this request.
 +     * Perhaps a better solution would be to return a nil list, i.e.
 +     * a list containing zero fontnames.
 +     */
 +    if (length > XLFDMAXFONTNAMELEN)
 +	return BadAlloc;
 +
 +    i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess);
 +    if (i != Success)
 +	return i;
 +
 +    if (!(c = xalloc(sizeof *c)))
 +	goto badAlloc;
 +    c->fpe_list = xalloc(sizeof(FontPathElementPtr) * num_fpes);
 +    if (!c->fpe_list)
 +    {
 +	xfree(c);
 +	goto badAlloc;
 +    }
 +    memmove(c->current.pattern, pattern, length);
 +    for (i = 0; i < num_fpes; i++)
 +    {
 +	c->fpe_list[i] = font_path_elements[i];
 +	UseFPE(c->fpe_list[i]);
 +    }
 +    c->client = client;
 +    c->num_fpes = num_fpes;
 +    c->reply = 0;
 +    c->length = 0;
 +    c->current.patlen = length;
 +    c->current.current_fpe = 0;
 +    c->current.max_names = max_names;
 +    c->current.list_started = FALSE;
 +    c->current.private = 0;
 +    c->savedNumFonts = 0;
 +    c->haveSaved = FALSE;
 +    c->slept = FALSE;
 +    c->savedName = 0;
 +    doListFontsWithInfo(client, c);
 +    return Success;
 +badAlloc:
 +    return BadAlloc;
 +}
 +
 +#define TextEltHeader 2
 +#define FontShiftSize 5
 +static XID clearGC[] = { CT_NONE };
 +#define clearGCmask (GCClipMask)
 +
 +int
 +doPolyText(ClientPtr client, PTclosurePtr c)
 +{
 +    FontPtr pFont = c->pGC->font, oldpFont;
 +    Font	fid, oldfid;
 +    int err = Success, lgerr;	/* err is in X error, not font error, space */
 +    enum { NEVER_SLEPT, START_SLEEP, SLEEPING } client_state = NEVER_SLEPT;
 +    FontPathElementPtr fpe;
 +    GC *origGC = NULL;
 +
 +    if (client->clientGone)
 +    {
 +	fpe = c->pGC->font->fpe;
 +	(*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
 +
 +	if (c->slept)
 +	{
 +	    /* Client has died, but we cannot bail out right now.  We
 +	       need to clean up after the work we did when going to
 +	       sleep.  Setting the drawable pointer to 0 makes this
 +	       happen without any attempts to render or perform other
 +	       unnecessary activities.  */
 +	    c->pDraw = (DrawablePtr)0;
 +	}
 +	else
 +	{
 +	    err = Success;
 +	    goto bail;
 +	}
 +    }
 +
 +    /* Make sure our drawable hasn't disappeared while we slept. */
 +    if (c->slept && c->pDraw)
 +    {
 +	DrawablePtr pDraw;
 +	dixLookupDrawable(&pDraw, c->did, client, 0, DixWriteAccess);
 +	if (c->pDraw != pDraw) {
 +	    /* Our drawable has disappeared.  Treat like client died... ask
 +	       the FPE code to clean up after client and avoid further
 +	       rendering while we clean up after ourself.  */
 +	    fpe = c->pGC->font->fpe;
 +	    (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
 +	    c->pDraw = (DrawablePtr)0;
 +	}
 +    }
 +
 +    client_state = c->slept ? SLEEPING : NEVER_SLEPT;
 +
 +    while (c->endReq - c->pElt > TextEltHeader)
 +    {
 +	if (*c->pElt == FontChange)
 +        {
 +	    if (c->endReq - c->pElt < FontShiftSize)
 +	    {
 +		 err = BadLength;
 +		 goto bail;
 +	    }
 +
 +	    oldpFont = pFont;
 +	    oldfid = fid;
 +
 +	    fid =  ((Font)*(c->pElt+4))		/* big-endian */
 +		 | ((Font)*(c->pElt+3)) << 8
 +		 | ((Font)*(c->pElt+2)) << 16
 +		 | ((Font)*(c->pElt+1)) << 24;
 +	    err = dixLookupResourceByType((pointer *)&pFont, fid, RT_FONT,
 +					  client, DixReadAccess);
 +	    if (err != Success)
 +	    {
 +		err = (err == BadValue) ? BadFont : err;
 +		/* restore pFont and fid for step 4 (described below) */
 +		pFont = oldpFont;
 +		fid = oldfid;
 +
 +		/* If we're in START_SLEEP mode, the following step
 +		   shortens the request...  in the unlikely event that
 +		   the fid somehow becomes valid before we come through
 +		   again to actually execute the polytext, which would
 +		   then mess up our refcounting scheme badly.  */
 +		c->err = err;
 +		c->endReq = c->pElt;
 +
 +		goto bail;
 +	    }
 +
 +	    /* Step 3 (described below) on our new font */
 +	    if (client_state == START_SLEEP)
 +		pFont->refcnt++;
 +	    else
 +	    {
 +		if (pFont != c->pGC->font && c->pDraw)
 +		{
 +		    ChangeGC( c->pGC, GCFont, &fid);
 +		    ValidateGC(c->pDraw, c->pGC);
 +		    if (c->reqType == X_PolyText8)
 +			c->polyText = (PolyTextPtr) c->pGC->ops->PolyText8;
 +		    else
 +			c->polyText = (PolyTextPtr) c->pGC->ops->PolyText16;
 +		}
 +
 +		/* Undo the refcnt++ we performed when going to sleep */
 +		if (client_state == SLEEPING)
 +		    (void)CloseFont(c->pGC->font, (Font)0);
 +	    }
 +	    c->pElt += FontShiftSize;
 +	}
 +	else	/* print a string */
 +	{
 +	    unsigned char *pNextElt;
 +	    pNextElt = c->pElt + TextEltHeader + (*c->pElt)*c->itemSize;
 +	    if ( pNextElt > c->endReq)
 +	    {
 +		err = BadLength;
 +		goto bail;
 +	    }
 +	    if (client_state == START_SLEEP)
 +	    {
 +		c->pElt = pNextElt;
 +		continue;
 +	    }
 +	    if (c->pDraw)
 +	    {
 +		lgerr = LoadGlyphs(client, c->pGC->font, *c->pElt, c->itemSize,
 +				   c->pElt + TextEltHeader);
 +	    }
 +	    else lgerr = Successful;
 +
 +	    if (lgerr == Suspended)
 +	    {
 +		if (!c->slept) {
 +		    int len;
 +		    GC *pGC;
 +		    PTclosurePtr new_closure;
 +
 +    /*  We're putting the client to sleep.  We need to do a few things
 +	to ensure successful and atomic-appearing execution of the
 +	remainder of the request.  First, copy the remainder of the
 +	request into a safe malloc'd area.  Second, create a scratch GC
 +	to use for the remainder of the request.  Third, mark all fonts
 +	referenced in the remainder of the request to prevent their
 +	deallocation.  Fourth, make the original GC look like the
 +	request has completed...  set its font to the final font value
 +	from this request.  These GC manipulations are for the unlikely
 +	(but possible) event that some other client is using the GC.
 +	Steps 3 and 4 are performed by running this procedure through
 +	the remainder of the request in a special no-render mode
 +	indicated by client_state = START_SLEEP.  */
 +
 +		    /* Step 1 */
 +		    /* Allocate a malloc'd closure structure to replace
 +		       the local one we were passed */
 +		    new_closure = xalloc(sizeof(PTclosureRec));
 +		    if (!new_closure)
 +		    {
 +			err = BadAlloc;
 +			goto bail;
 +		    }
 +		    *new_closure = *c;
 +		    c = new_closure;
 +
 +		    len = c->endReq - c->pElt;
 +		    c->data = xalloc(len);
 +		    if (!c->data)
 +		    {
 +			xfree(c);
 +			err = BadAlloc;
 +			goto bail;
 +		    }
 +		    memmove(c->data, c->pElt, len);
 +		    c->pElt = c->data;
 +		    c->endReq = c->pElt + len;
 +
 +		    /* Step 2 */
 +
 +		    pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen);
 +		    if (!pGC)
 +		    {
 +			xfree(c->data);
 +			xfree(c);
 +			err = BadAlloc;
 +			goto bail;
 +		    }
 +		    if ((err = CopyGC(c->pGC, pGC, GCFunction |
 +				      GCPlaneMask | GCForeground |
 +				      GCBackground | GCFillStyle |
 +				      GCTile | GCStipple |
 +				      GCTileStipXOrigin |
 +				      GCTileStipYOrigin | GCFont |
 +				      GCSubwindowMode | GCClipXOrigin |
 +				      GCClipYOrigin | GCClipMask)) !=
 +				      Success)
 +		    {
 +			FreeScratchGC(pGC);
 +			xfree(c->data);
 +			xfree(c);
 +			err = BadAlloc;
 +			goto bail;
 +		    }
 +		    origGC = c->pGC;
 +		    c->pGC = pGC;
 +		    ValidateGC(c->pDraw, c->pGC);
 +		    
 +		    c->slept = TRUE;
 +		    ClientSleep(client,
 +		    	     (ClientSleepProcPtr)doPolyText,
 +			     (pointer) c);
 +
 +		    /* Set up to perform steps 3 and 4 */
 +		    client_state = START_SLEEP;
 +		    continue;	/* on to steps 3 and 4 */
 +		}
 +		return TRUE;
 +	    }
 +	    else if (lgerr != Successful)
 +	    {
 +		err = FontToXError(lgerr);
 +		goto bail;
 +	    }
 +	    if (c->pDraw)
 +	    {
 +		c->xorg += *((INT8 *)(c->pElt + 1));	/* must be signed */
 +		c->xorg = (* c->polyText)(c->pDraw, c->pGC, c->xorg, c->yorg,
 +		    *c->pElt, c->pElt + TextEltHeader);
 +	    }
 +	    c->pElt = pNextElt;
 +	}
 +    }
 +
 +bail:
 +
 +    if (client_state == START_SLEEP)
 +    {
 +	/* Step 4 */
 +	if (pFont != origGC->font)
 +	{
 +	    ChangeGC(origGC, GCFont, &fid);
 +	    ValidateGC(c->pDraw, origGC);
 +	}
 +
 +	/* restore pElt pointer for execution of remainder of the request */
 +	c->pElt = c->data;
 +	return TRUE;
 +    }
 +
 +    if (c->err != Success) err = c->err;
 +    if (err != Success && c->client != serverClient) {
 +#ifdef PANORAMIX
 +        if (noPanoramiXExtension || !c->pGC->pScreen->myNum)
 +#endif
 +	    SendErrorToClient(c->client, c->reqType, 0, 0, err);
 +    }
 +    if (c->slept)
 +    {
 +	ClientWakeup(c->client);
 +	ChangeGC(c->pGC, clearGCmask, clearGC);
 +
 +	/* Unreference the font from the scratch GC */
 +	CloseFont(c->pGC->font, (Font)0);
 +	c->pGC->font = NullFont;
 +
 +	FreeScratchGC(c->pGC);
 +	xfree(c->data);
 +	xfree(c);
 +    }
 +    return TRUE;
 +}
 +
 +int
 +PolyText(ClientPtr client, DrawablePtr pDraw, GC *pGC, unsigned char *pElt, 
 +         unsigned char *endReq, int xorg, int yorg, int reqType, XID did)
 +{
 +    PTclosureRec local_closure;
 +
 +    local_closure.pElt = pElt;
 +    local_closure.endReq = endReq;
 +    local_closure.client = client;
 +    local_closure.pDraw = pDraw;
 +    local_closure.xorg = xorg;
 +    local_closure.yorg = yorg;
 +    if ((local_closure.reqType = reqType) == X_PolyText8)
 +    {
 +	local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText8;
 +	local_closure.itemSize = 1;
 +    }
 +    else
 +    {
 +	local_closure.polyText =  (PolyTextPtr) pGC->ops->PolyText16;
 +	local_closure.itemSize = 2;
 +    }
 +    local_closure.pGC = pGC;
 +    local_closure.did = did;
 +    local_closure.err = Success;
 +    local_closure.slept = FALSE;
 +
 +    (void) doPolyText(client, &local_closure);
 +    return Success;
 +}
 +
 +
 +#undef TextEltHeader
 +#undef FontShiftSize
 +
 +int
 +doImageText(ClientPtr client, ITclosurePtr c)
 +{
 +    int err = Success, lgerr;	/* err is in X error, not font error, space */
 +    FontPathElementPtr fpe;
 +
 +    if (client->clientGone)
 +    {
 +	fpe = c->pGC->font->fpe;
 +	(*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
 +	err = Success;
 +	goto bail;
 +    }
 +
 +    /* Make sure our drawable hasn't disappeared while we slept. */
 +    if (c->slept && c->pDraw)
 +    {
 +	DrawablePtr pDraw;
 +	dixLookupDrawable(&pDraw, c->did, client, 0, DixWriteAccess);
 +	if (c->pDraw != pDraw) {
 +	    /* Our drawable has disappeared.  Treat like client died... ask
 +	       the FPE code to clean up after client. */
 +	    fpe = c->pGC->font->fpe;
 +	    (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
 +	    err = Success;
 +	    goto bail;
 +	}
 +    }
 +
 +    lgerr = LoadGlyphs(client, c->pGC->font, c->nChars, c->itemSize, c->data);
 +    if (lgerr == Suspended)
 +    {
 +        if (!c->slept) {
 +	    GC *pGC;
 +	    unsigned char *data;
 +	    ITclosurePtr new_closure;
 +
 +	    /* We're putting the client to sleep.  We need to
 +	       save some state.  Similar problem to that handled
 +	       in doPolyText, but much simpler because the
 +	       request structure is much simpler. */
 +
 +	    new_closure = xalloc(sizeof(ITclosureRec));
 +	    if (!new_closure)
 +	    {
 +		err = BadAlloc;
 +		goto bail;
 +	    }
 +	    *new_closure = *c;
 +	    c = new_closure;
 +
 +	    data = xalloc(c->nChars * c->itemSize);
 +	    if (!data)
 +	    {
 +		xfree(c);
 +		err = BadAlloc;
 +		goto bail;
 +	    }
 +	    memmove(data, c->data, c->nChars * c->itemSize);
 +	    c->data = data;
 +
 +	    pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen);
 +	    if (!pGC)
 +	    {
 +		xfree(c->data);
 +		xfree(c);
 +		err = BadAlloc;
 +		goto bail;
 +	    }
 +	    if ((err = CopyGC(c->pGC, pGC, GCFunction | GCPlaneMask |
 +			      GCForeground | GCBackground | GCFillStyle |
 +			      GCTile | GCStipple | GCTileStipXOrigin |
 +			      GCTileStipYOrigin | GCFont |
 +			      GCSubwindowMode | GCClipXOrigin |
 +			      GCClipYOrigin | GCClipMask)) != Success)
 +	    {
 +		FreeScratchGC(pGC);
 +		xfree(c->data);
 +		xfree(c);
 +		err = BadAlloc;
 +		goto bail;
 +	    }
 +	    c->pGC = pGC;
 +	    ValidateGC(c->pDraw, c->pGC);
 +
 +	    c->slept = TRUE;
 +            ClientSleep(client, (ClientSleepProcPtr)doImageText, (pointer) c);
 +        }
 +        return TRUE;
 +    }
 +    else if (lgerr != Successful)
 +    {
 +        err = FontToXError(lgerr);
 +        goto bail;
 +    }
 +    if (c->pDraw)
 +    {
 +	(* c->imageText)(c->pDraw, c->pGC, c->xorg, c->yorg,
 +	    c->nChars, c->data);
 +    }
 +
 +bail:
 +
 +    if (err != Success && c->client != serverClient) {
 +	SendErrorToClient(c->client, c->reqType, 0, 0, err);
 +    }
 +    if (c->slept)
 +    {
 +	ClientWakeup(c->client);
 +	ChangeGC(c->pGC, clearGCmask, clearGC);
 +
 +	/* Unreference the font from the scratch GC */
 +	CloseFont(c->pGC->font, (Font)0);
 +	c->pGC->font = NullFont;
 +
 +	FreeScratchGC(c->pGC);
 +	xfree(c->data);
 +	xfree(c);
 +    }
 +    return TRUE;
 +}
 +
 +int
 +ImageText(ClientPtr client, DrawablePtr pDraw, GC *pGC, int nChars, 
 +          unsigned char *data, int xorg, int yorg, int reqType, XID did)
 +{
 +    ITclosureRec local_closure;
 +
 +    local_closure.client = client;
 +    local_closure.pDraw = pDraw;
 +    local_closure.pGC = pGC;
 +    local_closure.nChars = nChars;
 +    local_closure.data = data;
 +    local_closure.xorg = xorg;
 +    local_closure.yorg = yorg;
 +    if ((local_closure.reqType = reqType) == X_ImageText8)
 +    {
 +	local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText8;
 +	local_closure.itemSize = 1;
 +    }
 +    else
 +    {
 +	local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText16;
 +	local_closure.itemSize = 2;
 +    }
 +    local_closure.did = did;
 +    local_closure.slept = FALSE;
 +
 +    (void) doImageText(client, &local_closure);
 +    return Success;
 +}
 +
 +
 +/* does the necessary magic to figure out the fpe type */
 +static int
 +DetermineFPEType(char *pathname)
 +{
 +    int         i;
 +
 +    for (i = 0; i < num_fpe_types; i++) {
 +	if ((*fpe_functions[i].name_check) (pathname))
 +	    return i;
 +    }
 +    return -1;
 +}
 +
 +
 +static void
 +FreeFontPath(FontPathElementPtr *list, int n, Bool force)
 +{
 +    int         i;
 +
 +    for (i = 0; i < n; i++) {
 +	if (force) {
 +	    /* Sanity check that all refcounts will be 0 by the time
 +	       we get to the end of the list. */
 +	    int found = 1;	/* the first reference is us */
 +	    int j;
 +	    for (j = i+1; j < n; j++) {
 +		if (list[j] == list[i])
 +		    found++;
 +	    }
 +	    if (list[i]->refcount != found) {
 +		list[i]->refcount = found; /* ensure it will get freed */
 +	    }
 +	}
 +	FreeFPE(list[i]);
 +    }
 +    xfree(list);
 +}
 +
 +static FontPathElementPtr
 +find_existing_fpe(FontPathElementPtr *list, int num, unsigned char *name, int len)
 +{
 +    FontPathElementPtr fpe;
 +    int         i;
 +
 +    for (i = 0; i < num; i++) {
 +	fpe = list[i];
 +	if (fpe->name_length == len && memcmp(name, fpe->name, len) == 0)
 +	    return fpe;
 +    }
 +    return (FontPathElementPtr) 0;
 +}
 +
 +
 +static int
 +SetFontPathElements(int npaths, unsigned char *paths, int *bad, Bool persist)
 +{
 +    int         i, err = 0;
 +    int         valid_paths = 0;
 +    unsigned int len;
 +    unsigned char *cp = paths;
 +    FontPathElementPtr fpe = NULL, *fplist;
 +
 +    fplist = xalloc(sizeof(FontPathElementPtr) * npaths);
 +    if (!fplist) {
 +	*bad = 0;
 +	return BadAlloc;
 +    }
 +    for (i = 0; i < num_fpe_types; i++) {
 +	if (fpe_functions[i].set_path_hook)
 +	    (*fpe_functions[i].set_path_hook) ();
 +    }
 +    for (i = 0; i < npaths; i++) 
 +    {
 +	len = (unsigned int) (*cp++);
 +
 +	if (len == 0) 
 +	{
 +	    if (persist)
 +		ErrorF("[dix] Removing empty element from the valid list of fontpaths\n");
 +	    err = BadValue;
 +	}
 +	else
 +	{
 +	    /* if it's already in our active list, just reset it */
 +	    /*
 +	     * note that this can miss FPE's in limbo -- may be worth catching
 +	     * them, though it'd muck up refcounting
 +	     */
 +	    fpe = find_existing_fpe(font_path_elements, num_fpes, cp, len);
 +	    if (fpe) 
 +	    {
 +		err = (*fpe_functions[fpe->type].reset_fpe) (fpe);
 +		if (err == Successful) 
 +		{
 +		    UseFPE(fpe);/* since it'll be decref'd later when freed
 +				 * from the old list */
 +		}
 +		else
 +		    fpe = 0;
 +	    }
 +	    /* if error or can't do it, act like it's a new one */
 +	    if (!fpe)
 +	    {
 +		fpe = xalloc(sizeof(FontPathElementRec));
 +		if (!fpe) 
 +		{
 +		    err = BadAlloc;
 +		    goto bail;
 +		}
 +		fpe->name = xalloc(len + 1);
 +		if (!fpe->name) 
 +		{
 +		    xfree(fpe);
 +		    err = BadAlloc;
 +		    goto bail;
 +		}
 +		fpe->refcount = 1;
 +    
 +		strncpy(fpe->name, (char *) cp, (int) len);
 +		fpe->name[len] = '\0';
 +		fpe->name_length = len;
 +		fpe->type = DetermineFPEType(fpe->name);
 +		if (fpe->type == -1)
 +		    err = BadValue;
 +		else
 +		    err = (*fpe_functions[fpe->type].init_fpe) (fpe);
 +		if (err != Successful)
 +		{
 +		    if (persist)
 +		    {
 +			ErrorF("[dix] Could not init font path element %s, removing from list!\n",
 +			       fpe->name);
 +		    }
 +		    xfree (fpe->name);
 +		    xfree (fpe);
 +		}
 +	    }
 +	}
 +	if (err != Successful)
 +	{
 +	    if (!persist)
 +		goto bail;
 +	}
 +	else
 +	{
 +	    fplist[valid_paths++] = fpe;
 +	}
 +	cp += len;
 +    }
 +
 +    FreeFontPath(font_path_elements, num_fpes, FALSE);
 +    font_path_elements = fplist;
 +    if (patternCache)
 +	EmptyFontPatternCache(patternCache);
 +    num_fpes = valid_paths;
 +
 +    return Success;
 +bail:
 +    *bad = i;
 +    while (--valid_paths >= 0)
 +	FreeFPE(fplist[valid_paths]);
 +    xfree(fplist);
 +    return FontToXError(err);
 +}
 +
 +/* XXX -- do we need to pass error down to each renderer? */
 +int
 +SetFontPath(ClientPtr client, int npaths, unsigned char *paths, int *error)
 +{
 +    int err = XaceHook(XACE_SERVER_ACCESS, client, DixManageAccess);
 +    if (err != Success)
 +	return err;
 +
 +    if (npaths == 0) {
 +	if (SetDefaultFontPath(defaultFontPath) != Success)
 +	    return BadValue;
 +    } else {
 +	err = SetFontPathElements(npaths, paths, error, FALSE);
 +    }
 +    return err;
 +}
 +
 +int
 +SetDefaultFontPath(char *path)
 +{
 +    char       *temp_path,
 +               *start,
 +               *end;
 +    unsigned char *cp,
 +               *pp,
 +               *nump,
 +               *newpath;
 +    int         num = 1,
 +                len,
 +                err,
 +                size = 0,
 +                bad;
 +
 +    /* ensure temp_path contains "built-ins" */
 +    start = path;
 +    while (1) {
 +	start = strstr(start, "built-ins");
 +	if (start == NULL)
 +	    break;
 +	end = start + strlen("built-ins");
 +	if ((start == path || start[-1] == ',') && (!*end || *end == ','))
 +	    break;
 +	start = end;
 +    }
 +    if (!start) {
 +	temp_path = Xprintf("%s%sbuilt-ins", path, *path ? "," : "");
 +    } else {
 +	temp_path = Xstrdup(path);
 +    }
 +    if (!temp_path)
 +        return BadAlloc;
 +
 +    /* get enough for string, plus values -- use up commas */
 +    len = strlen(temp_path) + 1;
 +    nump = cp = newpath = xalloc(len);
 +    if (!newpath)
 +	return BadAlloc;
 +    pp = (unsigned char *) temp_path;
 +    cp++;
 +    while (*pp) {
 +	if (*pp == ',') {
 +	    *nump = (unsigned char) size;
 +	    nump = cp++;
 +	    pp++;
 +	    num++;
 +	    size = 0;
 +	} else {
 +	    *cp++ = *pp++;
 +	    size++;
 +	}
 +    }
 +    *nump = (unsigned char) size;
 +
 +    err = SetFontPathElements(num, newpath, &bad, TRUE);
 +
 +    xfree(newpath);
 +    xfree(temp_path);
 +
 +    return err;
 +}
 +
 +int
 +GetFontPath(ClientPtr client, int *count, int *length, unsigned char **result)
 +{
 +    int			i;
 +    unsigned char       *c;
 +    int			len;
 +    FontPathElementPtr	fpe;
 +
 +    i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess);
 +    if (i != Success)
 +	return i;
 +
 +    len = 0;
 +    for (i = 0; i < num_fpes; i++) {
 +	fpe = font_path_elements[i];
 +	len += fpe->name_length + 1;
 +    }
 +    font_path_string = (unsigned char *) xrealloc(font_path_string, len);
 +    if (!font_path_string)
 +	return BadAlloc;
 +
 +    c = font_path_string;
 +    *length = 0;
 +    for (i = 0; i < num_fpes; i++) {
 +	fpe = font_path_elements[i];
 +	*c = fpe->name_length;
 +	*length += *c++;
 +	memmove(c, fpe->name, fpe->name_length);
 +	c += fpe->name_length;
 +    }
 +    *count = num_fpes;
 +    *result = font_path_string;
 +    return Success;
 +}
 +
 +void
 +DeleteClientFontStuff(ClientPtr client)
 +{
 +    int			i;
 +    FontPathElementPtr	fpe;
 +
 +    for (i = 0; i < num_fpes; i++)
 +    {
 +	fpe = font_path_elements[i];
 +	if (fpe_functions[fpe->type].client_died)
 +	    (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
 +    }
 +}
 +
 +void
 +InitFonts (void)
 +{
 +    patternCache = MakeFontPatternCache();
 +
 +    BuiltinRegisterFpeFunctions();
 +    FontFileRegisterFpeFunctions();
 +    fs_register_fpe_functions();
 +}
 +
 +int
 +GetDefaultPointSize (void)
 +{
 +    return 120;
 +}
 +
 +
 +FontResolutionPtr
 +GetClientResolutions (int *num)
 +{
 +    static struct _FontResolution res;
 +    ScreenPtr   pScreen;
 +
 +    pScreen = screenInfo.screens[0];
 +    res.x_resolution = (pScreen->width * 25.4) / pScreen->mmWidth;
 +    /*
 +     * XXX - we'll want this as long as bitmap instances are prevalent 
 +     so that we can match them from scalable fonts
 +     */
 +    if (res.x_resolution < 88)
 +	res.x_resolution = 75;
 +    else
 +	res.x_resolution = 100;
 +    res.y_resolution = (pScreen->height * 25.4) / pScreen->mmHeight;
 +    if (res.y_resolution < 88)
 +	res.y_resolution = 75;
 +    else
 +	res.y_resolution = 100;
 +    res.point_size = 120;
 +    *num = 1;
 +    return &res;
 +}
 +
 +/*
 + * returns the type index of the new fpe
 + *
 + * should be called (only once!) by each type of fpe when initialized
 + */
 +
 +int
 +RegisterFPEFunctions(NameCheckFunc name_func, 
 +		     InitFpeFunc init_func, 
 +		     FreeFpeFunc free_func, 
 +		     ResetFpeFunc reset_func, 
 +		     OpenFontFunc open_func, 
 +		     CloseFontFunc close_func, 
 +		     ListFontsFunc list_func, 
 +		     StartLfwiFunc start_lfwi_func, 
 +		     NextLfwiFunc next_lfwi_func, 
 +		     WakeupFpeFunc wakeup_func, 
 +		     ClientDiedFunc client_died, 
 +		     LoadGlyphsFunc load_glyphs, 
 +		     StartLaFunc start_list_alias_func, 
 +		     NextLaFunc next_list_alias_func, 
 +		     SetPathFunc set_path_func)
 +{
 +    FPEFunctions *new;
 +
 +    /* grow the list */
 +    new = (FPEFunctions *) xrealloc(fpe_functions,
 +				 (num_fpe_types + 1) * sizeof(FPEFunctions));
 +    if (!new)
 +	return -1;
 +    fpe_functions = new;
 +
 +    fpe_functions[num_fpe_types].name_check = name_func;
 +    fpe_functions[num_fpe_types].open_font = open_func;
 +    fpe_functions[num_fpe_types].close_font = close_func;
 +    fpe_functions[num_fpe_types].wakeup_fpe = wakeup_func;
 +    fpe_functions[num_fpe_types].list_fonts = list_func;
 +    fpe_functions[num_fpe_types].start_list_fonts_with_info =
 +	start_lfwi_func;
 +    fpe_functions[num_fpe_types].list_next_font_with_info =
 +	next_lfwi_func;
 +    fpe_functions[num_fpe_types].init_fpe = init_func;
 +    fpe_functions[num_fpe_types].free_fpe = free_func;
 +    fpe_functions[num_fpe_types].reset_fpe = reset_func;
 +    fpe_functions[num_fpe_types].client_died = client_died;
 +    fpe_functions[num_fpe_types].load_glyphs = load_glyphs;
 +    fpe_functions[num_fpe_types].start_list_fonts_and_aliases =
 +	start_list_alias_func;
 +    fpe_functions[num_fpe_types].list_next_font_or_alias =
 +	next_list_alias_func;
 +    fpe_functions[num_fpe_types].set_path_hook = set_path_func;
 +
 +    return num_fpe_types++;
 +}
 +
 +void
 +FreeFonts(void)
 +{
 +    if (patternCache) {
 +	FreeFontPatternCache(patternCache);
 +	patternCache = 0;
 +    }
 +    FreeFontPath(font_path_elements, num_fpes, TRUE);
 +    font_path_elements = 0;
 +    num_fpes = 0;
 +    xfree(fpe_functions);
 +    num_fpe_types = 0;
 +    fpe_functions = (FPEFunctions *) 0;
 +}
 +
 +/* convenience functions for FS interface */
 +
 +FontPtr
 +find_old_font(XID id)
 +{
 +    pointer pFont;
 +    dixLookupResourceByType(&pFont, id, RT_NONE, serverClient, DixReadAccess);
 +    return (FontPtr)pFont;
 +}
 +
 +Font
 +GetNewFontClientID(void)
 +{
 +    return FakeClientID(0);
 +}
 +
 +int
 +StoreFontClientFont(FontPtr pfont, Font id)
 +{
 +    return AddResource(id, RT_NONE, (pointer) pfont);
 +}
 +
 +void
 +DeleteFontClientID(Font id)
 +{
 +    FreeResource(id, RT_NONE);
 +}
 +
 +int
 +client_auth_generation(ClientPtr client)
 +{
 +    return 0;
 +}
 +
 +static int  fs_handlers_installed = 0;
 +static unsigned int last_server_gen;
 +
 +int
 +init_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler)
 +{
 +    /* if server has reset, make sure the b&w handlers are reinstalled */
 +    if (last_server_gen < serverGeneration) {
 +	last_server_gen = serverGeneration;
 +	fs_handlers_installed = 0;
 +    }
 +    if (fs_handlers_installed == 0) {
 +	if (!RegisterBlockAndWakeupHandlers(block_handler,
 +					    FontWakeup, (pointer) 0))
 +	    return AllocError;
 +	fs_handlers_installed++;
 +    }
 +    QueueFontWakeup(fpe);
 +    return Successful;
 +}
 +
 +void
 +remove_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler, Bool all)
 +{
 +    if (all) {
 +	/* remove the handlers if no one else is using them */
 +	if (--fs_handlers_installed == 0) {
 +	    RemoveBlockAndWakeupHandlers(block_handler, FontWakeup,
 +					 (pointer) 0);
 +	}
 +    }
 +    RemoveFontWakeup(fpe);
 +}
 | 
