From 49c7992dfc9c6b8a60baf1afbede4616e0265e7f Mon Sep 17 00:00:00 2001
From: marha <marha@users.sourceforge.net>
Date: Sun, 9 May 2010 21:09:18 +0000
Subject: xserver git update 9/5/2010

---
 xorg-server/Xext/xf86bigfont.c | 1528 ++++++++++++++++++++--------------------
 1 file changed, 759 insertions(+), 769 deletions(-)

(limited to 'xorg-server/Xext')

diff --git a/xorg-server/Xext/xf86bigfont.c b/xorg-server/Xext/xf86bigfont.c
index a4eb3f659..8e8d460e5 100644
--- a/xorg-server/Xext/xf86bigfont.c
+++ b/xorg-server/Xext/xf86bigfont.c
@@ -1,769 +1,759 @@
-/*
- * BIGFONT extension for sharing font metrics between clients (if possible)
- * and for transmitting font metrics to clients in a compressed form.
- *
- * Copyright (c) 1999-2000  Bruno Haible
- * Copyright (c) 1999-2000  The XFree86 Project, Inc.
- */
-
-/* THIS IS NOT AN X CONSORTIUM STANDARD */
-
-/*
- * Big fonts suffer from the following: All clients that have opened a
- * font can access the complete glyph metrics array (the XFontStruct member
- * `per_char') directly, without going through a macro. Moreover these
- * glyph metrics are ink metrics, i.e. are not redundant even for a
- * fixed-width font. For a Unicode font, the size of this array is 768 KB.
- *
- * Problems: 1. It eats a lot of memory in each client. 2. All this glyph
- * metrics data is piped through the socket when the font is opened.
- *
- * This extension addresses these two problems for local clients, by using
- * shared memory. It also addresses the second problem for non-local clients,
- * by compressing the data before transmit by a factor of nearly 6.
- *
- * If you use this extension, your OS ought to nicely support shared memory.
- * This means: Shared memory should be swappable to the swap, and the limits
- * should be high enough (SHMMNI at least 64, SHMMAX at least 768 KB,
- * SHMALL at least 48 MB). It is a plus if your OS allows shmat() calls
- * on segments that have already been marked "removed", because it permits
- * these segments to be cleaned up by the OS if the X server is killed with
- * signal SIGKILL.
- *
- * This extension is transparently exploited by Xlib (functions XQueryFont,
- * XLoadQueryFont).
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <sys/types.h>
-#ifdef HAS_SHM
-#if defined(linux) && (!defined(__GNU_LIBRARY__) || __GNU_LIBRARY__ < 2)
-/* libc4 does not define __GNU_LIBRARY__, libc5 defines __GNU_LIBRARY__ as 1 */
-/* Linux libc4 and libc5 only (because glibc doesn't include kernel headers):
-   Linux 2.0.x and 2.2.x define SHMLBA as PAGE_SIZE, but forget to define
-   PAGE_SIZE. It is defined in <asm/page.h>. */
-#include <asm/page.h>
-#endif
-#ifdef SVR4
-#include <sys/sysmacros.h>
-#endif
-#if defined(__CYGWIN__) || defined(__SCO__)
-#include <sys/param.h>
-#include <sys/sysmacros.h>
-#endif
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#include <sys/stat.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <time.h>
-#include <errno.h>
-#endif
-
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include "misc.h"
-#include "os.h"
-#include "dixstruct.h"
-#include "gcstruct.h"
-#include "dixfontstr.h"
-#include "extnsionst.h"
-#include "protocol-versions.h"
-
-#include <X11/extensions/xf86bigfproto.h>
-#include "xf86bigfontsrv.h"
-
-static void XF86BigfontResetProc(
-    ExtensionEntry *	/* extEntry */
-    );
-
-static DISPATCH_PROC(ProcXF86BigfontDispatch);
-static DISPATCH_PROC(ProcXF86BigfontQueryVersion);
-static DISPATCH_PROC(ProcXF86BigfontQueryFont);
-static DISPATCH_PROC(SProcXF86BigfontDispatch);
-static DISPATCH_PROC(SProcXF86BigfontQueryVersion);
-static DISPATCH_PROC(SProcXF86BigfontQueryFont);
-
-#ifdef HAS_SHM
-
-/* A random signature, transmitted to the clients so they can verify that the
-   shared memory segment they are attaching to was really established by the
-   X server they are talking to. */
-static CARD32 signature;
-
-/* Index for additional information stored in a FontRec's devPrivates array. */
-static int FontShmdescIndex;
-
-static unsigned int pagesize;
-
-static Bool badSysCall = FALSE;
-
-#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) || defined(__DragonFly__)
-
-#include <sys/signal.h>
-
-static void
-SigSysHandler(
-     int signo)
-{
-    badSysCall = TRUE;
-}
-
-static Bool
-CheckForShmSyscall(void)
-{
-    void (*oldHandler)(int);
-    int shmid = -1;
-
-    /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */
-    oldHandler = signal(SIGSYS, SigSysHandler);
-
-    badSysCall = FALSE;
-    shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT);
-    if (shmid != -1)
-    {
-        /* Successful allocation - clean up */
-	shmctl(shmid, IPC_RMID, NULL);
-    }
-    else
-    {
-        /* Allocation failed */
-        badSysCall = TRUE;
-    }
-    signal(SIGSYS, oldHandler);
-    return (!badSysCall);
-}
-
-#define MUST_CHECK_FOR_SHM_SYSCALL
-
-#endif
-
-#endif
-
-void
-XFree86BigfontExtensionInit(void)
-{
-    if (AddExtension(XF86BIGFONTNAME,
-		     XF86BigfontNumberEvents,
-		     XF86BigfontNumberErrors,
-		     ProcXF86BigfontDispatch,
-		     SProcXF86BigfontDispatch,
-		     XF86BigfontResetProc,
-		     StandardMinorOpcode)) {
-#ifdef HAS_SHM
-#ifdef MUST_CHECK_FOR_SHM_SYSCALL
-	/*
-	 * Note: Local-clients will not be optimized without shared memory
-	 * support. Remote-client optimization does not depend on shared
-	 * memory support.  Thus, the extension is still registered even
-	 * when shared memory support is not functional.  
-	 */
-	if (!CheckForShmSyscall()) {
-	    ErrorF(XF86BIGFONTNAME " extension local-client optimization disabled due to lack of shared memory support in the kernel\n");
-	    return;
-	}
-#endif
-
-	srand((unsigned int) time(NULL));
-	signature = ((unsigned int) (65536.0/(RAND_MAX+1.0) * rand()) << 16)
-	           + (unsigned int) (65536.0/(RAND_MAX+1.0) * rand());
-	/* fprintf(stderr, "signature = 0x%08X\n", signature); */
-
-	FontShmdescIndex = AllocateFontPrivateIndex();
-
-#if !defined(CSRG_BASED) && !defined(__CYGWIN__)
-	pagesize = SHMLBA;
-#else
-# ifdef _SC_PAGESIZE
-	pagesize = sysconf(_SC_PAGESIZE);
-# else
-	pagesize = getpagesize();
-# endif
-#endif
-#endif
-    }
-}
-
-
-/* ========== Management of shared memory segments ========== */
-
-#ifdef HAS_SHM
-
-#ifdef __linux__
-/* On Linux, shared memory marked as "removed" can still be attached.
-   Nice feature, because the kernel will automatically free the associated
-   storage when the server and all clients are gone. */
-#define EARLY_REMOVE
-#endif
-
-typedef struct _ShmDesc {
-    struct _ShmDesc *next;
-    struct _ShmDesc **prev;
-    int shmid;
-    char *attach_addr;
-} ShmDescRec, *ShmDescPtr;
-
-static ShmDescPtr ShmList = (ShmDescPtr) NULL;
-
-static ShmDescPtr
-shmalloc(
-    unsigned int size)
-{
-    ShmDescPtr pDesc;
-    int shmid;
-    char *addr;
-
-#ifdef MUST_CHECK_FOR_SHM_SYSCALL
-    if (pagesize == 0)
-	return (ShmDescPtr) NULL;
-#endif
-
-    /* On some older Linux systems, the number of shared memory segments
-       system-wide is 127. In Linux 2.4, it is 4095.
-       Therefore there is a tradeoff to be made between allocating a
-       shared memory segment on one hand, and allocating memory and piping
-       the glyph metrics on the other hand. If the glyph metrics size is
-       small, we prefer the traditional way. */
-    if (size < 3500)
-	return (ShmDescPtr) NULL;
-
-    pDesc = xalloc(sizeof(ShmDescRec));
-    if (!pDesc)
-	return (ShmDescPtr) NULL;
-
-    size = (size + pagesize-1) & -pagesize;
-    shmid = shmget(IPC_PRIVATE, size, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
-    if (shmid == -1) {
-	ErrorF(XF86BIGFONTNAME " extension: shmget() failed, size = %u, %s\n",
-	       size, strerror(errno));
-	xfree(pDesc);
-	return (ShmDescPtr) NULL;
-    }
-
-    if ((addr = shmat(shmid, 0, 0)) == (char *)-1) {
-	ErrorF(XF86BIGFONTNAME " extension: shmat() failed, size = %u, %s\n",
-	       size, strerror(errno));
-	shmctl(shmid, IPC_RMID, (void *) 0);
-	xfree(pDesc);
-	return (ShmDescPtr) NULL;
-    }
-
-#ifdef EARLY_REMOVE
-    shmctl(shmid, IPC_RMID, (void *) 0);
-#endif
-
-    pDesc->shmid = shmid;
-    pDesc->attach_addr = addr;
-    if (ShmList) ShmList->prev = &pDesc->next;
-    pDesc->next = ShmList;
-    pDesc->prev = &ShmList;
-    ShmList = pDesc;
-
-    return pDesc;
-}
-
-static void
-shmdealloc(
-    ShmDescPtr pDesc)
-{
-#ifndef EARLY_REMOVE
-    shmctl(pDesc->shmid, IPC_RMID, (void *) 0);
-#endif
-    shmdt(pDesc->attach_addr);
-
-    if (pDesc->next) pDesc->next->prev = pDesc->prev;
-    *pDesc->prev = pDesc->next;
-    xfree(pDesc);
-}
-
-#endif
-
-/* Called when a font is closed. */
-void
-XF86BigfontFreeFontShm(
-    FontPtr pFont)
-{
-#ifdef HAS_SHM
-    ShmDescPtr pDesc;
-
-    /* If during shutdown of the server, XF86BigfontCleanup() has already
-     * called shmdealloc() for all segments, we don't need to do it here.
-     */
-    if (!ShmList)
-	return;
-
-    pDesc = (ShmDescPtr) FontGetPrivate(pFont, FontShmdescIndex);
-    if (pDesc)
-	shmdealloc(pDesc);
-#endif
-}
-
-/* Called upon fatal signal. */
-void
-XF86BigfontCleanup(void)
-{
-#ifdef HAS_SHM
-    while (ShmList)
-	shmdealloc(ShmList);
-#endif
-}
-
-/* Called when a server generation dies. */
-static void
-XF86BigfontResetProc(
-    ExtensionEntry* extEntry)
-{
-    /* This function is normally called from CloseDownExtensions(), called
-     * from main(). It will be followed by a call to FreeAllResources(),
-     * which will call XF86BigfontFreeFontShm() for each font. Thus it
-     * appears that we do not need to do anything in this function. --
-     * But I prefer to write robust code, and not keep shared memory lying
-     * around when it's not needed any more. (Someone might close down the
-     * extension without calling FreeAllResources()...)
-     */
-    XF86BigfontCleanup();
-}
-
-
-/* ========== Handling of extension specific requests ========== */
-
-static int
-ProcXF86BigfontQueryVersion(
-    ClientPtr client)
-{
-    xXF86BigfontQueryVersionReply reply;
-
-    REQUEST_SIZE_MATCH(xXF86BigfontQueryVersionReq);
-    reply.type = X_Reply;
-    reply.length = 0;
-    reply.sequenceNumber = client->sequence;
-    reply.majorVersion = SERVER_XF86BIGFONT_MAJOR_VERSION;
-    reply.minorVersion = SERVER_XF86BIGFONT_MINOR_VERSION;
-    reply.uid = geteuid();
-    reply.gid = getegid();
-#ifdef HAS_SHM
-    reply.signature = signature;
-#else
-    reply.signature = 0; /* This is redundant. Avoids uninitialized memory. */
-#endif
-    reply.capabilities =
-#ifdef HAS_SHM
-	(LocalClient(client) && !client->swapped ? XF86Bigfont_CAP_LocalShm : 0)
-#else
-	0
-#endif
-	; /* may add more bits here in future versions */
-    if (client->swapped) {
-	char tmp;
-	swaps(&reply.sequenceNumber, tmp);
-	swapl(&reply.length, tmp);
-	swaps(&reply.majorVersion, tmp);
-	swaps(&reply.minorVersion, tmp);
-	swapl(&reply.uid, tmp);
-	swapl(&reply.gid, tmp);
-	swapl(&reply.signature, tmp);
-    }
-    WriteToClient(client,
-		  sizeof(xXF86BigfontQueryVersionReply), (char *)&reply);
-    return client->noClientException;
-}
-
-static void
-swapCharInfo(
-    xCharInfo *pCI)
-{
-    char tmp;
-
-    swaps(&pCI->leftSideBearing, tmp);
-    swaps(&pCI->rightSideBearing, tmp);
-    swaps(&pCI->characterWidth, tmp);
-    swaps(&pCI->ascent, tmp);
-    swaps(&pCI->descent, tmp);
-    swaps(&pCI->attributes, tmp);
-}
-
-/* static CARD32 hashCI (xCharInfo *p); */
-#define hashCI(p) \
-	(CARD32)(((p->leftSideBearing << 27) + (p->leftSideBearing >> 5) + \
-	          (p->rightSideBearing << 23) + (p->rightSideBearing >> 9) + \
-	          (p->characterWidth << 16) + \
-	          (p->ascent << 11) + (p->descent << 6)) ^ p->attributes)
-
-static int
-ProcXF86BigfontQueryFont(
-    ClientPtr client)
-{
-    FontPtr pFont;
-    REQUEST(xXF86BigfontQueryFontReq);
-    CARD32 stuff_flags;
-    xCharInfo* pmax;
-    xCharInfo* pmin;
-    int nCharInfos;
-    int shmid;
-#ifdef HAS_SHM
-    ShmDescPtr pDesc;
-#else
-#define pDesc 0
-#endif
-    xCharInfo* pCI;
-    CARD16* pIndex2UniqIndex;
-    CARD16* pUniqIndex2Index;
-    CARD32 nUniqCharInfos;
-
-#if 0
-    REQUEST_SIZE_MATCH(xXF86BigfontQueryFontReq);
-#else
-    switch (client->req_len) {
-	case 2: /* client with version 1.0 libX11 */
-	    stuff_flags = (LocalClient(client) && !client->swapped ? XF86Bigfont_FLAGS_Shm : 0);
-	    break;
-	case 3: /* client with version 1.1 libX11 */
-	    stuff_flags = stuff->flags;
-	    break;
-	default:
-	    return BadLength;
-    }
-#endif
-    client->errorValue = stuff->id;		/* EITHER font or gc */
-    dixLookupResourceByType((pointer *)&pFont, stuff->id, RT_FONT,
-			    client, DixGetAttrAccess);
-    if (!pFont) {
-	GC *pGC;
-	dixLookupResourceByType((pointer *)&pGC, stuff->id, RT_GC,
-				client, DixGetAttrAccess);
-        if (!pGC)
-            return BadFont;    /* procotol spec says only error is BadFont */
-
-	pFont = pGC->font;
-    }
-
-    pmax = FONTINKMAX(pFont);
-    pmin = FONTINKMIN(pFont);
-    nCharInfos =
-       (pmax->rightSideBearing == pmin->rightSideBearing
-        && pmax->leftSideBearing == pmin->leftSideBearing
-        && pmax->descent == pmin->descent
-        && pmax->ascent == pmin->ascent
-        && pmax->characterWidth == pmin->characterWidth)
-       ? 0 : N2dChars(pFont);
-    shmid = -1;
-    pCI = NULL;
-    pIndex2UniqIndex = NULL;
-    pUniqIndex2Index = NULL;
-    nUniqCharInfos = 0;
-
-    if (nCharInfos > 0) {
-#ifdef HAS_SHM
-	if (!badSysCall)
-	    pDesc = (ShmDescPtr) FontGetPrivate(pFont, FontShmdescIndex);
-	else
-	    pDesc = NULL;
-	if (pDesc) {
-	    pCI = (xCharInfo *) pDesc->attach_addr;
-	    if (stuff_flags & XF86Bigfont_FLAGS_Shm)
-		shmid = pDesc->shmid;
-	} else {
-	    if (stuff_flags & XF86Bigfont_FLAGS_Shm && !badSysCall)
-		pDesc = shmalloc(nCharInfos * sizeof(xCharInfo)
-				 + sizeof(CARD32));
-	    if (pDesc) {
-		pCI = (xCharInfo *) pDesc->attach_addr;
-		shmid = pDesc->shmid;
-	    } else {
-#endif
-		pCI = xalloc(nCharInfos * sizeof(xCharInfo));
-		if (!pCI)
-		    return BadAlloc;
-#ifdef HAS_SHM
-	    }
-#endif
-	    /* Fill nCharInfos starting at pCI. */
-	    {
-		xCharInfo* prCI = pCI;
-		int ninfos = 0;
-		int ncols = pFont->info.lastCol - pFont->info.firstCol + 1;
-		int row;
-		for (row = pFont->info.firstRow;
-		     row <= pFont->info.lastRow && ninfos < nCharInfos;
-		     row++) {
-		    unsigned char chars[512];
-		    xCharInfo* tmpCharInfos[256];
-		    unsigned long count;
-		    int col;
-		    unsigned long i;
-		    i = 0;
-		    for (col = pFont->info.firstCol;
-			 col <= pFont->info.lastCol;
-			 col++) {
-			chars[i++] = row;
-			chars[i++] = col;
-		    }
-		    (*pFont->get_metrics) (pFont, ncols, chars, TwoD16Bit,
-					   &count, tmpCharInfos);
-		    for (i = 0; i < count && ninfos < nCharInfos; i++) {
-			*prCI++ = *tmpCharInfos[i];
-			ninfos++;
-		    }
-		}
-	    }
-#ifdef HAS_SHM
-	    if (pDesc && !badSysCall) {
-		*(CARD32 *)(pCI + nCharInfos) = signature;
-		if (!FontSetPrivate(pFont, FontShmdescIndex, pDesc)) {
-		    shmdealloc(pDesc);
-		    return BadAlloc;
-		}
-	    }
-	}
-#endif
-	if (shmid == -1) {
-	    /* Cannot use shared memory, so remove-duplicates the xCharInfos
-	       using a temporary hash table. */
-	    /* Note that CARD16 is suitable as index type, because
-	       nCharInfos <= 0x10000. */
-	    CARD32 hashModulus;
-	    CARD16* pHash2UniqIndex;
-	    CARD16* pUniqIndex2NextUniqIndex;
-	    CARD32 NextIndex;
-	    CARD32 NextUniqIndex;
-	    CARD16* tmp;
-	    CARD32 i, j;
-
-	    hashModulus = 67;
-	    if (hashModulus > nCharInfos+1)
-		hashModulus = nCharInfos+1;
-
-	    tmp = xalloc((4*nCharInfos+1) * sizeof(CARD16));
-	    if (!tmp) {
-		if (!pDesc) xfree(pCI);
-		return BadAlloc;
-	    }
-	    pIndex2UniqIndex = tmp;
-		/* nCharInfos elements */
-	    pUniqIndex2Index = tmp + nCharInfos;
-		/* max. nCharInfos elements */
-	    pUniqIndex2NextUniqIndex = tmp + 2*nCharInfos;
-		/* max. nCharInfos elements */
-	    pHash2UniqIndex = tmp + 3*nCharInfos;
-		/* hashModulus (<= nCharInfos+1) elements */
-
-	    /* Note that we can use 0xffff as end-of-list indicator, because
-	       even if nCharInfos = 0x10000, 0xffff can not occur as valid
-	       entry before the last element has been inserted. And once the
-	       last element has been inserted, we don't need the hash table
-	       any more. */
-	    for (j = 0; j < hashModulus; j++)
-		pHash2UniqIndex[j] = (CARD16)(-1);
-
-	    NextUniqIndex = 0;
-	    for (NextIndex = 0; NextIndex < nCharInfos; NextIndex++) {
-		xCharInfo* p = &pCI[NextIndex];
-		CARD32 hashCode = hashCI(p) % hashModulus;
-		for (i = pHash2UniqIndex[hashCode];
-		     i != (CARD16)(-1);
-		     i = pUniqIndex2NextUniqIndex[i]) {
-		    j = pUniqIndex2Index[i];
-		    if (pCI[j].leftSideBearing == p->leftSideBearing
-			&& pCI[j].rightSideBearing == p->rightSideBearing
-			&& pCI[j].characterWidth == p->characterWidth
-			&& pCI[j].ascent == p->ascent
-			&& pCI[j].descent == p->descent
-			&& pCI[j].attributes == p->attributes)
-			break;
-		}
-		if (i != (CARD16)(-1)) {
-		    /* Found *p at Index j, UniqIndex i */
-		    pIndex2UniqIndex[NextIndex] = i;
-		} else {
-		    /* Allocate a new entry in the Uniq table */
-		    if (hashModulus <= 2*NextUniqIndex
-			&& hashModulus < nCharInfos+1) {
-			/* Time to increate hash table size */
-			hashModulus = 2*hashModulus+1;
-			if (hashModulus > nCharInfos+1)
-			    hashModulus = nCharInfos+1;
-			for (j = 0; j < hashModulus; j++)
-			    pHash2UniqIndex[j] = (CARD16)(-1);
-			for (i = 0; i < NextUniqIndex; i++)
-			    pUniqIndex2NextUniqIndex[i] = (CARD16)(-1);
-			for (i = 0; i < NextUniqIndex; i++) {
-			    j = pUniqIndex2Index[i];
-			    p = &pCI[j];
-			    hashCode = hashCI(p) % hashModulus;
-			    pUniqIndex2NextUniqIndex[i] = pHash2UniqIndex[hashCode];
-			    pHash2UniqIndex[hashCode] = i;
-			}
-			p = &pCI[NextIndex];
-			hashCode = hashCI(p) % hashModulus;
-		    }
-		    i = NextUniqIndex++;
-		    pUniqIndex2NextUniqIndex[i] = pHash2UniqIndex[hashCode];
-		    pHash2UniqIndex[hashCode] = i;
-		    pUniqIndex2Index[i] = NextIndex;
-		    pIndex2UniqIndex[NextIndex] = i;
-		}
-	    }
-	    nUniqCharInfos = NextUniqIndex;
-	    /* fprintf(stderr, "font metrics: nCharInfos = %d, nUniqCharInfos = %d, hashModulus = %d\n", nCharInfos, nUniqCharInfos, hashModulus); */
-	}
-    }
-
-    {
-	int nfontprops = pFont->info.nprops;
-	int rlength =
-	   sizeof(xXF86BigfontQueryFontReply)
-	   + nfontprops * sizeof(xFontProp)
-	   + (nCharInfos > 0 && shmid == -1
-	      ? nUniqCharInfos * sizeof(xCharInfo)
-	        + (nCharInfos+1)/2 * 2 * sizeof(CARD16)
-	      : 0);
-	xXF86BigfontQueryFontReply* reply = xalloc(rlength);
-	char* p;
-	if (!reply) {
-	    if (nCharInfos > 0) {
-		if (shmid == -1) xfree(pIndex2UniqIndex);
-		if (!pDesc) xfree(pCI);
-	    }
-	    return BadAlloc;
-	}
-	reply->type = X_Reply;
-	reply->length = bytes_to_int32(rlength - sizeof(xGenericReply));
-	reply->sequenceNumber = client->sequence;
-	reply->minBounds = pFont->info.ink_minbounds;
-	reply->maxBounds = pFont->info.ink_maxbounds;
-	reply->minCharOrByte2 = pFont->info.firstCol;
-	reply->maxCharOrByte2 = pFont->info.lastCol;
-	reply->defaultChar = pFont->info.defaultCh;
-	reply->nFontProps = pFont->info.nprops;
-	reply->drawDirection = pFont->info.drawDirection;
-	reply->minByte1 = pFont->info.firstRow;
-	reply->maxByte1 = pFont->info.lastRow;
-	reply->allCharsExist = pFont->info.allExist;
-	reply->fontAscent = pFont->info.fontAscent;
-	reply->fontDescent = pFont->info.fontDescent;
-	reply->nCharInfos = nCharInfos;
-        reply->nUniqCharInfos = nUniqCharInfos;
-	reply->shmid = shmid;
-	reply->shmsegoffset = 0;
-	if (client->swapped) {
-	    char tmp;
-	    swaps(&reply->sequenceNumber, tmp);
-	    swapl(&reply->length, tmp);
-	    swapCharInfo(&reply->minBounds);
-	    swapCharInfo(&reply->maxBounds);
-	    swaps(&reply->minCharOrByte2, tmp);
-	    swaps(&reply->maxCharOrByte2, tmp);
-	    swaps(&reply->defaultChar, tmp);
-	    swaps(&reply->nFontProps, tmp);
-	    swaps(&reply->fontAscent, tmp);
-	    swaps(&reply->fontDescent, tmp);
-	    swapl(&reply->nCharInfos, tmp);
-	    swapl(&reply->nUniqCharInfos, tmp);
-	    swapl(&reply->shmid, tmp);
-	    swapl(&reply->shmsegoffset, tmp);
-	}
-	p = (char*) &reply[1];
-	{
-	    FontPropPtr pFP;
-	    xFontProp* prFP;
-	    int i;
-	    for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) p;
-		 i < nfontprops;
-		 i++, pFP++, prFP++) {
-		prFP->name = pFP->name;
-		prFP->value = pFP->value;
-		if (client->swapped) {
-		    char tmp;
-		    swapl(&prFP->name, tmp);
-		    swapl(&prFP->value, tmp);
-		}
-	    }
-	    p = (char*) prFP;
-	}
-	if (nCharInfos > 0 && shmid == -1) {
-	    xCharInfo* pci;
-	    CARD16* ps;
-	    int i, j;
-	    pci = (xCharInfo*) p;
-	    for (i = 0; i < nUniqCharInfos; i++, pci++) {
-		*pci = pCI[pUniqIndex2Index[i]];
-		if (client->swapped)
-		    swapCharInfo(pci);
-	    }
-	    ps = (CARD16*) pci;
-	    for (j = 0; j < nCharInfos; j++, ps++) {
-		*ps = pIndex2UniqIndex[j];
-		if (client->swapped) {
-		    char tmp;
-		    swaps(ps, tmp);
-		}
-	    }
-	}
-	WriteToClient(client, rlength, (char *)reply);
-	xfree(reply);
-	if (nCharInfos > 0) {
-	    if (shmid == -1) xfree(pIndex2UniqIndex);
-	    if (!pDesc) xfree(pCI);
-	}
-	return (client->noClientException);
-    }
-}
-
-static int
-ProcXF86BigfontDispatch(
-    ClientPtr client)
-{
-    REQUEST(xReq);
-
-    switch (stuff->data) {
-	case X_XF86BigfontQueryVersion:
-	    return ProcXF86BigfontQueryVersion(client);
-	case X_XF86BigfontQueryFont:
-	    return ProcXF86BigfontQueryFont(client);
-	default:
-	    return BadRequest;
-    }
-}
-
-static int
-SProcXF86BigfontQueryVersion(
-    ClientPtr client)
-{
-    REQUEST(xXF86BigfontQueryVersionReq);
-    char tmp;
-
-    swaps(&stuff->length, tmp);
-    return ProcXF86BigfontQueryVersion(client);
-}
-
-static int
-SProcXF86BigfontQueryFont(
-    ClientPtr client)
-{
-    REQUEST(xXF86BigfontQueryFontReq);
-    char tmp;
-
-    swaps(&stuff->length, tmp);
-    REQUEST_SIZE_MATCH(xXF86BigfontQueryFontReq);
-    swapl(&stuff->id, tmp);
-    return ProcXF86BigfontQueryFont(client);
-}
-
-static int
-SProcXF86BigfontDispatch(
-    ClientPtr client)
-{
-    REQUEST(xReq);
-
-    switch (stuff->data) {
-	case X_XF86BigfontQueryVersion:
-	    return SProcXF86BigfontQueryVersion(client);
-	case X_XF86BigfontQueryFont:
-	    return SProcXF86BigfontQueryFont(client);
-	default:
-	    return BadRequest;
-    }
-}
+/*
+ * BIGFONT extension for sharing font metrics between clients (if possible)
+ * and for transmitting font metrics to clients in a compressed form.
+ *
+ * Copyright (c) 1999-2000  Bruno Haible
+ * Copyright (c) 1999-2000  The XFree86 Project, Inc.
+ */
+
+/* THIS IS NOT AN X CONSORTIUM STANDARD */
+
+/*
+ * Big fonts suffer from the following: All clients that have opened a
+ * font can access the complete glyph metrics array (the XFontStruct member
+ * `per_char') directly, without going through a macro. Moreover these
+ * glyph metrics are ink metrics, i.e. are not redundant even for a
+ * fixed-width font. For a Unicode font, the size of this array is 768 KB.
+ *
+ * Problems: 1. It eats a lot of memory in each client. 2. All this glyph
+ * metrics data is piped through the socket when the font is opened.
+ *
+ * This extension addresses these two problems for local clients, by using
+ * shared memory. It also addresses the second problem for non-local clients,
+ * by compressing the data before transmit by a factor of nearly 6.
+ *
+ * If you use this extension, your OS ought to nicely support shared memory.
+ * This means: Shared memory should be swappable to the swap, and the limits
+ * should be high enough (SHMMNI at least 64, SHMMAX at least 768 KB,
+ * SHMALL at least 48 MB). It is a plus if your OS allows shmat() calls
+ * on segments that have already been marked "removed", because it permits
+ * these segments to be cleaned up by the OS if the X server is killed with
+ * signal SIGKILL.
+ *
+ * This extension is transparently exploited by Xlib (functions XQueryFont,
+ * XLoadQueryFont).
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <sys/types.h>
+#ifdef HAS_SHM
+#if defined(linux) && (!defined(__GNU_LIBRARY__) || __GNU_LIBRARY__ < 2)
+/* libc4 does not define __GNU_LIBRARY__, libc5 defines __GNU_LIBRARY__ as 1 */
+/* Linux libc4 and libc5 only (because glibc doesn't include kernel headers):
+   Linux 2.0.x and 2.2.x define SHMLBA as PAGE_SIZE, but forget to define
+   PAGE_SIZE. It is defined in <asm/page.h>. */
+#include <asm/page.h>
+#endif
+#ifdef SVR4
+#include <sys/sysmacros.h>
+#endif
+#if defined(__CYGWIN__) || defined(__SCO__)
+#include <sys/param.h>
+#include <sys/sysmacros.h>
+#endif
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <errno.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "os.h"
+#include "dixstruct.h"
+#include "gcstruct.h"
+#include "dixfontstr.h"
+#include "extnsionst.h"
+#include "protocol-versions.h"
+
+#include <X11/extensions/xf86bigfproto.h>
+#include "xf86bigfontsrv.h"
+
+static void XF86BigfontResetProc(
+    ExtensionEntry *	/* extEntry */
+    );
+
+static DISPATCH_PROC(ProcXF86BigfontDispatch);
+static DISPATCH_PROC(ProcXF86BigfontQueryVersion);
+static DISPATCH_PROC(ProcXF86BigfontQueryFont);
+static DISPATCH_PROC(SProcXF86BigfontDispatch);
+static DISPATCH_PROC(SProcXF86BigfontQueryVersion);
+static DISPATCH_PROC(SProcXF86BigfontQueryFont);
+
+#ifdef HAS_SHM
+
+/* A random signature, transmitted to the clients so they can verify that the
+   shared memory segment they are attaching to was really established by the
+   X server they are talking to. */
+static CARD32 signature;
+
+/* Index for additional information stored in a FontRec's devPrivates array. */
+static int FontShmdescIndex;
+
+static unsigned int pagesize;
+
+static Bool badSysCall = FALSE;
+
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) || defined(__DragonFly__)
+
+#include <sys/signal.h>
+
+static void
+SigSysHandler(
+     int signo)
+{
+    badSysCall = TRUE;
+}
+
+static Bool
+CheckForShmSyscall(void)
+{
+    void (*oldHandler)(int);
+    int shmid = -1;
+
+    /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */
+    oldHandler = signal(SIGSYS, SigSysHandler);
+
+    badSysCall = FALSE;
+    shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT);
+    if (shmid != -1)
+    {
+        /* Successful allocation - clean up */
+	shmctl(shmid, IPC_RMID, NULL);
+    }
+    else
+    {
+        /* Allocation failed */
+        badSysCall = TRUE;
+    }
+    signal(SIGSYS, oldHandler);
+    return (!badSysCall);
+}
+
+#define MUST_CHECK_FOR_SHM_SYSCALL
+
+#endif
+
+#endif
+
+void
+XFree86BigfontExtensionInit(void)
+{
+    if (AddExtension(XF86BIGFONTNAME,
+		     XF86BigfontNumberEvents,
+		     XF86BigfontNumberErrors,
+		     ProcXF86BigfontDispatch,
+		     SProcXF86BigfontDispatch,
+		     XF86BigfontResetProc,
+		     StandardMinorOpcode)) {
+#ifdef HAS_SHM
+#ifdef MUST_CHECK_FOR_SHM_SYSCALL
+	/*
+	 * Note: Local-clients will not be optimized without shared memory
+	 * support. Remote-client optimization does not depend on shared
+	 * memory support.  Thus, the extension is still registered even
+	 * when shared memory support is not functional.  
+	 */
+	if (!CheckForShmSyscall()) {
+	    ErrorF(XF86BIGFONTNAME " extension local-client optimization disabled due to lack of shared memory support in the kernel\n");
+	    return;
+	}
+#endif
+
+	srand((unsigned int) time(NULL));
+	signature = ((unsigned int) (65536.0/(RAND_MAX+1.0) * rand()) << 16)
+	           + (unsigned int) (65536.0/(RAND_MAX+1.0) * rand());
+	/* fprintf(stderr, "signature = 0x%08X\n", signature); */
+
+	FontShmdescIndex = AllocateFontPrivateIndex();
+
+#if !defined(CSRG_BASED) && !defined(__CYGWIN__)
+	pagesize = SHMLBA;
+#else
+# ifdef _SC_PAGESIZE
+	pagesize = sysconf(_SC_PAGESIZE);
+# else
+	pagesize = getpagesize();
+# endif
+#endif
+#endif
+    }
+}
+
+
+/* ========== Management of shared memory segments ========== */
+
+#ifdef HAS_SHM
+
+#ifdef __linux__
+/* On Linux, shared memory marked as "removed" can still be attached.
+   Nice feature, because the kernel will automatically free the associated
+   storage when the server and all clients are gone. */
+#define EARLY_REMOVE
+#endif
+
+typedef struct _ShmDesc {
+    struct _ShmDesc *next;
+    struct _ShmDesc **prev;
+    int shmid;
+    char *attach_addr;
+} ShmDescRec, *ShmDescPtr;
+
+static ShmDescPtr ShmList = (ShmDescPtr) NULL;
+
+static ShmDescPtr
+shmalloc(
+    unsigned int size)
+{
+    ShmDescPtr pDesc;
+    int shmid;
+    char *addr;
+
+#ifdef MUST_CHECK_FOR_SHM_SYSCALL
+    if (pagesize == 0)
+	return (ShmDescPtr) NULL;
+#endif
+
+    /* On some older Linux systems, the number of shared memory segments
+       system-wide is 127. In Linux 2.4, it is 4095.
+       Therefore there is a tradeoff to be made between allocating a
+       shared memory segment on one hand, and allocating memory and piping
+       the glyph metrics on the other hand. If the glyph metrics size is
+       small, we prefer the traditional way. */
+    if (size < 3500)
+	return (ShmDescPtr) NULL;
+
+    pDesc = xalloc(sizeof(ShmDescRec));
+    if (!pDesc)
+	return (ShmDescPtr) NULL;
+
+    size = (size + pagesize-1) & -pagesize;
+    shmid = shmget(IPC_PRIVATE, size, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
+    if (shmid == -1) {
+	ErrorF(XF86BIGFONTNAME " extension: shmget() failed, size = %u, %s\n",
+	       size, strerror(errno));
+	xfree(pDesc);
+	return (ShmDescPtr) NULL;
+    }
+
+    if ((addr = shmat(shmid, 0, 0)) == (char *)-1) {
+	ErrorF(XF86BIGFONTNAME " extension: shmat() failed, size = %u, %s\n",
+	       size, strerror(errno));
+	shmctl(shmid, IPC_RMID, (void *) 0);
+	xfree(pDesc);
+	return (ShmDescPtr) NULL;
+    }
+
+#ifdef EARLY_REMOVE
+    shmctl(shmid, IPC_RMID, (void *) 0);
+#endif
+
+    pDesc->shmid = shmid;
+    pDesc->attach_addr = addr;
+    if (ShmList) ShmList->prev = &pDesc->next;
+    pDesc->next = ShmList;
+    pDesc->prev = &ShmList;
+    ShmList = pDesc;
+
+    return pDesc;
+}
+
+static void
+shmdealloc(
+    ShmDescPtr pDesc)
+{
+#ifndef EARLY_REMOVE
+    shmctl(pDesc->shmid, IPC_RMID, (void *) 0);
+#endif
+    shmdt(pDesc->attach_addr);
+
+    if (pDesc->next) pDesc->next->prev = pDesc->prev;
+    *pDesc->prev = pDesc->next;
+    xfree(pDesc);
+}
+
+#endif
+
+/* Called when a font is closed. */
+void
+XF86BigfontFreeFontShm(
+    FontPtr pFont)
+{
+#ifdef HAS_SHM
+    ShmDescPtr pDesc;
+
+    /* If during shutdown of the server, XF86BigfontCleanup() has already
+     * called shmdealloc() for all segments, we don't need to do it here.
+     */
+    if (!ShmList)
+	return;
+
+    pDesc = (ShmDescPtr) FontGetPrivate(pFont, FontShmdescIndex);
+    if (pDesc)
+	shmdealloc(pDesc);
+#endif
+}
+
+/* Called upon fatal signal. */
+void
+XF86BigfontCleanup(void)
+{
+#ifdef HAS_SHM
+    while (ShmList)
+	shmdealloc(ShmList);
+#endif
+}
+
+/* Called when a server generation dies. */
+static void
+XF86BigfontResetProc(
+    ExtensionEntry* extEntry)
+{
+    /* This function is normally called from CloseDownExtensions(), called
+     * from main(). It will be followed by a call to FreeAllResources(),
+     * which will call XF86BigfontFreeFontShm() for each font. Thus it
+     * appears that we do not need to do anything in this function. --
+     * But I prefer to write robust code, and not keep shared memory lying
+     * around when it's not needed any more. (Someone might close down the
+     * extension without calling FreeAllResources()...)
+     */
+    XF86BigfontCleanup();
+}
+
+
+/* ========== Handling of extension specific requests ========== */
+
+static int
+ProcXF86BigfontQueryVersion(
+    ClientPtr client)
+{
+    xXF86BigfontQueryVersionReply reply;
+
+    REQUEST_SIZE_MATCH(xXF86BigfontQueryVersionReq);
+    reply.type = X_Reply;
+    reply.length = 0;
+    reply.sequenceNumber = client->sequence;
+    reply.majorVersion = SERVER_XF86BIGFONT_MAJOR_VERSION;
+    reply.minorVersion = SERVER_XF86BIGFONT_MINOR_VERSION;
+    reply.uid = geteuid();
+    reply.gid = getegid();
+#ifdef HAS_SHM
+    reply.signature = signature;
+#else
+    reply.signature = 0; /* This is redundant. Avoids uninitialized memory. */
+#endif
+    reply.capabilities =
+#ifdef HAS_SHM
+	(LocalClient(client) && !client->swapped ? XF86Bigfont_CAP_LocalShm : 0)
+#else
+	0
+#endif
+	; /* may add more bits here in future versions */
+    if (client->swapped) {
+	char tmp;
+	swaps(&reply.sequenceNumber, tmp);
+	swapl(&reply.length, tmp);
+	swaps(&reply.majorVersion, tmp);
+	swaps(&reply.minorVersion, tmp);
+	swapl(&reply.uid, tmp);
+	swapl(&reply.gid, tmp);
+	swapl(&reply.signature, tmp);
+    }
+    WriteToClient(client,
+		  sizeof(xXF86BigfontQueryVersionReply), (char *)&reply);
+    return client->noClientException;
+}
+
+static void
+swapCharInfo(
+    xCharInfo *pCI)
+{
+    char tmp;
+
+    swaps(&pCI->leftSideBearing, tmp);
+    swaps(&pCI->rightSideBearing, tmp);
+    swaps(&pCI->characterWidth, tmp);
+    swaps(&pCI->ascent, tmp);
+    swaps(&pCI->descent, tmp);
+    swaps(&pCI->attributes, tmp);
+}
+
+/* static CARD32 hashCI (xCharInfo *p); */
+#define hashCI(p) \
+	(CARD32)(((p->leftSideBearing << 27) + (p->leftSideBearing >> 5) + \
+	          (p->rightSideBearing << 23) + (p->rightSideBearing >> 9) + \
+	          (p->characterWidth << 16) + \
+	          (p->ascent << 11) + (p->descent << 6)) ^ p->attributes)
+
+static int
+ProcXF86BigfontQueryFont(
+    ClientPtr client)
+{
+    FontPtr pFont;
+    REQUEST(xXF86BigfontQueryFontReq);
+    CARD32 stuff_flags;
+    xCharInfo* pmax;
+    xCharInfo* pmin;
+    int nCharInfos;
+    int shmid;
+#ifdef HAS_SHM
+    ShmDescPtr pDesc;
+#else
+#define pDesc 0
+#endif
+    xCharInfo* pCI;
+    CARD16* pIndex2UniqIndex;
+    CARD16* pUniqIndex2Index;
+    CARD32 nUniqCharInfos;
+
+#if 0
+    REQUEST_SIZE_MATCH(xXF86BigfontQueryFontReq);
+#else
+    switch (client->req_len) {
+	case 2: /* client with version 1.0 libX11 */
+	    stuff_flags = (LocalClient(client) && !client->swapped ? XF86Bigfont_FLAGS_Shm : 0);
+	    break;
+	case 3: /* client with version 1.1 libX11 */
+	    stuff_flags = stuff->flags;
+	    break;
+	default:
+	    return BadLength;
+    }
+#endif
+    if (dixLookupFontable(&pFont, stuff->id, client, DixGetAttrAccess) != Success)
+	return BadFont;    /* procotol spec says only error is BadFont */
+
+    pmax = FONTINKMAX(pFont);
+    pmin = FONTINKMIN(pFont);
+    nCharInfos =
+       (pmax->rightSideBearing == pmin->rightSideBearing
+        && pmax->leftSideBearing == pmin->leftSideBearing
+        && pmax->descent == pmin->descent
+        && pmax->ascent == pmin->ascent
+        && pmax->characterWidth == pmin->characterWidth)
+       ? 0 : N2dChars(pFont);
+    shmid = -1;
+    pCI = NULL;
+    pIndex2UniqIndex = NULL;
+    pUniqIndex2Index = NULL;
+    nUniqCharInfos = 0;
+
+    if (nCharInfos > 0) {
+#ifdef HAS_SHM
+	if (!badSysCall)
+	    pDesc = (ShmDescPtr) FontGetPrivate(pFont, FontShmdescIndex);
+	else
+	    pDesc = NULL;
+	if (pDesc) {
+	    pCI = (xCharInfo *) pDesc->attach_addr;
+	    if (stuff_flags & XF86Bigfont_FLAGS_Shm)
+		shmid = pDesc->shmid;
+	} else {
+	    if (stuff_flags & XF86Bigfont_FLAGS_Shm && !badSysCall)
+		pDesc = shmalloc(nCharInfos * sizeof(xCharInfo)
+				 + sizeof(CARD32));
+	    if (pDesc) {
+		pCI = (xCharInfo *) pDesc->attach_addr;
+		shmid = pDesc->shmid;
+	    } else {
+#endif
+		pCI = xalloc(nCharInfos * sizeof(xCharInfo));
+		if (!pCI)
+		    return BadAlloc;
+#ifdef HAS_SHM
+	    }
+#endif
+	    /* Fill nCharInfos starting at pCI. */
+	    {
+		xCharInfo* prCI = pCI;
+		int ninfos = 0;
+		int ncols = pFont->info.lastCol - pFont->info.firstCol + 1;
+		int row;
+		for (row = pFont->info.firstRow;
+		     row <= pFont->info.lastRow && ninfos < nCharInfos;
+		     row++) {
+		    unsigned char chars[512];
+		    xCharInfo* tmpCharInfos[256];
+		    unsigned long count;
+		    int col;
+		    unsigned long i;
+		    i = 0;
+		    for (col = pFont->info.firstCol;
+			 col <= pFont->info.lastCol;
+			 col++) {
+			chars[i++] = row;
+			chars[i++] = col;
+		    }
+		    (*pFont->get_metrics) (pFont, ncols, chars, TwoD16Bit,
+					   &count, tmpCharInfos);
+		    for (i = 0; i < count && ninfos < nCharInfos; i++) {
+			*prCI++ = *tmpCharInfos[i];
+			ninfos++;
+		    }
+		}
+	    }
+#ifdef HAS_SHM
+	    if (pDesc && !badSysCall) {
+		*(CARD32 *)(pCI + nCharInfos) = signature;
+		if (!FontSetPrivate(pFont, FontShmdescIndex, pDesc)) {
+		    shmdealloc(pDesc);
+		    return BadAlloc;
+		}
+	    }
+	}
+#endif
+	if (shmid == -1) {
+	    /* Cannot use shared memory, so remove-duplicates the xCharInfos
+	       using a temporary hash table. */
+	    /* Note that CARD16 is suitable as index type, because
+	       nCharInfos <= 0x10000. */
+	    CARD32 hashModulus;
+	    CARD16* pHash2UniqIndex;
+	    CARD16* pUniqIndex2NextUniqIndex;
+	    CARD32 NextIndex;
+	    CARD32 NextUniqIndex;
+	    CARD16* tmp;
+	    CARD32 i, j;
+
+	    hashModulus = 67;
+	    if (hashModulus > nCharInfos+1)
+		hashModulus = nCharInfos+1;
+
+	    tmp = xalloc((4*nCharInfos+1) * sizeof(CARD16));
+	    if (!tmp) {
+		if (!pDesc) xfree(pCI);
+		return BadAlloc;
+	    }
+	    pIndex2UniqIndex = tmp;
+		/* nCharInfos elements */
+	    pUniqIndex2Index = tmp + nCharInfos;
+		/* max. nCharInfos elements */
+	    pUniqIndex2NextUniqIndex = tmp + 2*nCharInfos;
+		/* max. nCharInfos elements */
+	    pHash2UniqIndex = tmp + 3*nCharInfos;
+		/* hashModulus (<= nCharInfos+1) elements */
+
+	    /* Note that we can use 0xffff as end-of-list indicator, because
+	       even if nCharInfos = 0x10000, 0xffff can not occur as valid
+	       entry before the last element has been inserted. And once the
+	       last element has been inserted, we don't need the hash table
+	       any more. */
+	    for (j = 0; j < hashModulus; j++)
+		pHash2UniqIndex[j] = (CARD16)(-1);
+
+	    NextUniqIndex = 0;
+	    for (NextIndex = 0; NextIndex < nCharInfos; NextIndex++) {
+		xCharInfo* p = &pCI[NextIndex];
+		CARD32 hashCode = hashCI(p) % hashModulus;
+		for (i = pHash2UniqIndex[hashCode];
+		     i != (CARD16)(-1);
+		     i = pUniqIndex2NextUniqIndex[i]) {
+		    j = pUniqIndex2Index[i];
+		    if (pCI[j].leftSideBearing == p->leftSideBearing
+			&& pCI[j].rightSideBearing == p->rightSideBearing
+			&& pCI[j].characterWidth == p->characterWidth
+			&& pCI[j].ascent == p->ascent
+			&& pCI[j].descent == p->descent
+			&& pCI[j].attributes == p->attributes)
+			break;
+		}
+		if (i != (CARD16)(-1)) {
+		    /* Found *p at Index j, UniqIndex i */
+		    pIndex2UniqIndex[NextIndex] = i;
+		} else {
+		    /* Allocate a new entry in the Uniq table */
+		    if (hashModulus <= 2*NextUniqIndex
+			&& hashModulus < nCharInfos+1) {
+			/* Time to increate hash table size */
+			hashModulus = 2*hashModulus+1;
+			if (hashModulus > nCharInfos+1)
+			    hashModulus = nCharInfos+1;
+			for (j = 0; j < hashModulus; j++)
+			    pHash2UniqIndex[j] = (CARD16)(-1);
+			for (i = 0; i < NextUniqIndex; i++)
+			    pUniqIndex2NextUniqIndex[i] = (CARD16)(-1);
+			for (i = 0; i < NextUniqIndex; i++) {
+			    j = pUniqIndex2Index[i];
+			    p = &pCI[j];
+			    hashCode = hashCI(p) % hashModulus;
+			    pUniqIndex2NextUniqIndex[i] = pHash2UniqIndex[hashCode];
+			    pHash2UniqIndex[hashCode] = i;
+			}
+			p = &pCI[NextIndex];
+			hashCode = hashCI(p) % hashModulus;
+		    }
+		    i = NextUniqIndex++;
+		    pUniqIndex2NextUniqIndex[i] = pHash2UniqIndex[hashCode];
+		    pHash2UniqIndex[hashCode] = i;
+		    pUniqIndex2Index[i] = NextIndex;
+		    pIndex2UniqIndex[NextIndex] = i;
+		}
+	    }
+	    nUniqCharInfos = NextUniqIndex;
+	    /* fprintf(stderr, "font metrics: nCharInfos = %d, nUniqCharInfos = %d, hashModulus = %d\n", nCharInfos, nUniqCharInfos, hashModulus); */
+	}
+    }
+
+    {
+	int nfontprops = pFont->info.nprops;
+	int rlength =
+	   sizeof(xXF86BigfontQueryFontReply)
+	   + nfontprops * sizeof(xFontProp)
+	   + (nCharInfos > 0 && shmid == -1
+	      ? nUniqCharInfos * sizeof(xCharInfo)
+	        + (nCharInfos+1)/2 * 2 * sizeof(CARD16)
+	      : 0);
+	xXF86BigfontQueryFontReply* reply = xalloc(rlength);
+	char* p;
+	if (!reply) {
+	    if (nCharInfos > 0) {
+		if (shmid == -1) xfree(pIndex2UniqIndex);
+		if (!pDesc) xfree(pCI);
+	    }
+	    return BadAlloc;
+	}
+	reply->type = X_Reply;
+	reply->length = bytes_to_int32(rlength - sizeof(xGenericReply));
+	reply->sequenceNumber = client->sequence;
+	reply->minBounds = pFont->info.ink_minbounds;
+	reply->maxBounds = pFont->info.ink_maxbounds;
+	reply->minCharOrByte2 = pFont->info.firstCol;
+	reply->maxCharOrByte2 = pFont->info.lastCol;
+	reply->defaultChar = pFont->info.defaultCh;
+	reply->nFontProps = pFont->info.nprops;
+	reply->drawDirection = pFont->info.drawDirection;
+	reply->minByte1 = pFont->info.firstRow;
+	reply->maxByte1 = pFont->info.lastRow;
+	reply->allCharsExist = pFont->info.allExist;
+	reply->fontAscent = pFont->info.fontAscent;
+	reply->fontDescent = pFont->info.fontDescent;
+	reply->nCharInfos = nCharInfos;
+        reply->nUniqCharInfos = nUniqCharInfos;
+	reply->shmid = shmid;
+	reply->shmsegoffset = 0;
+	if (client->swapped) {
+	    char tmp;
+	    swaps(&reply->sequenceNumber, tmp);
+	    swapl(&reply->length, tmp);
+	    swapCharInfo(&reply->minBounds);
+	    swapCharInfo(&reply->maxBounds);
+	    swaps(&reply->minCharOrByte2, tmp);
+	    swaps(&reply->maxCharOrByte2, tmp);
+	    swaps(&reply->defaultChar, tmp);
+	    swaps(&reply->nFontProps, tmp);
+	    swaps(&reply->fontAscent, tmp);
+	    swaps(&reply->fontDescent, tmp);
+	    swapl(&reply->nCharInfos, tmp);
+	    swapl(&reply->nUniqCharInfos, tmp);
+	    swapl(&reply->shmid, tmp);
+	    swapl(&reply->shmsegoffset, tmp);
+	}
+	p = (char*) &reply[1];
+	{
+	    FontPropPtr pFP;
+	    xFontProp* prFP;
+	    int i;
+	    for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) p;
+		 i < nfontprops;
+		 i++, pFP++, prFP++) {
+		prFP->name = pFP->name;
+		prFP->value = pFP->value;
+		if (client->swapped) {
+		    char tmp;
+		    swapl(&prFP->name, tmp);
+		    swapl(&prFP->value, tmp);
+		}
+	    }
+	    p = (char*) prFP;
+	}
+	if (nCharInfos > 0 && shmid == -1) {
+	    xCharInfo* pci;
+	    CARD16* ps;
+	    int i, j;
+	    pci = (xCharInfo*) p;
+	    for (i = 0; i < nUniqCharInfos; i++, pci++) {
+		*pci = pCI[pUniqIndex2Index[i]];
+		if (client->swapped)
+		    swapCharInfo(pci);
+	    }
+	    ps = (CARD16*) pci;
+	    for (j = 0; j < nCharInfos; j++, ps++) {
+		*ps = pIndex2UniqIndex[j];
+		if (client->swapped) {
+		    char tmp;
+		    swaps(ps, tmp);
+		}
+	    }
+	}
+	WriteToClient(client, rlength, (char *)reply);
+	xfree(reply);
+	if (nCharInfos > 0) {
+	    if (shmid == -1) xfree(pIndex2UniqIndex);
+	    if (!pDesc) xfree(pCI);
+	}
+	return (client->noClientException);
+    }
+}
+
+static int
+ProcXF86BigfontDispatch(
+    ClientPtr client)
+{
+    REQUEST(xReq);
+
+    switch (stuff->data) {
+	case X_XF86BigfontQueryVersion:
+	    return ProcXF86BigfontQueryVersion(client);
+	case X_XF86BigfontQueryFont:
+	    return ProcXF86BigfontQueryFont(client);
+	default:
+	    return BadRequest;
+    }
+}
+
+static int
+SProcXF86BigfontQueryVersion(
+    ClientPtr client)
+{
+    REQUEST(xXF86BigfontQueryVersionReq);
+    char tmp;
+
+    swaps(&stuff->length, tmp);
+    return ProcXF86BigfontQueryVersion(client);
+}
+
+static int
+SProcXF86BigfontQueryFont(
+    ClientPtr client)
+{
+    REQUEST(xXF86BigfontQueryFontReq);
+    char tmp;
+
+    swaps(&stuff->length, tmp);
+    REQUEST_SIZE_MATCH(xXF86BigfontQueryFontReq);
+    swapl(&stuff->id, tmp);
+    return ProcXF86BigfontQueryFont(client);
+}
+
+static int
+SProcXF86BigfontDispatch(
+    ClientPtr client)
+{
+    REQUEST(xReq);
+
+    switch (stuff->data) {
+	case X_XF86BigfontQueryVersion:
+	    return SProcXF86BigfontQueryVersion(client);
+	case X_XF86BigfontQueryFont:
+	    return SProcXF86BigfontQueryFont(client);
+	default:
+	    return BadRequest;
+    }
+}
-- 
cgit v1.2.3