diff options
Diffstat (limited to 'xorg-server/dix/dixfonts.c')
-rw-r--r-- | xorg-server/dix/dixfonts.c | 4236 |
1 files changed, 2112 insertions, 2124 deletions
diff --git a/xorg-server/dix/dixfonts.c b/xorg-server/dix/dixfonts.c index fec32bb98..ea3d9e276 100644 --- a/xorg-server/dix/dixfonts.c +++ b/xorg-server/dix/dixfonts.c @@ -1,2124 +1,2112 @@ -/************************************************************************ -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 -#include "xf86bigfontsrv.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 *) - realloc(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); - free(fpe->name); - free(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; - Bool fromDispatch = c->from_dispatch; - Bool finished = FALSE; - /* - * 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; - - c->from_dispatch = FALSE; - - 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 *) realloc(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 (!ClientIsAsleep(client)) - ClientSleep(client, (ClientSleepProcPtr)doOpenFont, c); - else - goto xinerama_sleep; - 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)); - } - ClientWakeup(c->client); - finished = TRUE; -xinerama_sleep: - if (finished || fromDispatch) { - for (i = 0; i < c->num_fpes; i++) { - FreeFPE(c->fpe_list[i]); - } - free(c->fpe_list); - free(c->fontname); - free(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 = malloc(lenfname + 1); - memmove(f, pfontname, lenfname); - f[lenfname] = '\0'; - ErrorF("[dix] OpenFont: fontname is \"%s\"\n", f); - free(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 = malloc(sizeof(OFclosureRec)); - if (!c) - return BadAlloc; - c->fontname = malloc(lenfname); - c->origFontName = pfontname; - c->origFontNameLen = lenfname; - if (!c->fontname) { - free(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 = malloc(sizeof(FontPathElementPtr) * num_fpes); - if (!c->fpe_list) { - free(c->fontname); - free(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->flags = flags; - c->from_dispatch = TRUE; - 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; - Bool fromDispatch = c->from_dispatch; - Bool finished = FALSE; - - c->from_dispatch = FALSE; - - 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 (!ClientIsAsleep(client)) - ClientSleep(client, - (ClientSleepProcPtr)doListFontsAndAliases, - c); - else - goto xinerama_sleep; - 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 (!ClientIsAsleep(client)) - ClientSleep(client, - (ClientSleepProcPtr)doListFontsAndAliases, - c); - else - goto xinerama_sleep; - 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 (!ClientIsAsleep(client)) - ClientSleep(client, - (ClientSleepProcPtr)doListFontsAndAliases, - c); - else - goto xinerama_sleep; - return TRUE; - } - if (err == FontNameAlias) { - free(resolved); - resolved = malloc(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; - free(c->savedName); - c->savedName = malloc(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 = malloc(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); - free(bufferStart); - -bail: - ClientWakeup(client); - finished = TRUE; -xinerama_sleep: - if (finished || fromDispatch) { - for (i = 0; i < c->num_fpes; i++) - FreeFPE(c->fpe_list[i]); - free(c->fpe_list); - free(c->savedName); - FreeFontNames(names); - free(c); - } - free(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 = malloc(sizeof *c))) - return BadAlloc; - c->fpe_list = malloc(sizeof(FontPathElementPtr) * num_fpes); - if (!c->fpe_list) { - free(c); - return BadAlloc; - } - c->names = MakeFontNamesRecord(max_names < 100 ? max_names : 100); - if (!c->names) - { - free(c->fpe_list); - free(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->from_dispatch = TRUE; - c->savedName = 0; - doListFontsAndAliases(client, c); - return Success; -} - -int -doListFontsWithInfo(ClientPtr client, LFWIclosurePtr c) -{ - FontPathElementPtr fpe; - int err = Successful; - char *name; - Bool fromDispatch = c->from_dispatch; - Bool finished = FALSE; - int namelen; - int numFonts; - FontInfoRec fontInfo, - *pFontInfo; - xListFontsWithInfoReply *reply; - int length; - xFontProp *pFP; - int i; - int aliascount = 0; - xListFontsWithInfoReply finalReply; - - c->from_dispatch = FALSE; - - 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 (!ClientIsAsleep(client)) - ClientSleep(client, - (ClientSleepProcPtr)doListFontsWithInfo, c); - else - goto xinerama_sleep; - 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 (!ClientIsAsleep(client)) - ClientSleep(client, - (ClientSleepProcPtr)doListFontsWithInfo, c); - else - goto xinerama_sleep; - 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; - free(c->savedName); - c->savedName = malloc(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 *) realloc(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) - { - free(fontInfo.props); - free(fontInfo.isStringProp); - } - --c->current.max_names; - } - } -finish: - length = sizeof(xListFontsWithInfoReply); - memset((char *) &finalReply, 0, sizeof(xListFontsWithInfoReply)); - finalReply.type = X_Reply; - finalReply.sequenceNumber = client->sequence; - finalReply.length = bytes_to_int32(sizeof(xListFontsWithInfoReply) - - sizeof(xGenericReply)); - WriteSwappedDataToClient(client, length, &finalReply); -bail: - ClientWakeup(client); - finished = TRUE; -xinerama_sleep: - if (finished || fromDispatch) { - for (i = 0; i < c->num_fpes; i++) - FreeFPE(c->fpe_list[i]); - free(c->reply); - free(c->fpe_list); - free(c->savedName); - free(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 = malloc(sizeof *c))) - goto badAlloc; - c->fpe_list = malloc(sizeof(FontPathElementPtr) * num_fpes); - if (!c->fpe_list) - { - free(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->from_dispatch = TRUE; - c->savedName = 0; - doListFontsWithInfo(client, c); - return Success; -badAlloc: - return BadAlloc; -} - -#define TextEltHeader 2 -#define FontShiftSize 5 -static ChangeGCVal clearGC[] = { NullPixmap }; -#define clearGCmask (GCClipMask) - -int -doPolyText(ClientPtr client, PTclosurePtr c) -{ - FontPtr pFont = c->pGC->font, oldpFont; - 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; - int itemSize = c->reqType == X_PolyText8 ? 1 : 2; - Bool fromDispatch = c->from_dispatch; - Bool finished = FALSE; - - c->from_dispatch = FALSE; - - if (client->clientGone) - { - fpe = c->pGC->font->fpe; - (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); - - if (ClientIsAsleep(client)) - { - /* 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 (ClientIsAsleep(client) && 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 = ClientIsAsleep(client) ? SLEEPING : NEVER_SLEPT; - - while (c->endReq - c->pElt > TextEltHeader) - { - if (*c->pElt == FontChange) - { - Font fid; - if (c->endReq - c->pElt < FontShiftSize) - { - err = BadLength; - goto bail; - } - - oldpFont = pFont; - - 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, DixUseAccess); - if (err != Success) - { - /* restore pFont for step 4 (described below) */ - pFont = oldpFont; - - /* 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) - { - ChangeGCVal val; - val.ptr = pFont; - ChangeGC(NullClient, c->pGC, GCFont, &val); - ValidateGC(c->pDraw, c->pGC); - } - - /* 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) * 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, itemSize, - c->pElt + TextEltHeader); - } - else lgerr = Successful; - - if (lgerr == Suspended) - { - if (!ClientIsAsleep(client)) { - 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 = malloc(sizeof(PTclosureRec)); - if (!new_closure) - { - err = BadAlloc; - goto bail; - } - *new_closure = *c; - c = new_closure; - - len = c->endReq - c->pElt; - c->data = malloc(len); - if (!c->data) - { - free(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) - { - free(c->data); - free(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); - free(c->data); - free(c); - err = BadAlloc; - goto bail; - } - origGC = c->pGC; - c->pGC = pGC; - ValidateGC(c->pDraw, c->pGC); - - ClientSleep(client, (ClientSleepProcPtr)doPolyText, c); - - /* Set up to perform steps 3 and 4 */ - client_state = START_SLEEP; - continue; /* on to steps 3 and 4 */ - } - else - goto xinerama_sleep; - return TRUE; - } - else if (lgerr != Successful) - { - err = FontToXError(lgerr); - goto bail; - } - if (c->pDraw) - { - c->xorg += *((INT8 *)(c->pElt + 1)); /* must be signed */ - if (c->reqType == X_PolyText8) - c->xorg = (* c->pGC->ops->PolyText8)(c->pDraw, c->pGC, c->xorg, c->yorg, - *c->pElt, (char *) (c->pElt + TextEltHeader)); - else - c->xorg = (* c->pGC->ops->PolyText16)(c->pDraw, c->pGC, c->xorg, c->yorg, - *c->pElt, (unsigned short *) (c->pElt + TextEltHeader)); - } - c->pElt = pNextElt; - } - } - -bail: - - if (client_state == START_SLEEP) - { - /* Step 4 */ - if (pFont != origGC->font) - { - ChangeGCVal val; - val.ptr = pFont; - ChangeGC(NullClient, origGC, GCFont, &val); - 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 (ClientIsAsleep(client)) - { - ClientWakeup(c->client); - finished = TRUE; -xinerama_sleep: - if (finished || fromDispatch) { - ChangeGC(NullClient, c->pGC, clearGCmask, clearGC); - - /* Unreference the font from the scratch GC */ - CloseFont(c->pGC->font, (Font)0); - c->pGC->font = NullFont; - - FreeScratchGC(c->pGC); - free(c->data); - free(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; - local_closure.reqType = reqType; - local_closure.pGC = pGC; - local_closure.did = did; - local_closure.err = Success; - - (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; - int itemSize = c->reqType == X_ImageText8 ? 1 : 2; - Bool fromDispatch = c->from_dispatch; - Bool finished = FALSE; - - c->from_dispatch = FALSE; - - 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 (ClientIsAsleep(client) && 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, itemSize, c->data); - if (lgerr == Suspended) - { - if (!ClientIsAsleep(client)) { - 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 = malloc(sizeof(ITclosureRec)); - if (!new_closure) - { - err = BadAlloc; - goto bail; - } - *new_closure = *c; - c = new_closure; - - data = malloc(c->nChars * itemSize); - if (!data) - { - free(c); - err = BadAlloc; - goto bail; - } - memmove(data, c->data, c->nChars * itemSize); - c->data = data; - - pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen); - if (!pGC) - { - free(c->data); - free(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); - free(c->data); - free(c); - err = BadAlloc; - goto bail; - } - c->pGC = pGC; - ValidateGC(c->pDraw, c->pGC); - - ClientSleep(client, (ClientSleepProcPtr)doImageText, c); - } - else - goto xinerama_sleep; - return TRUE; - } - else if (lgerr != Successful) - { - err = FontToXError(lgerr); - goto bail; - } - if (c->pDraw) - { - if (c->reqType == X_ImageText8) - (* c->pGC->ops->ImageText8)(c->pDraw, c->pGC, c->xorg, c->yorg, - c->nChars, (char *) c->data); - else - (* c->pGC->ops->ImageText16)(c->pDraw, c->pGC, c->xorg, c->yorg, - c->nChars, (unsigned short *) c->data); - } - -bail: - - if (err != Success && c->client != serverClient) { - SendErrorToClient(c->client, c->reqType, 0, 0, err); - } - if (ClientIsAsleep(client)) - { - ClientWakeup(c->client); - finished = TRUE; -xinerama_sleep: - if (finished || fromDispatch) { - ChangeGC(NullClient, c->pGC, clearGCmask, clearGC); - - /* Unreference the font from the scratch GC */ - CloseFont(c->pGC->font, (Font)0); - c->pGC->font = NullFont; - - FreeScratchGC(c->pGC); - free(c->data); - free(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; - local_closure.reqType = reqType; - local_closure.did = did; - - (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]); - } - free(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 = malloc(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 = malloc(sizeof(FontPathElementRec)); - if (!fpe) - { - err = BadAlloc; - goto bail; - } - fpe->name = malloc(len + 1); - if (!fpe->name) - { - free(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); - } - free(fpe->name); - free(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]); - free(fplist); - return FontToXError(err); -} - -int -SetFontPath(ClientPtr client, int npaths, unsigned char *paths) -{ - int err = XaceHook(XACE_SERVER_ACCESS, client, DixManageAccess); - if (err != Success) - return err; - - if (npaths == 0) { - if (SetDefaultFontPath(defaultFontPath) != Success) - return BadValue; - } else { - int bad; - err = SetFontPathElements(npaths, paths, &bad, FALSE); - client->errorValue = bad; - } - 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) { - if (asprintf(&temp_path, "%s%sbuilt-ins", path, *path ? "," : "") - == -1) - temp_path = NULL; - } else { - temp_path = strdup(path); - } - if (!temp_path) - return BadAlloc; - - /* get enough for string, plus values -- use up commas */ - len = strlen(temp_path) + 1; - nump = cp = newpath = malloc(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); - - free(newpath); - free(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 *) realloc(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(); - - 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 *) realloc(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; - free(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 XF86BIGFONT
+#include "xf86bigfontsrv.h"
+#endif
+
+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 *)
+ realloc(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);
+ free(fpe->name);
+ free(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;
+ Bool fromDispatch = c->from_dispatch;
+ Bool finished = FALSE;
+ /*
+ * 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;
+
+ c->from_dispatch = FALSE;
+
+ 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 *) realloc(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 (!ClientIsAsleep(client))
+ ClientSleep(client, (ClientSleepProcPtr)doOpenFont, c);
+ else
+ goto xinerama_sleep;
+ 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));
+ }
+ ClientWakeup(c->client);
+ finished = TRUE;
+xinerama_sleep:
+ if (finished || fromDispatch) {
+ for (i = 0; i < c->num_fpes; i++) {
+ FreeFPE(c->fpe_list[i]);
+ }
+ free(c->fpe_list);
+ free(c->fontname);
+ free(c);
+ }
+ return TRUE;
+}
+
+int
+OpenFont(ClientPtr client, XID fid, Mask flags, unsigned lenfname, char *pfontname)
+{
+ OFclosurePtr c;
+ int i;
+ FontPtr cached = (FontPtr)0;
+
+ 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 = malloc(sizeof(OFclosureRec));
+ if (!c)
+ return BadAlloc;
+ c->fontname = malloc(lenfname);
+ c->origFontName = pfontname;
+ c->origFontNameLen = lenfname;
+ if (!c->fontname) {
+ free(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 = malloc(sizeof(FontPathElementPtr) * num_fpes);
+ if (!c->fpe_list) {
+ free(c->fontname);
+ free(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->flags = flags;
+ c->from_dispatch = TRUE;
+ 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;
+ Bool fromDispatch = c->from_dispatch;
+ Bool finished = FALSE;
+
+ c->from_dispatch = FALSE;
+
+ 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 (!ClientIsAsleep(client))
+ ClientSleep(client,
+ (ClientSleepProcPtr)doListFontsAndAliases,
+ c);
+ else
+ goto xinerama_sleep;
+ 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 (!ClientIsAsleep(client))
+ ClientSleep(client,
+ (ClientSleepProcPtr)doListFontsAndAliases,
+ c);
+ else
+ goto xinerama_sleep;
+ 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 (!ClientIsAsleep(client))
+ ClientSleep(client,
+ (ClientSleepProcPtr)doListFontsAndAliases,
+ c);
+ else
+ goto xinerama_sleep;
+ return TRUE;
+ }
+ if (err == FontNameAlias) {
+ free(resolved);
+ resolved = malloc(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;
+ free(c->savedName);
+ c->savedName = malloc(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 = malloc(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);
+ free(bufferStart);
+
+bail:
+ ClientWakeup(client);
+ finished = TRUE;
+xinerama_sleep:
+ if (finished || fromDispatch) {
+ for (i = 0; i < c->num_fpes; i++)
+ FreeFPE(c->fpe_list[i]);
+ free(c->fpe_list);
+ free(c->savedName);
+ FreeFontNames(names);
+ free(c);
+ }
+ free(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 = malloc(sizeof *c)))
+ return BadAlloc;
+ c->fpe_list = malloc(sizeof(FontPathElementPtr) * num_fpes);
+ if (!c->fpe_list) {
+ free(c);
+ return BadAlloc;
+ }
+ c->names = MakeFontNamesRecord(max_names < 100 ? max_names : 100);
+ if (!c->names)
+ {
+ free(c->fpe_list);
+ free(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->from_dispatch = TRUE;
+ c->savedName = 0;
+ doListFontsAndAliases(client, c);
+ return Success;
+}
+
+int
+doListFontsWithInfo(ClientPtr client, LFWIclosurePtr c)
+{
+ FontPathElementPtr fpe;
+ int err = Successful;
+ char *name;
+ Bool fromDispatch = c->from_dispatch;
+ Bool finished = FALSE;
+ int namelen;
+ int numFonts;
+ FontInfoRec fontInfo,
+ *pFontInfo;
+ xListFontsWithInfoReply *reply;
+ int length;
+ xFontProp *pFP;
+ int i;
+ int aliascount = 0;
+ xListFontsWithInfoReply finalReply;
+
+ c->from_dispatch = FALSE;
+
+ 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 (!ClientIsAsleep(client))
+ ClientSleep(client,
+ (ClientSleepProcPtr)doListFontsWithInfo, c);
+ else
+ goto xinerama_sleep;
+ 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 (!ClientIsAsleep(client))
+ ClientSleep(client,
+ (ClientSleepProcPtr)doListFontsWithInfo, c);
+ else
+ goto xinerama_sleep;
+ 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;
+ free(c->savedName);
+ c->savedName = malloc(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 *) realloc(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)
+ {
+ free(fontInfo.props);
+ free(fontInfo.isStringProp);
+ }
+ --c->current.max_names;
+ }
+ }
+finish:
+ length = sizeof(xListFontsWithInfoReply);
+ memset((char *) &finalReply, 0, sizeof(xListFontsWithInfoReply));
+ finalReply.type = X_Reply;
+ finalReply.sequenceNumber = client->sequence;
+ finalReply.length = bytes_to_int32(sizeof(xListFontsWithInfoReply)
+ - sizeof(xGenericReply));
+ WriteSwappedDataToClient(client, length, &finalReply);
+bail:
+ ClientWakeup(client);
+ finished = TRUE;
+xinerama_sleep:
+ if (finished || fromDispatch) {
+ for (i = 0; i < c->num_fpes; i++)
+ FreeFPE(c->fpe_list[i]);
+ free(c->reply);
+ free(c->fpe_list);
+ free(c->savedName);
+ free(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 = malloc(sizeof *c)))
+ goto badAlloc;
+ c->fpe_list = malloc(sizeof(FontPathElementPtr) * num_fpes);
+ if (!c->fpe_list)
+ {
+ free(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->from_dispatch = TRUE;
+ c->savedName = 0;
+ doListFontsWithInfo(client, c);
+ return Success;
+badAlloc:
+ return BadAlloc;
+}
+
+#define TextEltHeader 2
+#define FontShiftSize 5
+static ChangeGCVal clearGC[] = { NullPixmap };
+#define clearGCmask (GCClipMask)
+
+int
+doPolyText(ClientPtr client, PTclosurePtr c)
+{
+ FontPtr pFont = c->pGC->font, oldpFont;
+ 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;
+ int itemSize = c->reqType == X_PolyText8 ? 1 : 2;
+ Bool fromDispatch = c->from_dispatch;
+ Bool finished = FALSE;
+
+ c->from_dispatch = FALSE;
+
+ if (client->clientGone)
+ {
+ fpe = c->pGC->font->fpe;
+ (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
+
+ if (ClientIsAsleep(client))
+ {
+ /* 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 (ClientIsAsleep(client) && 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 = ClientIsAsleep(client) ? SLEEPING : NEVER_SLEPT;
+
+ while (c->endReq - c->pElt > TextEltHeader)
+ {
+ if (*c->pElt == FontChange)
+ {
+ Font fid;
+ if (c->endReq - c->pElt < FontShiftSize)
+ {
+ err = BadLength;
+ goto bail;
+ }
+
+ oldpFont = pFont;
+
+ 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, DixUseAccess);
+ if (err != Success)
+ {
+ /* restore pFont for step 4 (described below) */
+ pFont = oldpFont;
+
+ /* 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)
+ {
+ ChangeGCVal val;
+ val.ptr = pFont;
+ ChangeGC(NullClient, c->pGC, GCFont, &val);
+ ValidateGC(c->pDraw, c->pGC);
+ }
+
+ /* 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) * 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, itemSize,
+ c->pElt + TextEltHeader);
+ }
+ else lgerr = Successful;
+
+ if (lgerr == Suspended)
+ {
+ if (!ClientIsAsleep(client)) {
+ 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 = malloc(sizeof(PTclosureRec));
+ if (!new_closure)
+ {
+ err = BadAlloc;
+ goto bail;
+ }
+ *new_closure = *c;
+ c = new_closure;
+
+ len = c->endReq - c->pElt;
+ c->data = malloc(len);
+ if (!c->data)
+ {
+ free(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)
+ {
+ free(c->data);
+ free(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);
+ free(c->data);
+ free(c);
+ err = BadAlloc;
+ goto bail;
+ }
+ origGC = c->pGC;
+ c->pGC = pGC;
+ ValidateGC(c->pDraw, c->pGC);
+
+ ClientSleep(client, (ClientSleepProcPtr)doPolyText, c);
+
+ /* Set up to perform steps 3 and 4 */
+ client_state = START_SLEEP;
+ continue; /* on to steps 3 and 4 */
+ }
+ else
+ goto xinerama_sleep;
+ return TRUE;
+ }
+ else if (lgerr != Successful)
+ {
+ err = FontToXError(lgerr);
+ goto bail;
+ }
+ if (c->pDraw)
+ {
+ c->xorg += *((INT8 *)(c->pElt + 1)); /* must be signed */
+ if (c->reqType == X_PolyText8)
+ c->xorg = (* c->pGC->ops->PolyText8)(c->pDraw, c->pGC, c->xorg, c->yorg,
+ *c->pElt, (char *) (c->pElt + TextEltHeader));
+ else
+ c->xorg = (* c->pGC->ops->PolyText16)(c->pDraw, c->pGC, c->xorg, c->yorg,
+ *c->pElt, (unsigned short *) (c->pElt + TextEltHeader));
+ }
+ c->pElt = pNextElt;
+ }
+ }
+
+bail:
+
+ if (client_state == START_SLEEP)
+ {
+ /* Step 4 */
+ if (pFont != origGC->font)
+ {
+ ChangeGCVal val;
+ val.ptr = pFont;
+ ChangeGC(NullClient, origGC, GCFont, &val);
+ 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 (ClientIsAsleep(client))
+ {
+ ClientWakeup(c->client);
+ finished = TRUE;
+xinerama_sleep:
+ if (finished || fromDispatch) {
+ ChangeGC(NullClient, c->pGC, clearGCmask, clearGC);
+
+ /* Unreference the font from the scratch GC */
+ CloseFont(c->pGC->font, (Font)0);
+ c->pGC->font = NullFont;
+
+ FreeScratchGC(c->pGC);
+ free(c->data);
+ free(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;
+ local_closure.reqType = reqType;
+ local_closure.pGC = pGC;
+ local_closure.did = did;
+ local_closure.err = Success;
+
+ (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;
+ int itemSize = c->reqType == X_ImageText8 ? 1 : 2;
+ Bool fromDispatch = c->from_dispatch;
+ Bool finished = FALSE;
+
+ c->from_dispatch = FALSE;
+
+ 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 (ClientIsAsleep(client) && 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, itemSize, c->data);
+ if (lgerr == Suspended)
+ {
+ if (!ClientIsAsleep(client)) {
+ 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 = malloc(sizeof(ITclosureRec));
+ if (!new_closure)
+ {
+ err = BadAlloc;
+ goto bail;
+ }
+ *new_closure = *c;
+ c = new_closure;
+
+ data = malloc(c->nChars * itemSize);
+ if (!data)
+ {
+ free(c);
+ err = BadAlloc;
+ goto bail;
+ }
+ memmove(data, c->data, c->nChars * itemSize);
+ c->data = data;
+
+ pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen);
+ if (!pGC)
+ {
+ free(c->data);
+ free(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);
+ free(c->data);
+ free(c);
+ err = BadAlloc;
+ goto bail;
+ }
+ c->pGC = pGC;
+ ValidateGC(c->pDraw, c->pGC);
+
+ ClientSleep(client, (ClientSleepProcPtr)doImageText, c);
+ }
+ else
+ goto xinerama_sleep;
+ return TRUE;
+ }
+ else if (lgerr != Successful)
+ {
+ err = FontToXError(lgerr);
+ goto bail;
+ }
+ if (c->pDraw)
+ {
+ if (c->reqType == X_ImageText8)
+ (* c->pGC->ops->ImageText8)(c->pDraw, c->pGC, c->xorg, c->yorg,
+ c->nChars, (char *) c->data);
+ else
+ (* c->pGC->ops->ImageText16)(c->pDraw, c->pGC, c->xorg, c->yorg,
+ c->nChars, (unsigned short *) c->data);
+ }
+
+bail:
+
+ if (err != Success && c->client != serverClient) {
+ SendErrorToClient(c->client, c->reqType, 0, 0, err);
+ }
+ if (ClientIsAsleep(client))
+ {
+ ClientWakeup(c->client);
+ finished = TRUE;
+xinerama_sleep:
+ if (finished || fromDispatch) {
+ ChangeGC(NullClient, c->pGC, clearGCmask, clearGC);
+
+ /* Unreference the font from the scratch GC */
+ CloseFont(c->pGC->font, (Font)0);
+ c->pGC->font = NullFont;
+
+ FreeScratchGC(c->pGC);
+ free(c->data);
+ free(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;
+ local_closure.reqType = reqType;
+ local_closure.did = did;
+
+ (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]);
+ }
+ free(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 = malloc(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 = malloc(sizeof(FontPathElementRec));
+ if (!fpe)
+ {
+ err = BadAlloc;
+ goto bail;
+ }
+ fpe->name = malloc(len + 1);
+ if (!fpe->name)
+ {
+ free(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);
+ }
+ free(fpe->name);
+ free(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]);
+ free(fplist);
+ return FontToXError(err);
+}
+
+int
+SetFontPath(ClientPtr client, int npaths, unsigned char *paths)
+{
+ int err = XaceHook(XACE_SERVER_ACCESS, client, DixManageAccess);
+ if (err != Success)
+ return err;
+
+ if (npaths == 0) {
+ if (SetDefaultFontPath(defaultFontPath) != Success)
+ return BadValue;
+ } else {
+ int bad;
+ err = SetFontPathElements(npaths, paths, &bad, FALSE);
+ client->errorValue = bad;
+ }
+ 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) {
+ if (asprintf(&temp_path, "%s%sbuilt-ins", path, *path ? "," : "")
+ == -1)
+ temp_path = NULL;
+ } else {
+ temp_path = strdup(path);
+ }
+ if (!temp_path)
+ return BadAlloc;
+
+ /* get enough for string, plus values -- use up commas */
+ len = strlen(temp_path) + 1;
+ nump = cp = newpath = malloc(len);
+ if (!newpath) {
+ free(temp_path);
+ 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);
+
+ free(newpath);
+ free(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 *) realloc(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();
+
+ 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 *) realloc(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;
+ free(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);
+}
|