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