diff options
Diffstat (limited to 'xorg-server/dix/dixfonts.c')
-rw-r--r-- | xorg-server/dix/dixfonts.c | 4224 |
1 files changed, 2112 insertions, 2112 deletions
diff --git a/xorg-server/dix/dixfonts.c b/xorg-server/dix/dixfonts.c index ea3d9e276..45655de78 100644 --- a/xorg-server/dix/dixfonts.c +++ b/xorg-server/dix/dixfonts.c @@ -1,2112 +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 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);
-}
+/************************************************************************ +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); +} |