--- ./nx-X11/programs/Xserver/hw/nxagent/X/NXdixfonts.c.X.original 2015-02-13 14:03:44.744441510 +0100 +++ ./nx-X11/programs/Xserver/hw/nxagent/X/NXdixfonts.c 2015-02-13 14:03:44.744441510 +0100 @@ -1,3 +1,20 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of Medialogic S.p.A. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + /* $XdotOrg: xc/programs/Xserver/dix/dixfonts.c,v 1.8 2005/07/03 08:53:38 daniels Exp $ */ /* $XFree86: xc/programs/Xserver/dix/dixfonts.c,v 3.28 2003/11/08 02:02:03 dawes Exp $ */ /************************************************************************ @@ -68,12 +85,84 @@ #include "dixfontstr.h" #include "closestr.h" +/* +#define NXAGENT_DEBUG +*/ + #ifdef DEBUG #include #endif +#include "Agent.h" +#include "Font.h" + +#ifndef NX_TRANS_SOCKET + +#define NX_TRANS_SOCKET + +#endif + +#ifdef NX_TRANS_SOCKET + +char _NXFontPath[1024]; + +/* + * Override the default font path and make + * it configurable at run time, based on + * the NX_FONT environment. + */ + +static const char *_NXGetFontPath(const char *path) +{ + const char *fontEnv; + + /* + * Check the environment only once. + */ + + if (*_NXFontPath != '\0') + { + return _NXFontPath; + } + + fontEnv = getenv("NX_FONT"); + + if (fontEnv != NULL && *fontEnv != '\0') + { + if (strlen(fontEnv) + 1 > 1024) + { +#ifdef NX_TRANS_TEST + fprintf(stderr, "_NXGetFontPath: WARNING! Maximum length of font path exceeded.\n"); +#endif + goto _NXGetFontPathError; + } + + strcpy(_NXFontPath, fontEnv); + +#ifdef NX_TRANS_TEST + fprintf(stderr, "_NXGetFontPath: Using NX font path [%s].\n", _NXFontPath); +#endif + + return _NXFontPath; + } + +_NXGetFontPathError: + + strncpy(_NXFontPath, path, 1023); + _NXFontPath[1023] = '\0'; + +#ifdef NX_TRANS_TEST + fprintf(stderr, "_NXGetFontPath: Using default font path [%s].\n", _NXFontPath); +#endif + + return _NXFontPath; +} + +#endif + #ifdef PANORAMIX -#include "panoramiX.h" +#include "../../Xext/panoramiX.h" +#include "../../Xext/panoramiXsrv.h" #endif #ifdef LBX @@ -245,6 +334,9 @@ *newname; int newlen; int aliascount = 20; + char nxagentOrigFontName[256]; + int nxagentOrigFontNameLen; + /* * Decide at runtime what FontFormat to use. */ @@ -276,6 +368,13 @@ BitmapFormatScanlineUnit8; + + nxagentOrigFontNameLen = (c -> origFontNameLen < 256) ? c -> origFontNameLen : 255; + + memcpy(nxagentOrigFontName, c -> origFontName, nxagentOrigFontNameLen); + + nxagentOrigFontName[nxagentOrigFontNameLen] = 0; + if (client->clientGone) { if (c->current_fpe < c->num_fpes) @@ -324,6 +423,9 @@ if (!c->slept) { c->slept = TRUE; ClientSleep(client, (ClientSleepProcPtr)doOpenFont, (pointer) c); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doOpenFont: client [%lx] sleeping.\n", client); +#endif } return TRUE; } @@ -352,10 +454,15 @@ pScr = screenInfo.screens[i]; if (pScr->RealizeFont) { - if (!(*pScr->RealizeFont) (pScr, pfont)) + + /* NXAGENT uses useless screen pointer to pass the original font name + * to realizeFont, could be a source of problems in the future. + */ + + if (!(*pScr->RealizeFont) ((ScreenPtr)nxagentOrigFontName, pfont)) { CloseFont (pfont, (Font) 0); - err = AllocError; + err=BadFontName; goto bail; } } @@ -365,8 +472,19 @@ err = AllocError; goto bail; } + if( nxagentFontPriv(pfont) -> mirrorID == 0 ) + { + extern RESTYPE RT_NX_FONT; + + nxagentFontPriv(pfont) -> mirrorID = FakeClientID(0); + if (!AddResource(nxagentFontPriv(pfont) -> mirrorID, RT_NX_FONT, (pointer) pfont)) { + FreeResource(c->fontid, RT_NONE); + err = AllocError; + goto bail; + } + } if (patternCache && pfont != c->non_cachable_font) - CacheFontPattern(patternCache, c->origFontName, c->origFontNameLen, + CacheFontPattern(patternCache, nxagentOrigFontName, nxagentOrigFontNameLen, pfont); bail: if (err != Successful && c->client != serverClient) { @@ -374,7 +492,12 @@ c->fontid, FontToXError(err)); } if (c->slept) + { ClientWakeup(c->client); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doOpenFont: client [%lx] wakeup.\n", client); +#endif + } for (i = 0; i < c->num_fpes; i++) { FreeFPE(c->fpe_list[i]); } @@ -502,7 +625,10 @@ LbxFreeFontTag(pfont); #endif #ifdef XF86BIGFONT - XF86BigfontFreeFontShm(pfont); + { + extern void XF86BigfontFreeFontShm(FontPtr); + XF86BigfontFreeFontShm(pfont); + } #endif fpe = pfont->fpe; (*fpe_functions[fpe->type].close_font) (fpe, pfont); @@ -631,6 +757,9 @@ ClientSleep(client, (ClientSleepProcPtr)doListFontsAndAliases, (pointer) c); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFont (1): client [%lx] sleeping.\n", client); +#endif } return TRUE; } @@ -677,6 +806,12 @@ (ClientSleepProcPtr)doListFontsAndAliases, (pointer) c); c->slept = TRUE; +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFont (2): client [%lx] sleeping.\n", client); +#endif +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFont (3): client [%lx] sleeping.\n", client); +#endif } return TRUE; } @@ -813,6 +948,24 @@ reply.nFonts--; else { + { + /* dirty hack: don't list to client fonts not existing on the remote side */ + char tmp[256]; + + memcpy(tmp, names->names[i], names->length[i]); + tmp[ names->length[i] ] = 0; + + if (nxagentFontLookUp(tmp) == 0) + { +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "doListFontsAndAliases:\n"); + fprintf(stderr, " removing font: %s \n", tmp); +#endif + reply.nFonts--; + stringLens -= names->length[i]; + continue; + } + } *bufptr++ = names->length[i]; memmove( bufptr, names->names[i], names->length[i]); bufptr += names->length[i]; @@ -827,7 +980,12 @@ bail: if (c->slept) + { ClientWakeup(client); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFont: client [%lx] wakeup.\n", client); +#endif + } for (i = 0; i < c->num_fpes; i++) FreeFPE(c->fpe_list[i]); xfree(c->fpe_list); @@ -862,7 +1020,7 @@ xfree(c); return BadAlloc; } - c->names = MakeFontNamesRecord(max_names < 100 ? max_names : 100); + c->names = MakeFontNamesRecord(max_names < nxagentMaxFontNames ? max_names : nxagentMaxFontNames); if (!c->names) { xfree(c->fpe_list); @@ -933,6 +1091,9 @@ { ClientSleep(client, (ClientSleepProcPtr)doListFontsWithInfo, c); c->slept = TRUE; +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFontWinfo (1): client [%lx] sleeping.\n", client); +#endif } return TRUE; } @@ -954,6 +1115,9 @@ (ClientSleepProcPtr)doListFontsWithInfo, c); c->slept = TRUE; +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFontWinfo (2): client [%lx] sleeping.\n", client); +#endif } return TRUE; } @@ -1035,6 +1199,23 @@ } else if (err == Successful) { + + if (c->haveSaved) + { + numFonts = c->savedNumFonts; + name = c->savedName; + namelen = strlen(name); + } + + if (nxagentFontLookUp(name) == 0) + { +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "doListFontsAndAliases (with info):\n"); + fprintf(stderr, " removing font: %s \n", name); +#endif + continue; + } + length = sizeof(*reply) + pFontInfo->nprops * sizeof(xFontProp); reply = c->reply; if (c->length < length) @@ -1048,12 +1229,6 @@ c->reply = reply; c->length = length; } - if (c->haveSaved) - { - numFonts = c->savedNumFonts; - name = c->savedName; - namelen = strlen(name); - } reply->type = X_Reply; reply->length = (sizeof *reply - sizeof(xGenericReply) + pFontInfo->nprops * sizeof(xFontProp) + @@ -1100,7 +1275,12 @@ WriteSwappedDataToClient(client, length, &finalReply); bail: if (c->slept) + { ClientWakeup(client); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFontWinfo: client [%lx] wakeup.\n", client); +#endif + } for (i = 0; i < c->num_fpes; i++) FreeFPE(c->fpe_list[i]); xfree(c->reply); @@ -1347,6 +1527,11 @@ err = BadAlloc; goto bail; } + + pGC->tileIsPixel = TRUE; + pGC->tile.pixel = 0; + pGC->stipple = NullPixmap; + if ((err = CopyGC(c->pGC, pGC, GCFunction | GCPlaneMask | GCForeground | GCBackground | GCFillStyle | @@ -1371,6 +1556,9 @@ ClientSleep(client, (ClientSleepProcPtr)doPolyText, (pointer) c); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doPolyText (1): client [%lx] sleeping.\n", client); +#endif /* Set up to perform steps 3 and 4 */ client_state = START_SLEEP; @@ -1419,6 +1607,9 @@ if (c->slept) { ClientWakeup(c->client); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doPolytext: client [%lx] wakeup.\n", client); +#endif ChangeGC(c->pGC, clearGCmask, clearGC); /* Unreference the font from the scratch GC */ @@ -1535,6 +1726,11 @@ err = BadAlloc; goto bail; } + + pGC->tileIsPixel = TRUE; + pGC->tile.pixel = 0; + pGC->stipple = NullPixmap; + if ((err = CopyGC(c->pGC, pGC, GCFunction | GCPlaneMask | GCForeground | GCBackground | GCFillStyle | GCTile | GCStipple | GCTileStipXOrigin | @@ -1553,6 +1749,10 @@ c->slept = TRUE; ClientSleep(client, (ClientSleepProcPtr)doImageText, (pointer) c); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doImageText (1): client [%lx] sleeping.\n", client); +#endif + } return TRUE; } @@ -1575,6 +1775,9 @@ if (c->slept) { ClientWakeup(c->client); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doImageText: client [%lx] wakeup.\n", client); +#endif ChangeGC(c->pGC, clearGCmask, clearGC); /* Unreference the font from the scratch GC */ @@ -1751,11 +1954,13 @@ err = (*fpe_functions[fpe->type].init_fpe) (fpe); if (err != Successful) { + #ifndef NXAGENT_SERVER if (persist) { ErrorF("Could not init font path element %s, removing from list!\n", fpe->name); } + #endif xfree (fpe->name); xfree (fpe); } @@ -1817,11 +2022,19 @@ bad; /* get enough for string, plus values -- use up commas */ +#ifdef NX_TRANS_SOCKET + len = strlen(_NXGetFontPath(path)) + 1; +#else len = strlen(path) + 1; +#endif nump = cp = newpath = (unsigned char *) ALLOCATE_LOCAL(len); if (!newpath) return BadAlloc; +#ifdef NX_TRANS_SOCKET + pp = (unsigned char *) _NXGetFontPath(path); +#else pp = (unsigned char *) path; +#endif cp++; while (*pp) { if (*pp == ',') { @@ -2148,3 +2361,445 @@ } #endif + + +typedef struct +{ + LFclosurePtr c; + OFclosurePtr oc; +} nxFs,*nxFsPtr; + +static Bool +#if NeedFunctionPrototypes +nxdoListFontsAndAliases(ClientPtr client, nxFsPtr fss) +#else +nxdoListFontsAndAliases(client, fss) + ClientPtr client; + nxFsPtr fss; +#endif +{ + LFclosurePtr c=fss->c; + OFclosurePtr oc=fss->oc; + FontPathElementPtr fpe; + int err = Successful; + char *name, *resolved=NULL; + int namelen, resolvedlen; + int i; + int aliascount = 0; + char tmp[256]; + tmp[0]=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)nxdoListFontsAndAliases, + (pointer) fss); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: nxdoListFont (1): client [%lx] sleeping.\n", client); +#endif + } + 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)nxdoListFontsAndAliases, + (pointer) fss); + c->slept = TRUE; +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: nxdoListFont (2): client [%lx] sleeping.\n", client); +#endif + } + 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)nxdoListFontsAndAliases, + (pointer) fss); + c->slept = TRUE; +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: nxdoListFont (3): client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + if (err == FontNameAlias) { + if (resolved) xfree(resolved); + resolved = (char *) xalloc(resolvedlen + 1); + if (resolved) + { + memmove(resolved, tmpname, resolvedlen); + resolved[resolvedlen] = '\0'; + } + } + } + + if (err == Successful) + { + if (c->haveSaved) + { + if (c->savedName) + { + memcpy(tmp,c->savedName,c->savedNameLen>255?255:c->savedNameLen); + tmp[c->savedNameLen>255?256:c->savedNameLen]=0; + if (nxagentFontLookUp(tmp)) + break; + else tmp[0]=0; + } + } + else + { + memcpy(tmp,name,namelen>255?255:namelen); + tmp[namelen>255?256:namelen]=0; + if (nxagentFontLookUp(tmp)) + break; + else tmp[0]=0; + } + } + + /* + * 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 = (char *)xalloc(namelen + 1); + if (c->savedName) + { + memmove(c->savedName, name, namelen); + c->savedName[namelen] = '\0'; + } + 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 + */ +bail: +finish: + if (strlen(tmp)) + { +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "nxListFont changed (0) font to %s\n",tmp); +#endif + memcpy(oc->fontname, tmp, strlen(tmp)); + oc->fnamelen = strlen(tmp); + + oc->origFontName = oc->fontname; + oc->origFontNameLen = oc->fnamelen; + + } + else + { + for (i = 0; i < c->names->nnames; i++) + { + if (c->names->length[i] > 255) + continue; + else + { + memcpy(tmp, c->names->names[i], c->names->length[i]); + tmp[ c->names->length[i] ] = 0; + if (nxagentFontLookUp(tmp) == 0) + continue; + memcpy(oc->fontname, tmp, strlen(tmp)); + oc->fnamelen = strlen(tmp); + + oc->origFontName = oc->fontname; + oc->origFontNameLen = oc->fnamelen; + +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "nxListFont changed (1) font to %s\n",tmp); +#endif + break; + } + } + } + + if (c->slept) + { + ClientWakeup(client); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: nxdoListFont: client [%lx] wakeup.\n", client); +#endif + } + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->fpe_list); + if (c->savedName) xfree(c->savedName); + FreeFontNames(c->names); + xfree(c); + xfree(fss); + if (resolved) xfree(resolved); + + return doOpenFont(client, oc); +} + +int +nxOpenFont(client, fid, flags, lenfname, pfontname) + ClientPtr client; + XID fid; + Mask flags; + unsigned lenfname; + char *pfontname; +{ + nxFsPtr fss; + LFclosurePtr c; + OFclosurePtr oc; + int i; + FontPtr cached = (FontPtr)0; + +#ifdef FONTDEBUG + char *f; + f = (char *)xalloc(lenfname + 1); + memmove(f, pfontname, lenfname); + f[lenfname] = '\0'; + ErrorF("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; + } + } + if (!(fss = (nxFsPtr) xalloc(sizeof(nxFs)))) + return BadAlloc; + + if (!(c = (LFclosurePtr) xalloc(sizeof *c))) + { + xfree(fss); + return BadAlloc; + } + c->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) { + xfree(c); + xfree(fss); + return BadAlloc; + } + c->names = MakeFontNamesRecord(100); + if (!c->names) + { + xfree(c->fpe_list); + xfree(c); + xfree(fss); + return BadAlloc; + } + memmove( c->current.pattern, 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->num_fpes = num_fpes; + c->current.patlen = lenfname; + c->current.current_fpe = 0; + c->current.max_names = nxagentMaxFontNames; + c->current.list_started = FALSE; + c->current.private = 0; + c->haveSaved = FALSE; + c->slept = FALSE; + c->savedName = 0; + + oc = (OFclosurePtr) xalloc(sizeof(OFclosureRec)); + if (!oc) + { + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->fpe_list); + xfree(c); + xfree(fss); + return BadAlloc; + } + oc->fontname = (char *) xalloc(256);/* I don't want to deal with future reallocs errors */ + oc->origFontName = pfontname; + oc->origFontNameLen = lenfname; + if (!oc->fontname) { + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->fpe_list); + xfree(c); + xfree(oc); + xfree(fss); + 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 + */ + oc->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!oc->fpe_list) { + xfree(oc->fontname); + xfree(oc); + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->fpe_list); + xfree(c); + xfree(fss); + return BadAlloc; + } + memmove(oc->fontname, pfontname, lenfname); + for (i = 0; i < num_fpes; i++) { + oc->fpe_list[i] = font_path_elements[i]; + UseFPE(oc->fpe_list[i]); + } + oc->client = client; + oc->fontid = fid; + oc->current_fpe = 0; + oc->num_fpes = num_fpes; + oc->fnamelen = lenfname; + oc->slept = FALSE; + oc->flags = flags; + oc->non_cachable_font = cached; + fss->c=c; + fss->oc=oc; + nxdoListFontsAndAliases(client, fss); + return Success; +} +