/************************************************************
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
and the Massachusetts Institute of Technology, Cambridge, 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 names of Digital or MIT 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.

********************************************************/

/*
 * XXX - gag, choke, puke - XXX
 */
asm("	export XCRoutines");

#include "X.h"
#define NEED←REPLIES
#define NEED←EVENTS
#include "Xproto.h"
#include "Xprotostr.h"
#include "windowstr.h"
#include "fontstruct.h"
#include "dixfontstr.h"
#include "gcstruct.h"
#include "osstruct.h"
#include "resource.h"
#include "selection.h"
#include "colormapst.h"
#include "dixstruct.h"
#include "extension.h"
#include "input.h"
#include "cursorstr.h"
#include "scrnintstr.h"
#include "opaque.h"

extern WindowRec WindowTable[];
extern xConnSetupPrefix connSetupPrefix;
extern char *ConnectionInfo;
extern char *SwappedConnInfo;

extern void ValidateGC();
extern void WriteSConnectionInfo();

extern Selection *CurrentSelections;
extern int NumCurrentSelections;

extern long ScreenSaverTime;
extern long ScreenSaverInterval;
extern int  ScreenSaverBlanking;
extern int  ScreenSaverAllowExposures;
extern ClientPtr onlyClient;
extern Bool grabbingClient;
extern long *checkForInput[2];
extern Bool clientsDoomed;

extern int (* ProcVector[256]) ();
extern int (* SwappedProcVector[256]) ();
extern void (* EventSwapVector[128]) ();
extern void (* ReplySwapVector[256]) ();

void KillAllClients();

/* buffers for clients. legal values below */
extern int nextFreeClientID;	   /* 0 is for the server */

extern int	nClients;	/* number active clients */

extern int ProcBadRequest();

#define SAME←SCREENS(a, b) (\
    (a.pScreen == b.pScreen))

#define VALIDATE(pGC, pDraw, rt) {\
    if (pGC->serialNumber != pDraw->serialNumber)\
    {\
	ValidateGC(pDraw, pGC);\
    } \
}

#define LEGAL←NEW←RESOURCE(id)\
    if ((LookupID(id, RT←ANY, RC←CORE) != 0) || (id & SERVER←BIT) \
	|| (client->clientAsMask != CLIENT←BITS(id)))\
        return(BadIDChoice)


#define LOOKUP←DRAWABLE(did, client)\
    ((client->lastDrawableID == did) ? \
     (DrawablePtr)client->lastDrawable : (DrawablePtr)LookupDrawable(did, client))

#define VERIFY←GC(pGC, rid, client)\
    if (client->lastGCID == rid)\
    {\
        pGC = (GC *) client->lastGC;\
    }\
    else\
    {\
	pGC = (GC *)LookupID(rid, RT←GC, RC←CORE);\
        if (!pGC)\
        {\
	    client->errorValue = rid;\
	    return (BadGC);\
        }\
    }

#define VALIDATE←DRAWABLE←AND←GC(drawID, pDraw, pGC, client)\
    if ((client->lastDrawableID != drawID) || (client->lastGCID != stuff->gc))\
    {\
        if (client->lastDrawableID != drawID)\
	{\
    	    pDraw = (DrawablePtr)LookupID(drawID, RT←DRAWABLE, RC←CORE);\
    	    if (!pDraw)\
	    {\
	        client->errorValue = drawID; \
                return (BadDrawable);\
	    }\
	    if ((pDraw->type == DRAWABLE←WINDOW) || \
		(pDraw->type == DRAWABLE←PIXMAP))\
    	    {\
	        client->lastDrawable = (pointer)pDraw;\
	        client->lastDrawableID = drawID;\
	    }\
            else\
	    {\
	        client->errorValue = drawID;\
                return (BadDrawable);\
	    }\
        }\
        else\
	    pDraw = (DrawablePtr)client->lastDrawable;\
        if (client->lastGCID != stuff->gc)\
	{\
	    pGC = (GC *)LookupID(stuff->gc, RT←GC, RC←CORE);\
            if (!pGC)\
            {\
	        client->errorValue = stuff->gc;\
	        return (BadGC);\
            }\
            client->lastGC = (pointer)pGC;\
            client->lastGCID = stuff->gc;\
        }\
        else\
            pGC = (GC *) client->lastGC;\
        if ((pGC->depth != pDraw->depth) || (pGC->pScreen != pDraw->pScreen))\
	{\
            client->errorValue = stuff->gc;\
	    client->lastGCID = -1;\
	    return (BadMatch);\
         }\
    }\
    else\
    {\
        pGC = (GC *) client->lastGC;\
        pDraw = (DrawablePtr)client->lastDrawable;\
    }\
    if (pGC->serialNumber != pDraw->serialNumber)\
    { \
	ValidateGC(pDraw, pGC);\
    }


int
ProcImageText(client)
    register ClientPtr client;
{
    register DrawablePtr pDraw;
    register GC *pGC;

    REQUEST(xImageTextReq);

    REQUEST←AT←LEAST←SIZE(xImageTextReq);
    VALIDATE←DRAWABLE←AND←GC(stuff->drawable, pDraw, pGC, client);

    (*((stuff->reqType == X←ImageText8) ? pGC->ImageText8 : pGC->ImageText16))
	(pDraw, pGC, stuff->x, stuff->y, stuff->nChars, (char *)&stuff[1]);
    return (client->noClientException);
}


int
ProcCreateColormap(client)
    register ClientPtr client;
{
    VisualPtr	pVisual;
    ColormapPtr	pmap;
    long	mid;
    register WindowPtr   pWin;
    REQUEST(xCreateColormapReq);
    int result;

    REQUEST←SIZE←MATCH(xCreateColormapReq);

    if ((stuff->alloc != AllocNone) && (stuff->alloc != AllocAll))
        return(BadValue);
    mid = stuff->mid;
    LEGAL←NEW←RESOURCE(mid);    
    pWin = (WindowPtr)LookupWindow(stuff->window, client);
    if (!pWin)
        return(BadWindow);

    if(stuff->visual == CopyFromParent)
        if(pWin->parent)
	    stuff->visual = pWin->parent->visual;
	else
	    stuff->visual = pWin->visual;
    pVisual = (VisualPtr)LookupID(stuff->visual, RT←VISUALID, RC←CORE);
    if ((!pVisual) || pVisual->screen != pWin->drawable.pScreen->myNum)
    {
	client->errorValue = stuff->visual;
	return(BadValue);
    }
    result =  CreateColormap(mid, pWin->drawable.pScreen,
        pVisual, &pmap, (int)stuff->alloc, (unsigned int)client->index);
    if (client->noClientException != Success)
        return(client->noClientException);
    else
        return(result);
}

int
ProcFreeColormap(client)
    register ClientPtr client;
{
    ColormapPtr pmap;
    REQUEST(xResourceReq);

    REQUEST←SIZE←MATCH(xResourceReq);
    pmap = (ColormapPtr )LookupID(stuff->id, RT←COLORMAP, RC←CORE);
    if (pmap) 
    {
	FreeColormap(pmap, client->index);
	FreeResource(stuff->id, RC←NONE);
	return (client->noClientException);
    }
    else 
    {
	client->errorValue = stuff->id;
	return (BadColor);
    }
}


int
ProcCopyColormapAndFree(client)
    register ClientPtr client;
{
    int		mid;
    ColormapPtr	pSrcMap;
    REQUEST(xCopyColormapAndFreeReq);
    int result;

    REQUEST←SIZE←MATCH(xCopyColormapAndFreeReq);
    mid = stuff->mid;
    LEGAL←NEW←RESOURCE(mid);
    if(pSrcMap = (ColormapPtr )LookupID(stuff->srcCmap, RT←COLORMAP, RC←CORE))
    {
	result = CopyColormapAndFree(mid, pSrcMap, client->index);
	if (client->noClientException != Success)
            return(client->noClientException);
	else
            return(result);
    }
    else
    {
	client->errorValue = stuff->srcCmap;
	return(BadColor);
    }
}

int
ProcInstallColormap(client)
    register ClientPtr client;
{
    ColormapPtr pcmp;
    REQUEST(xResourceReq);

    REQUEST←SIZE←MATCH(xResourceReq);
    pcmp = (ColormapPtr  )LookupID(stuff->id, RT←COLORMAP, RC←CORE);
    if (pcmp)
    {
        (*(pcmp->pScreen->InstallColormap)) (pcmp);
        return (client->noClientException);        
    }
    else
    {
        client->errorValue = stuff->id;
        return (BadColor);
    }
}

int
ProcUninstallColormap(client)
    register ClientPtr client;
{
    ColormapPtr pcmp;
    REQUEST(xResourceReq);

    REQUEST←SIZE←MATCH(xResourceReq);
    pcmp = (ColormapPtr )LookupID(stuff->id, RT←COLORMAP, RC←CORE);
    if (pcmp)
    {
	if(pcmp->mid != pcmp->pScreen->defColormap)
            (*(pcmp->pScreen->UninstallColormap)) (pcmp);
        return (client->noClientException);        
    }
    else
    {
        client->errorValue = stuff->id;
        return (BadColor);
    }
}

int
ProcListInstalledColormaps(client)
    register ClientPtr client;
{
    xListInstalledColormapsReply *preply; 
    int nummaps;
    WindowPtr pWin;
    REQUEST(xResourceReq);

    REQUEST←SIZE←MATCH(xResourceReq);
    pWin = (WindowPtr)LookupWindow(stuff->id, client);

    if (!pWin)
        return(BadWindow);

    preply = (xListInstalledColormapsReply *) 
		ALLOCATE←LOCAL(sizeof(xListInstalledColormapsReply) +
		     pWin->drawable.pScreen->maxInstalledCmaps *
		     sizeof(Colormap));
    if(!preply)
        return(client->noClientException = BadAlloc);

    preply->type = X←Reply;
    preply->sequenceNumber = client->sequence;
    nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps)
        (pWin->drawable.pScreen, (Colormap *)&preply[1]);
    preply->nColormaps = nummaps;
    preply->length = nummaps;
    WriteReplyToClient(client, sizeof (xListInstalledColormapsReply), preply);
    WriteReplyToClient(client, nummaps * sizeof(Colormap), &preply[1]);
    DEALLOCATE←LOCAL(preply);
    return(client->noClientException);
}

int
ProcAllocColor                (client)
    register ClientPtr client;
{
    ColormapPtr pmap;
    int	retval;
    xAllocColorReply acr;
    REQUEST(xAllocColorReq);

    REQUEST←SIZE←MATCH(xAllocColorReq);
    pmap = (ColormapPtr )LookupID(stuff->cmap, RT←COLORMAP, RC←CORE);
    if (pmap)
    {
	acr.type = X←Reply;
	acr.length = 0;
	acr.sequenceNumber = client->sequence;
	acr.red = stuff->red;
	acr.green = stuff->green;
	acr.blue = stuff->blue;
	if(retval = AllocColor(pmap, &acr.red, &acr.green, &acr.blue,
	                       &acr.pixel, client->index))
	{
            if (client->noClientException != Success)
                return(client->noClientException);
	    else
	        return (retval);
	}
        WriteReplyToClient(client, sizeof(xAllocColorReply), &acr);
	return (client->noClientException);

    }
    else
    {
        client->errorValue = stuff->cmap;
        return (BadColor);
    }
}

int
ProcAllocNamedColor           (client)
    register ClientPtr client;
{
    ColormapPtr pcmp;
    REQUEST(xAllocNamedColorReq);

    REQUEST←AT←LEAST←SIZE(xAllocNamedColorReq);
    pcmp = (ColormapPtr )LookupID(stuff->cmap, RT←COLORMAP, RC←CORE);
    if (pcmp)
    {
	int		retval;

	xAllocNamedColorReply ancr;

	ancr.type = X←Reply;
	ancr.length = 0;
	ancr.sequenceNumber = client->sequence;

	if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], stuff->nbytes,
	                 &ancr.exactRed, &ancr.exactGreen, &ancr.exactBlue))
	{
	    ancr.screenRed = ancr.exactRed;
	    ancr.screenGreen = ancr.exactGreen;
	    ancr.screenBlue = ancr.exactBlue;
	    if(retval = AllocColor(pcmp,
	                 &ancr.screenRed, &ancr.screenGreen, &ancr.screenBlue,
			 &ancr.pixel, client->index))
	    {
                if (client->noClientException != Success)
                    return(client->noClientException);
                else
    	            return(retval);
	    }
            WriteReplyToClient(client, sizeof (xAllocNamedColorReply), &ancr);
	    return (client->noClientException);
	}
	else
	    return(BadName);
	
    }
    else
    {
        client->errorValue = stuff->cmap;
        return (BadColor);
    }
}

int
ProcAllocColorCells           (client)
    register ClientPtr client;
{
    ColormapPtr pcmp;
    REQUEST(xAllocColorCellsReq);

    REQUEST←SIZE←MATCH(xAllocColorCellsReq);
    pcmp = (ColormapPtr )LookupID(stuff->cmap, RT←COLORMAP, RC←CORE);
    if (pcmp)
    {
	xAllocColorCellsReply	accr;
	int			npixels, nmasks, retval;
	unsigned long		*ppixels, *pmasks;

	npixels = stuff->colors;
	nmasks = stuff->planes;
	ppixels = (unsigned long *)ALLOCATE←LOCAL(npixels * sizeof(long) + 
						  nmasks * sizeof(long));
	if(!ppixels)
            return(client->noClientException = BadAlloc);
	pmasks = ppixels + npixels;

	if(retval = AllocColorCells(client->index, pcmp, npixels, nmasks, 
	                            (Bool)stuff->contiguous, ppixels, pmasks))
	{
            if (client->noClientException != Success)
                return(client->noClientException);
	    else
	        return(retval);
	}
	accr.type = X←Reply;
	accr.length = ( (npixels + nmasks) * sizeof(long)) >> 2;
	accr.sequenceNumber = client->sequence;
	accr.nPixels = npixels;
	accr.nMasks = nmasks;
        WriteReplyToClient(client, sizeof (xAllocColorCellsReply), &accr);
        WriteReplyToClient(client, (npixels + nmasks) * sizeof (long), ppixels);
	DEALLOCATE←LOCAL(ppixels);
        return (client->noClientException);        
    }
    else
    {
        client->errorValue = stuff->cmap;
        return (BadColor);
    }
}

int
ProcAllocColorPlanes(client)
    register ClientPtr client;
{
    ColormapPtr pcmp;
    REQUEST(xAllocColorPlanesReq);

    REQUEST←SIZE←MATCH(xAllocColorPlanesReq);
    pcmp = (ColormapPtr )LookupID(stuff->cmap, RT←COLORMAP, RC←CORE);
    if (pcmp)
    {
	xAllocColorPlanesReply	acpr;
	int			npixels, retval;
	unsigned long		*ppixels;

	npixels = stuff->colors;
	acpr.type = X←Reply;
	acpr.sequenceNumber = client->sequence;
	acpr.nPixels = npixels;
	npixels *= sizeof(long);
	ppixels = (unsigned long *)ALLOCATE←LOCAL(npixels);
	if(!ppixels)
            return(client->noClientException = BadAlloc);
	if(retval = AllocColorPlanes(client->index, pcmp, (int)stuff->colors,
	    (int)stuff->red, (int)stuff->green, (int)stuff->blue, 
	    (Bool)stuff->contiguous, ppixels,
	    &acpr.redMask, &acpr.greenMask, &acpr.blueMask))
	{
            DEALLOCATE←LOCAL(ppixels);
            if (client->noClientException != Success)
                return(client->noClientException);
	    else
	        return(retval);
	}
	acpr.length = npixels >> 2;
	WriteReplyToClient(client, sizeof(xAllocColorPlanesReply), &acpr);
	WriteReplyToClient(client, npixels, ppixels);
	DEALLOCATE←LOCAL(ppixels);
        return (client->noClientException);        
    }
    else
    {
        client->errorValue = stuff->cmap;
        return (BadColor);
    }
}

int
ProcFreeColors          (client)
    register ClientPtr client;
{
    ColormapPtr pcmp;
    REQUEST(xFreeColorsReq);

    REQUEST←AT←LEAST←SIZE(xFreeColorsReq);
    pcmp = (ColormapPtr )LookupID(stuff->cmap, RT←COLORMAP, RC←CORE);
    if (pcmp)
    {
	int	count;
        int     retval;

	if(pcmp->flags & AllAllocated)
	    return(BadAccess);
	count = ((stuff->length << 2)- sizeof(xFreeColorsReq)) >> 2;
	retval =  FreeColors(pcmp, client->index, count,
	    (unsigned long *)&stuff[1], stuff->planeMask);
        if (client->noClientException != Success)
            return(client->noClientException);
        else
            return(retval);

    }
    else
    {
        client->errorValue = stuff->cmap;
        return (BadColor);
    }
}

int
ProcStoreColors               (client)
    register ClientPtr client;
{
    ColormapPtr pcmp;
    REQUEST(xStoreColorsReq);

    REQUEST←AT←LEAST←SIZE(xStoreColorsReq);
    pcmp = (ColormapPtr )LookupID(stuff->cmap, RT←COLORMAP, RC←CORE);
    if (pcmp)
    {
	int	count;
        int     retval;

        if(pcmp->flags & AllAllocated)
	    if(CLIENT←ID(stuff->cmap) != client->index)
	        return(BadAccess);
        count =
	  ((stuff->length << 2) - sizeof(xStoreColorsReq)) / sizeof(xColorItem);
	retval = StoreColors(pcmp, count, (xColorItem *)&stuff[1]);
        if (client->noClientException != Success)
            return(client->noClientException);
        else
            return(retval);
    }
    else
    {
        client->errorValue = stuff->cmap;
        return (BadColor);
    }
}

int
ProcStoreNamedColor           (client)
    register ClientPtr client;
{
    ColormapPtr pcmp;
    REQUEST(xStoreNamedColorReq);

    REQUEST←AT←LEAST←SIZE(xStoreNamedColorReq);
    pcmp = (ColormapPtr )LookupID(stuff->cmap, RT←COLORMAP, RC←CORE);
    if (pcmp)
    {
	xColorItem	def;
        int             retval;

        if(pcmp->flags & AllAllocated)
	    if(CLIENT←ID(stuff->cmap) != client->index)
	        return(BadAccess);

	if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1],
	                 stuff->nbytes, &def.red, &def.green, &def.blue))
	{
	    def.flags = stuff->flags;
	    retval = StoreColors(pcmp, 1, &def);
            if (client->noClientException != Success)
                return(client->noClientException);
	    else
		return(retval);
	}
        return (BadName);        
    }
    else
    {
        client->errorValue = stuff->cmap;
        return (BadColor);
    }
}

int
ProcQueryColors(client)
    register ClientPtr client;
{
    ColormapPtr pcmp;
    REQUEST(xQueryColorsReq);

    REQUEST←AT←LEAST←SIZE(xQueryColorsReq);
    pcmp = (ColormapPtr )LookupID(stuff->cmap, RT←COLORMAP, RC←CORE);
    if (pcmp)
    {
	int			count, retval;
	xrgb 			*prgbs;
	xQueryColorsReply	qcr;

	count = ((stuff->length << 2) - sizeof(xQueryColorsReq)) >> 2;
	if(!(prgbs = (xrgb *)ALLOCATE←LOCAL(count * sizeof(xrgb))))
            return(client->noClientException = BadAlloc);
	if(retval = QueryColors(pcmp, count, (unsigned long *)&stuff[1], prgbs))
	{
   	    DEALLOCATE←LOCAL(prgbs);
	    if (client->noClientException != Success)
                return(client->noClientException);
	    else
	        return (retval);
	}
	qcr.type = X←Reply;
	qcr.length = (count * sizeof(xrgb)) >> 2;
	qcr.sequenceNumber = client->sequence;
	qcr.nColors = count;
	WriteReplyToClient(client, sizeof(xQueryColorsReply), &qcr);
	WriteReplyToClient(client, count * sizeof(xrgb), prgbs);
	DEALLOCATE←LOCAL(prgbs);
	return(client->noClientException);
	
    }
    else
    {
        client->errorValue = stuff->cmap;
        return (BadColor);
    }
} 

int
ProcLookupColor(client)
    register ClientPtr client;
{
    ColormapPtr pcmp;
    REQUEST(xLookupColorReq);

    REQUEST←AT←LEAST←SIZE(xLookupColorReq);
    pcmp = (ColormapPtr )LookupID(stuff->cmap, RT←COLORMAP, RC←CORE);
    if (pcmp)
    {
	xLookupColorReply lcr;

	if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], stuff->nbytes,
	                 &lcr.exactRed, &lcr.exactGreen, &lcr.exactBlue))
	{
	    lcr.type = X←Reply;
	    lcr.length = 0;
	    lcr.sequenceNumber = client->sequence;
	    lcr.screenRed = lcr.exactRed;
	    lcr.screenGreen = lcr.exactGreen;
	    lcr.screenBlue = lcr.exactBlue;
	    (*pcmp->pScreen->ResolveColor)(&lcr.screenRed,
	                                   &lcr.screenGreen,
					   &lcr.screenBlue);
	    WriteReplyToClient(client, sizeof(xLookupColorReply), &lcr);
	    return(client->noClientException);
	}
        return (BadName);        
    }
    else
    {
        client->errorValue = stuff->cmap;
        return (BadColor);
    }
}

int
ProcCreateCursor( client)
    register ClientPtr client;
{
    CursorPtr	pCursor;

    register PixmapPtr 	src;
    register PixmapPtr 	msk;
    unsigned int *	srcbits;
    unsigned int *	mskbits;
    int		width, height;
    CursorMetricRec cm;


    REQUEST(xCreateCursorReq);

    REQUEST←SIZE←MATCH(xCreateCursorReq);
    LEGAL←NEW←RESOURCE(stuff->cid);

    src = (PixmapPtr)LookupID( stuff->source, RT←PIXMAP, RC←CORE);
    msk = (PixmapPtr)LookupID( stuff->mask, RT←PIXMAP, RC←CORE);
    if (   src == (PixmapPtr)NULL)
	return (BadPixmap);
    if ( msk == (PixmapPtr)NULL)
	msk = src;

    if (  src->width != msk->width
       || src->height != msk->height
       || src->drawable.depth != 1
       || msk->drawable.depth != 1)
	return (BadMatch);

    width = src->width;
    height = src->height;

    if ( stuff->x > width 
      || stuff->y > height )
	return (BadMatch);

    srcbits = (unsigned int *)Xalloc( PixmapBytePad(width, 1)*height); 
    mskbits = (unsigned int *)Xalloc( PixmapBytePad(width, 1)*height); 

    (* src->drawable.pScreen->GetImage)( src, 0, 0, width, height,
					 XYBitmap, 0xffff, srcbits);
    (* msk->drawable.pScreen->GetImage)( msk, 0, 0, width, height,
					 XYBitmap, 0xffff, mskbits);
    cm.width = width;
    cm.height = height;
    cm.xhot = stuff->x;
    cm.yhot = stuff->y;
    pCursor = AllocCursor( (unsigned char *)srcbits, (unsigned char *)mskbits, 
	    &cm, stuff->foreRed, stuff->foreGreen, stuff->foreBlue,
	    stuff->backRed, stuff->backGreen, stuff->backBlue);

    AddResource( stuff->cid, RT←CURSOR, (pointer)pCursor, FreeCursor, RC←CORE);
    return (client->noClientException);
}

/*
 * protocol requires positioning of glyphs so hot-spots are coincident	XXX
 */
int
ProcCreateGlyphCursor( client)
    register ClientPtr client;
{
    FontPtr  sourcefont;
    FontPtr  maskfont;
    char   *srcbits;
    char   *mskbits;
    CursorPtr pCursor;
    CursorMetricRec cm;
    int res;

    REQUEST(xCreateGlyphCursorReq);

    REQUEST←SIZE←MATCH(xCreateGlyphCursorReq);
    LEGAL←NEW←RESOURCE(stuff->cid);

    sourcefont = (FontPtr) LookupID(stuff->source, RT←FONT, RC←CORE);
    maskfont = (FontPtr) LookupID(stuff->mask, RT←FONT, RC←CORE);

    if (sourcefont == (FontPtr) NULL)
	return(BadFont);

    if (!CursorMetricsFromGlyph(maskfont,(int) stuff->maskChar, &cm))
	return BadValue;

    if (res = ServerBitsFromGlyph(stuff->source, 
				  sourcefont, stuff->sourceChar,
				  &cm, (unsigned char **)&srcbits))
	return res;
    if (res = ServerBitsFromGlyph(stuff->mask, 
				  maskfont, stuff->maskChar,
				  &cm, (unsigned char **)&mskbits))
	return res;

    pCursor = AllocCursor((unsigned char *)srcbits, (unsigned char *)mskbits, 
	    &cm, stuff->foreRed, stuff->foreGreen, stuff->foreBlue,
	    stuff->backRed, stuff->backGreen, stuff->backBlue);

    AddResource(stuff->cid, RT←CURSOR, (pointer)pCursor, FreeCursor, RC←CORE);
    return client->noClientException;
}


int
ProcFreeCursor(client)
    register ClientPtr client;
{
    CursorPtr pCursor;
    REQUEST(xResourceReq);

    REQUEST←SIZE←MATCH(xResourceReq);
    pCursor = (CursorPtr)LookupID(stuff->id, RT←CURSOR, RC←CORE);
    if (pCursor) 
    {
	FreeResource( stuff->id, RC←NONE);
	return (client->noClientException);
    }
    else 
    {
	return (BadCursor);
    }
}

int
ProcQueryBestSize   (client)
    register ClientPtr client;
{
    xQueryBestSizeReply	reply;
    register DrawablePtr pDraw;
    ScreenPtr pScreen;
    REQUEST(xQueryBestSizeReq);

    REQUEST←SIZE←MATCH(xQueryBestSizeReq);
    if ((stuff->class != CursorShape) && 
	(stuff->class != TileShape) && 
	(stuff->class != StippleShape))
        return(BadValue);
    if (!(pDraw = LOOKUP←DRAWABLE(stuff->drawable, client)))
    {
	client->errorValue = stuff->drawable;
	return (BadDrawable);
    }
    pScreen = pDraw->pScreen;
    (* pScreen->QueryBestSize)(stuff->class, &stuff->width,
			       &stuff->height);
    reply.type = X←Reply;
    reply.length = 0;
    reply.sequenceNumber = client->sequence;
    reply.width = stuff->width;
    reply.height = stuff->height;
    WriteReplyToClient(client, sizeof(xQueryBestSizeReply), &reply);
    return (client->noClientException);
}


int
ProcSetScreenSaver            (client)
    register ClientPtr client;
{
    int blankingOption, exposureOption;
    REQUEST(xSetScreenSaverReq);

    REQUEST←SIZE←MATCH(xSetScreenSaverReq);
    blankingOption = stuff->preferBlank;
    if ((blankingOption != DontPreferBlanking) &&
        (blankingOption != PreferBlanking) &&
        (blankingOption != DefaultBlanking))
        return BadMatch;

    exposureOption = stuff->allowExpose;
    if ((exposureOption != DontAllowExposures) &&
        (exposureOption != AllowExposures) &&
        (exposureOption != DefaultExposures))
        return BadMatch;

    if ((stuff->timeout < -1) || (stuff->interval < -1))
        return BadMatch;

    ScreenSaverBlanking = blankingOption; 
    ScreenSaverAllowExposures = exposureOption;

    if (stuff->timeout >= 0)
	ScreenSaverTime = stuff->timeout * MILLI←PER←SECOND;
    else 
	ScreenSaverTime = DEFAULT←SCREEN←SAVER←TIME;
    if (stuff->interval > 0)
	ScreenSaverInterval = stuff->interval * MILLI←PER←SECOND;
    else
	ScreenSaverInterval = DEFAULT←SCREEN←SAVER←TIME;
    return (client->noClientException);
}

int
ProcGetScreenSaver(client)
    register ClientPtr client;
{
    xGetScreenSaverReply rep;

    rep.type = X←Reply;
    rep.length = 0;
    rep.sequenceNumber = client->sequence;
    rep.timeout = ScreenSaverTime / MILLI←PER←SECOND;
    rep.interval = ScreenSaverInterval / MILLI←PER←SECOND;
    rep.preferBlanking = ScreenSaverBlanking;
    rep.allowExposures = ScreenSaverAllowExposures;
    WriteReplyToClient(client, sizeof(xGetScreenSaverReply), &rep);
    return (client->noClientException);
}

int
ProcChangeHosts(client)
    register ClientPtr client;
{
    REQUEST(xChangeHostsReq);
    int result;

    REQUEST←AT←LEAST←SIZE(xChangeHostsReq);

    if(stuff->mode == HostInsert)
	result = AddHost(client, stuff->hostFamily, stuff->hostLength, 
		&stuff[1]);
    else if (stuff->mode == HostDelete)
	result = RemoveHost(client, stuff->hostFamily, 
			    stuff->hostLength,  &stuff[1]);  
    else
        return BadValue;
    return (result || client->noClientException);
}

int
ProcListHosts(client)
    register ClientPtr client;
{
extern int GetHosts();
    xListHostsReply reply;
    int	len, nHosts;
    char	*pdata;
    Bool tmp←enabled;
    REQUEST(xListHostsReq);

    REQUEST←SIZE←MATCH(xListHostsReq);
    if((len = GetHosts(&pdata, &nHosts, &tmp←enabled)) < 0)
	return(BadImplementation);
    reply.enabled = tmp←enabled;
    reply.type = X←Reply;
    reply.sequenceNumber = client->sequence;
    reply.nHosts = nHosts;
    reply.length = len >> 2;
    WriteReplyToClient(client, sizeof(xListHostsReply), &reply);
    WriteReplyToClient(client, len, pdata);
    Xfree(pdata);
    return (client->noClientException);
}

int
ProcChangeAccessControl(client)
    register ClientPtr client;
{
    REQUEST(xSetAccessControlReq);

    REQUEST←SIZE←MATCH(xSetAccessControlReq);
    if ((stuff->mode != EnableAccess) && (stuff->mode != DisableAccess))
        return BadValue;
    ChangeAccessControl(client, stuff->mode == EnableAccess);
    return (client->noClientException);
}

int
ProcKillClient(client)
    register ClientPtr client;
{
    REQUEST(xResourceReq);

    pointer *pResource;

    REQUEST←SIZE←MATCH(xResourceReq);
    if (stuff->id == AllTemporary)
    {
	CloseDownRetainedResources();
        return (client->noClientException);
    }
    pResource = (pointer *)LookupID(stuff->id, RT←ANY, RC←CORE);
    if ((CLIENT←ID(stuff->id)) && pResource)
    {
	CloseDownClient(client);
        return (client->noClientException);
    }
    else   /* can't kill client 0, which is server */
    {
	client->errorValue = stuff->id;
	return (BadValue);
    }
}

int
ProcSetFontPath(client)
    register ClientPtr client;
{
    REQUEST(xSetFontPathReq);
    
    REQUEST←AT←LEAST←SIZE(xSetFontPathReq);
    
    SetFontPath((int)stuff->nFonts, (int)stuff->length, (char *)&stuff[1]);
    return (client->noClientException);
}

int
ProcGetFontPath(client)
    register ClientPtr client;
{
    FontPathPtr pFP;
    xGetFontPathReply reply;
    int stringLens, i;
    char *bufferStart;
    register char  *bufptr;
    REQUEST (xReq);

    REQUEST←SIZE←MATCH(xReq);
    pFP = GetFontPath();
    stringLens = 0;
    for (i=0; i<pFP->npaths; i++)
        stringLens += pFP->length[i];

    reply.type = X←Reply;
    reply.sequenceNumber = client->sequence;
    reply.length = (stringLens + pFP->npaths + 3) >> 2;
    reply.nPaths = pFP->npaths;

    bufptr = bufferStart = (char *)ALLOCATE←LOCAL((int)reply.length << 2);
    if(!bufptr)
        return(client->noClientException = BadAlloc);
            /* since WriteToClient long word aligns things, 
	       copy to temp buffer and write all at once */
    for (i=0; i<pFP->npaths; i++)
    {
        *bufptr++ = pFP->length[i];
        bcopy(pFP->paths[i], bufptr,  pFP->length[i]);
        bufptr += pFP->length[i];
    }
    WriteReplyToClient(client, sizeof(xGetFontPathReply), &reply);
    WriteReplyToClient(client, reply.length << 2, bufferStart);
    DEALLOCATE←LOCAL(bufferStart);
    return(client->noClientException);
}

int
ProcChangeCloseDownMode(client)
    register ClientPtr client;
{
    REQUEST(xSetCloseDownModeReq);

    REQUEST←SIZE←MATCH(xSetCloseDownModeReq);
    if ((stuff->mode == AllTemporary) ||
	(stuff->mode == RetainPermanent) ||
	(stuff->mode == RetainTemporary))
    {
	client->closeDownMode = stuff->mode;
	return (client->noClientException);
    }
    else   
    {
	client->errorValue = stuff->mode;
	return (BadValue);
    }
}

int ProcForceScreenSaver(client)
    register ClientPtr client;
{    
    REQUEST(xForceScreenSaverReq);

    REQUEST←SIZE←MATCH(xForceScreenSaverReq);
    
    if ((stuff->mode != ScreenSaverReset) && 
	(stuff->mode != ScreenSaverActive))
        return BadValue;
    SaveScreens(SCREEN←SAVER←FORCER, (int)stuff->mode);
    return client->noClientException;
}

int ProcNoOperation(client)
    register ClientPtr client;
{
    REQUEST(xReq);

    REQUEST←AT←LEAST←SIZE(xReq);
    
    /* noop -- don't do anything */
    return(client->noClientException);
}

void
InitProcVectors()
{
    int i;
    for (i = 0; i<256; i++)
    {
	if(!ProcVector[i])
	{
            ProcVector[i] = SwappedProcVector[i] = ProcBadRequest;
	    ReplySwapVector[i] = NotImplemented;
	}
    }
    for(i = LASTEvent; i < 128; i++)
    {
	EventSwapVector[i] = NotImplemented;
    }
    
}

/**********************
 * CloseDownClient
 *
 *  Client can either mark his resources destroy or retain.  If retained and
 *  then killed again, the client is really destroyed.
 *********************/

void
CloseDownClient(client)
    register ClientPtr client;
{
    register int i;
      /* ungrab server if grabbing client dies */
    if (grabbingClient &&  (onlyClient == client))
    {
	grabbingClient = FALSE;
	ListenToAllClients();
    }
    ReleaseActiveGrabs(client);
    
    if (client->closeDownMode == DestroyAll)
    {
        client->clientGone = TRUE;  /* so events aren't sent to client */
        CloseDownConnection(client);
        FreeClientResources(client);
        for (i=0; i<currentMaxClients; i++)
            if (clients[i] == client)
	    {
		nextFreeClientID = i;
                clients[nextFreeClientID] = NullClient;
		break;
	    }
        Xfree(client);
	if(--nClients == 0)
	    nClients = -1;
    }
            /* really kill resources this time */
    else if (client->clientGone)
    {
        FreeClientResources(client);
        for (i=0; i<currentMaxClients; i++)
            if (clients[i] == client)
	    {
		nextFreeClientID = i;
                clients[nextFreeClientID] = NullClient;
		break;
	    }
        Xfree(client);
	--nClients;
    }
    else
    {
        client->clientGone = TRUE;
        CloseDownConnection(client);
    }
}

void
KillAllClients()
{
    int i;
    for (i=1; i<currentMaxClients; i++)
        if (clients[i] && !clients[i]->clientGone)
            CloseDownClient(clients[i]);     
}

void
KillServerResources()
{
    int i;

    KillAllClients();
    CloseDownDevices((int)0, (long)0);
    for (i = 0; i < screenInfo.numScreens; i++)
	(*screenInfo.screen[i].CloseScreen)(i, &screenInfo.screen[i]);
}


/*********************
 * CloseDownRetainedResources
 *
 *    Find all clients that are gone and have terminated in RetainTemporary 
 *    and  destroy their resources.
 *********************/

CloseDownRetainedResources()
{
    register int i;
    register ClientPtr client;

    for (i=1; i<currentMaxClients; i++)
    {
        client = clients[i];
        if (client && (client->closeDownMode == RetainTemporary)
	    && (client->clientGone))
	{
            FreeClientResources(client);
            nextFreeClientID = i;
	    Xfree(client);
	    clients[i] = NullClient;
	}
    }
}

/************************
 * int NextAvailableClientID()
 *
 * OS depedent portion can't assign client id's because of CloseDownModes.
 * Returns -1 if the there are no free clients.
 *************************/
/*
 * XXX - gag, choke, puke - XXX
 */

asm("	exportproc ←NextAvailableClient, XCRoutines");

ClientPtr
NextAvailableClient()
{
    long i;
    ClientPtr client;

    if (nextFreeClientID >= currentMaxClients)
        nextFreeClientID = 1;
    if (!clients[nextFreeClientID])
    {
	i = nextFreeClientID;
	nextFreeClientID++;
    }
    else
    {
	i = 1;
	while ((i<currentMaxClients) && (clients[i]))
            i++;
        if (i < currentMaxClients)
	    nextFreeClientID = i;
	else
        {
	    clients = (ClientPtr *)Xrealloc(clients, i * sizeof(ClientRec));
	    currentMaxClients++;
	}
    }
    clients[i] = client =  (ClientPtr)Xalloc(sizeof(ClientRec));
    client->index = i;
    client->sequence = 0; 
    client->clientAsMask = i << CLIENTOFFSET;
    client->closeDownMode = DestroyAll;
    client->clientGone = FALSE;
    client->lastDrawable = (pointer) NULL;
    client->lastDrawableID = -1;
    client->lastGC = (pointer) NULL;
    client->lastGCID = -1;
    client->numSaved = 0;
    client->saveSet = (pointer *)NULL;
    client->noClientException = Success;

    return(client);
}

SendConnectionSetupInfo(client)
    ClientPtr client;
{
    xConnSetup *setup;
    /*
    if (client->swapped)
	setup = (xConnSetup *) SwappedConnInfo;
    else
    */
        setup = (xConnSetup *)ConnectionInfo;
    client->pSwapReplyFunc = (void (*) ()) NULL;
    setup->ridBase = (client->clientAsMask);
    setup->ridMask = 0xfffff;

    WriteConnToClient(client, (int)sizeof(xConnSetupPrefix), (xConnSetupPrefix *)&connSetupPrefix);
    WriteSConnectionInfo(client, (int)connSetupPrefix.length << 2, (char  *)ConnectionInfo);
}

/*****************
 * Oops
 *    Send an Error back to the client. 
 *****************/

Oops (client, reqCode, minorCode, status)
    ClientPtr client;
    char reqCode, minorCode, status;
{
    xError rep;
    register int i;

    rep.type = X←Error;
    rep.sequenceNumber = client->sequence;
    rep.errorCode = status;
    rep.majorCode = reqCode;
    rep.minorCode = minorCode;
    rep.resourceID = client->errorValue;

    for (i=0; i<currentMaxClients; i++)
        if (clients[i] == client) break;
    ErrorF(  "OOPS!!! to client %x\n", i);
    ErrorF(  "    sequenceNumber = %d\n", rep.sequenceNumber);
    ErrorF( "    rep.errorCode= %d\n", rep.errorCode);
    ErrorF(  "    rep.majorCode = %d\n", rep.majorCode);
    ErrorF( "    rep.resourceID = %x\n", rep.resourceID);

    WriteEventToClient (client, 1, (pointer) &rep); 
}


void
DeleteWindowFromAnySelections(pWin)
    WindowPtr pWin;
{
    int i = 0;

    for (i = 0; i< NumCurrentSelections; i++)
        if (CurrentSelections[i].pWin == pWin)
        {
            CurrentSelections[i].pWin = (WindowPtr)NULL;
            CurrentSelections[i].window = None;
	}
}

void
MarkClientException(client)
    ClientPtr client;
{
    client->noClientException = -1;
}


/* Byte swap a list of longs */

SwapLongs (list, count)
	register long *list;
	register int count;
{
	register int n;

	while (count >= 8) {
	    swapl(list+0, n);
	    swapl(list+1, n);
	    swapl(list+2, n);
	    swapl(list+3, n);
	    swapl(list+4, n);
	    swapl(list+5, n);
	    swapl(list+6, n);
	    swapl(list+7, n);
	    list += 8;
	    count -= 8;
	}
	while (--count >= 0) {
	    swapl(list, n);
	    list++;
	}
}

/* Byte swap a list of shorts */

SwapShorts (list, count)
	register short *list;
	register int count;
{
	register int n;

	while (count >= 16) {
	    swaps(list+0, n);
	    swaps(list+1, n);
	    swaps(list+2, n);
	    swaps(list+3, n);
	    swaps(list+4, n);
	    swaps(list+5, n);
	    swaps(list+6, n);
	    swaps(list+7, n);
	    swaps(list+8, n);
	    swaps(list+9, n);
	    swaps(list+10, n);
	    swaps(list+11, n);
	    swaps(list+12, n);
	    swaps(list+13, n);
	    swaps(list+14, n);
	    swaps(list+15, n);
	    list += 16;
	    count -= 16;
	}
	while (--count >= 0) 
        {
	    swaps(list, n);
	    list++;
	}
}