X-Git-Url: https://git.sesse.net/?p=rdpsrv;a=blobdiff_plain;f=Xserver%2Fprograms%2FXserver%2FXext%2Fxprint.c;fp=Xserver%2Fprograms%2FXserver%2FXext%2Fxprint.c;h=829a8f3f0afe7d05741ad38d98027b479d86ef14;hp=0000000000000000000000000000000000000000;hb=b6e6afccf37f4ad0515ef2a698f714fdf1bf23b3;hpb=e3340a110a3b01756b8e67531395a33b40a17d37 diff --git a/Xserver/programs/Xserver/Xext/xprint.c b/Xserver/programs/Xserver/Xext/xprint.c new file mode 100644 index 0000000..829a8f3 --- /dev/null +++ b/Xserver/programs/Xserver/Xext/xprint.c @@ -0,0 +1,2873 @@ +/* $XConsortium: xprint.c /main/3 1996/11/23 17:11:55 rws $ */ +/* +(c) Copyright 1996 Hewlett-Packard Company +(c) Copyright 1996 International Business Machines Corp. +(c) Copyright 1996 Sun Microsystems, Inc. +(c) Copyright 1996 Novell, Inc. +(c) Copyright 1996 Digital Equipment Corp. +(c) Copyright 1996 Fujitsu Limited +(c) Copyright 1996 Hitachi, Ltd. + +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, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +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 THE +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 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 names of the copyright holders shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from said +copyright holders. +*/ +/******************************************************************* +** +** ********************************************************* +** * +** * File: xprint.c +** * +** * Copyright: Copyright 1993, 1995 Hewlett-Packard Company +** * +** * Copyright 1989 by The Massachusetts Institute of Technology +** * +** * 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 MIT not be used in +** * advertising or publicity pertaining to distribution of the +** * software without specific prior written permission. +** * M.I.T. makes no representation about the suitability of +** * this software for any purpose. It is provided "as is" +** * without any express or implied warranty. +** * +** * MIT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +** * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT- +** * NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MIT BE LI- +** * ABLE 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. +** * +** ********************************************************* +** +********************************************************************/ +/* $XFree86: xc/programs/Xserver/Xext/xprint.c,v 1.4 1997/01/02 04:05:05 dawes Exp $ */ + +#include "X.h" +#define NEED_EVENTS +#include "Xproto.h" +#undef NEED_EVENTS +#include "misc.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "Xatom.h" +#define _XP_PRINT_SERVER_ +#include "Print.h" +#include "Printstr.h" +#undef _XP_PRINT_SERVER_ +#include "../Xprint/DiPrint.h" + +extern WindowPtr *WindowTable; /* declared in dix:globals.c */ + +extern WindowPtr XpDiValidatePrinter(); +extern char *XpDiGetDriverName(); +extern char *XpGetAttributes(); +extern char *XpGetOneAttribute(); +extern int XpRehashPrinterList(); +extern void XpSetFontResFunc(); + +static void XpResetProc(); + +static int ProcXpDispatch(); +static int ProcXpSwappedDispatch(); + +static int ProcXpQueryVersion(); +static int ProcXpGetPrinterList(); +static int ProcXpCreateContext(); +static int ProcXpSetContext(); +static int ProcXpGetContext(); +static int ProcXpDestroyContext(); +static int ProcXpGetContextScreen(); +static int ProcXpStartJob(); +static int ProcXpEndJob(); +static int ProcXpStartDoc(); +static int ProcXpEndDoc(); +static int ProcXpStartPage(); +static int ProcXpEndPage(); +static int ProcXpSelectInput(); +static int ProcXpInputSelected(); +static int ProcXpPutDocumentData(); +static int ProcXpGetDocumentData(); +static int ProcXpGetAttributes(); +static int ProcXpGetOneAttribute(); +static int ProcXpSetAttributes(); +static int ProcXpRehashPrinterList(); +static int ProcXpQueryScreens(); +static int ProcXpGetPageDimensions(); +static int ProcXpSetImageResolution(); +static int ProcXpGetImageResolution(); + +static void SwapXpNotifyEvent(); +static void SwapXpAttributeEvent(); + +static int SProcXpGetPrinterList(); +static int SProcXpCreateContext(); +static int SProcXpSetContext(); +static int SProcXpGetContext(); +static int SProcXpDestroyContext(); +static int SProcXpGetContextScreen(); +static int SProcXpStartJob(); +static int SProcXpEndJob(); +static int SProcXpStartDoc(); +static int SProcXpEndDoc(); +static int SProcXpStartPage(); +static int SProcXpEndPage(); +static int SProcXpSelectInput(); +static int SProcXpInputSelected(); +static int SProcXpPutDocumentData(); +static int SProcXpGetDocumentData(); +static int SProcXpGetAttributes(); +static int SProcXpGetOneAttribute(); +static int SProcXpSetAttributes(); +static int SProcXpRehashPrinterList(); +static int SProcXpGetPageDimensions(); +static int SProcXpSetImageResolution(); +static int SProcXpGetImageResolution(); + +static void SendXpNotify(); +static void SendAttributeNotify(); +static int XpFreeClient(); +static int XpFreeContext(); +static int XpFreePage(); +static int XpFreeEvents(); +static Bool XpCloseScreen(); +static CARD32 GetAllEventMasks(); +static struct _XpEvent *AddEventRec(); +static void DeleteEventRec(); +static struct _XpEvent *FindEventRec(); +static struct _XpClient *CreateXpClient(); +static void FreeXpClient(); +static void InitContextPrivates(); +static void ResetContextPrivates(); +static struct _XpClient *FindClient(); +static struct _XpClient *AcquireClient(); + +typedef struct _driver { + struct _driver *next; + char *name; + int (* CreateContext)(); +} XpDriverRec, *XpDriverPtr; + +typedef struct _xpScreen { + Bool (* CloseScreen)(); + struct _driver *drivers; +} XpScreenRec, *XpScreenPtr; + +/* + * Each context has a list of XpClients indicating which clients have + * associated this context with their connection. + * Each such client has a RTclient resource allocated for it, + * and this per-client + * resource is used to delete the XpClientRec if/when the client closes + * its connection. + * The list of XpClients is also walked if/when the context is destroyed + * so that the ContextPtr can be removed from the client's devPrivates. + */ +typedef struct _XpClient { + struct _XpClient *pNext; + ClientPtr client; + XpContextPtr context; + CARD32 eventMask; + XID contextClientID; /* unneeded sanity check? */ +} XpClientRec, *XpClientPtr; + +/* + * Each StartPage request specifies a window which forms the top level + * window of the page. One of the following structs is created as a + * RTpage resource with the same ID as the window itself. This enables + * us to clean up when/if the window is destroyed, and to prevent the + * same window from being simultaneously referenced in multiple contexts. + * The page resource is created at the first StartPage on a given window, + * and is only destroyed when/if the window is destroyed. When the + * EndPage is recieved (or an EndDoc or EndJob) the context field is + * set to NULL, but the resource remains alive. + */ +typedef struct _XpPage { + XpContextPtr context; +} XpPageRec, *XpPagePtr; + +typedef struct _XpStPageRec { + XpContextPtr pContext; + Bool slept; + XpPagePtr pPage; + WindowPtr pWin; +} XpStPageRec, *XpStPagePtr; + +typedef struct _XpStDocRec { + XpContextPtr pContext; + Bool slept; + CARD8 type; +} XpStDocRec, *XpStDocPtr; + +#define QUADPAD(x) ((((x)+3)>>2)<<2) + +/* + * Possible bit-mask values in the "state" field of a XpContextRec. + */ +#define JOB_STARTED (1 << 0) +#define DOC_RAW_STARTED (1 << 1) +#define DOC_COOKED_STARTED (1 << 2) +#define PAGE_STARTED (1 << 3) +#define GET_DOC_DATA_STARTED (1 << 4) +#define JOB_GET_DATA (1 << 5) + +static XpScreenPtr XpScreens[MAXSCREENS]; +static unsigned char XpReqCode; +static int XpEventBase; +static int XpErrorBase; +static int XpGeneration = 0; +static int XpWindowPrivateIndex; +static int XpClientPrivateIndex; + +/* Variables for the context private machinery. + * These must be initialized at compile time because + * main() calls InitOutput before InitExtensions, and the + * output drivers are likely to call AllocateContextPrivate. + * These variables are reset at CloseScreen time. CloseScreen + * is used because it occurs after FreeAllResources, and before + * the next InitOutput cycle. + */ +static int contextPrivateCount = 0; +static int contextPrivateLen = 0; +static unsigned *contextPrivateSizes = (unsigned *)NULL; +static unsigned totalContextSize = sizeof(XpContextRec); + +/* + * There are three types of resources involved. One is the resource associated + * with the context itself, with an ID specified by a printing client. The + * next is a resource created by us on the client's behalf (and unknown to + * the client) when a client inits or sets a context which allows us to + * track each client's interest in events + * on a particular context, and also allows us to clean up this interest + * record when/if the client's connection is closed. Finally, there is + * a resource created for each window that's specified in a StartPage. This + * resource carries the same ID as the window itself, and enables us to + * easily prevent the same window being referenced in multiple contexts + * simultaneously, and enables us to clean up if the window is destroyed + * before the EndPage. + */ +static RESTYPE RTclient, RTcontext, RTpage; + +/* + * allEvents is the OR of all the legal event mask bits. + */ +static CARD32 allEvents = XPPrintMask | XPAttributeMask; + + +/******************************************************************************* + * + * ExtensionInit, Driver Init functions, QueryVersion, and Dispatch procs + * + ******************************************************************************/ + +/* + * XpExtensionInit + * + * Called from InitExtensions in main() usually through miinitextension + * + */ + +void +XpExtensionInit() +{ + ExtensionEntry *extEntry, *AddExtension(); + int i; + + RTclient = CreateNewResourceType(XpFreeClient); + RTcontext = CreateNewResourceType(XpFreeContext); + RTpage = CreateNewResourceType(XpFreePage); + if (RTclient && RTcontext && RTpage && + (extEntry = AddExtension(XP_PRINTNAME, XP_EVENTS, XP_ERRORS, + ProcXpDispatch, ProcXpSwappedDispatch, + XpResetProc, StandardMinorOpcode))) + { + XpReqCode = (unsigned char)extEntry->base; + XpEventBase = extEntry->eventBase; + XpErrorBase = extEntry->errorBase; + EventSwapVector[XpEventBase] = SwapXpNotifyEvent; + EventSwapVector[XpEventBase+1] = SwapXpAttributeEvent; + } + + if(XpGeneration != serverGeneration) + { + XpClientPrivateIndex = AllocateClientPrivateIndex(); + /* + * We allocate 0 length & simply stuff a pointer to the + * ContextRec in the DevUnion. + */ + if(AllocateClientPrivate(XpClientPrivateIndex, 0) != TRUE) + { + /* we can't alloc a client private, should we bail??? XXX */ + } + XpGeneration = serverGeneration; + } + + for(i = 0; i < MAXSCREENS; i++) + { + /* + * If a screen has registered with our extension, then we + * wrap the screen's CloseScreen function to allow us to + * reset our ContextPrivate stuff. Note that this + * requires a printing DDX to call XpRegisterInitFunc + * _before_ this extension is initialized - i.e. at screen init + * time, _not_ at root window creation time. + */ + if(XpScreens[i] != (XpScreenPtr)NULL) + { + XpScreens[i]->CloseScreen = screenInfo.screens[i]->CloseScreen; + screenInfo.screens[i]->CloseScreen = XpCloseScreen; + } + } + DeclareExtensionSecurity(XP_PRINTNAME, TRUE); +} + +static void +XpResetProc(extEntry) + ExtensionEntry extEntry; +{ + int i; + + /* + * We can't free up the XpScreens recs here, because extensions are + * closed before screens, and our CloseScreen function uses the XpScreens + * recs. + for(i = 0; i < MAXSCREENS; i++) + { + if(XpScreens[i] != (XpScreenPtr)NULL) + Xfree(XpScreens[i]); + XpScreens[i] = (XpScreenPtr)NULL; + } + */ +} + +static Bool +XpCloseScreen(index, pScreen) + int index; + ScreenPtr pScreen; +{ + Bool (* CloseScreen)(); + + CloseScreen = XpScreens[index]->CloseScreen; + if(XpScreens[index] != (XpScreenPtr)NULL) + { + XpDriverPtr pDriv, nextDriv; + + pDriv = XpScreens[index]->drivers; + while(pDriv != (XpDriverPtr)NULL) + { + nextDriv = pDriv->next; + Xfree(pDriv); + pDriv = nextDriv; + } + Xfree(XpScreens[index]); + } + XpScreens[index] = (XpScreenPtr)NULL; + + /* + * It's wasteful to call ResetContextPrivates() at every CloseScreen, + * but it's the best we know how to do for now. We do this because we + * have to wait until after all resources have been freed (so we know + * how to free the ContextRecs), and before the next InitOutput cycle. + * See dix/main.c for the order of initialization and reset. + */ + ResetContextPrivates(); + return (*CloseScreen)(index, pScreen); +} + +static void +FreeScreenEntry(pScreenEntry) + XpScreenPtr pScreenEntry; +{ + XpDriverPtr pDriver; + + pDriver = pScreenEntry->drivers; + while(pDriver != (XpDriverPtr)NULL) + { + XpDriverPtr tmp; + + tmp = pDriver->next; + xfree(pDriver); + pDriver = tmp; + } + xfree(pScreenEntry); +} + +/* + * XpRegisterInitFunc tells the print extension which screens + * are printers as opposed to displays, and what drivers are + * supported on each screen. This eliminates the need of + * allocating print-related private structures on windows on _all_ screens. + * It also hands the extension a pointer to the routine to be called + * whenever a context gets created for a particular driver on this screen. + */ +void +XpRegisterInitFunc(pScreen, driverName, initContext) + ScreenPtr pScreen; + char *driverName; + int (*initContext)(); +{ + XpDriverPtr pDriver; + + if(XpScreens[pScreen->myNum] == (XpScreenPtr)NULL) + { + if((XpScreens[pScreen->myNum] = + (XpScreenPtr) Xalloc(sizeof(XpScreenRec))) == (XpScreenPtr)NULL) + return; + XpScreens[pScreen->myNum]->CloseScreen = (Bool(*)())NULL; + XpScreens[pScreen->myNum]->drivers = (XpDriverPtr)NULL; + } + + if((pDriver = (XpDriverPtr)Xalloc(sizeof(XpDriverRec))) == + (XpDriverPtr)NULL) + return; + pDriver->next = XpScreens[pScreen->myNum]->drivers; + pDriver->name = driverName; + pDriver->CreateContext = initContext; + XpScreens[pScreen->myNum]->drivers = pDriver; +} + +static int +ProcXpDispatch(client) + ClientPtr client; +{ + REQUEST(xReq); + + switch(stuff->data) + { + case X_PrintQueryVersion: + return ProcXpQueryVersion(client); + case X_PrintGetPrinterList: + return ProcXpGetPrinterList(client); + case X_PrintCreateContext: + return ProcXpCreateContext(client); + case X_PrintSetContext: + return ProcXpSetContext(client); + case X_PrintGetContext: + return ProcXpGetContext(client); + case X_PrintDestroyContext: + return ProcXpDestroyContext(client); + case X_PrintGetContextScreen: + return ProcXpGetContextScreen(client); + case X_PrintStartJob: + return ProcXpStartJob(client); + case X_PrintEndJob: + return ProcXpEndJob(client); + case X_PrintStartDoc: + return ProcXpStartDoc(client); + case X_PrintEndDoc: + return ProcXpEndDoc(client); + case X_PrintStartPage: + return ProcXpStartPage(client); + case X_PrintEndPage: + return ProcXpEndPage(client); + case X_PrintSelectInput: + return ProcXpSelectInput(client); + case X_PrintInputSelected: + return ProcXpInputSelected(client); + case X_PrintPutDocumentData: + return ProcXpPutDocumentData(client); + case X_PrintGetDocumentData: + return ProcXpGetDocumentData(client); + case X_PrintSetAttributes: + return ProcXpSetAttributes(client); + case X_PrintGetAttributes: + return ProcXpGetAttributes(client); + case X_PrintGetOneAttribute: + return ProcXpGetOneAttribute(client); + case X_PrintRehashPrinterList: + return ProcXpRehashPrinterList(client); + case X_PrintQueryScreens: + return ProcXpQueryScreens(client); + case X_PrintGetPageDimensions: + return ProcXpGetPageDimensions(client); + case X_PrintSetImageResolution: + return ProcXpSetImageResolution(client); + case X_PrintGetImageResolution: + return ProcXpGetImageResolution(client); + default: + return BadRequest; + } +} + +static int +ProcXpSwappedDispatch(client) + ClientPtr client; +{ + int temp; + REQUEST(xReq); + + switch(stuff->data) + { + case X_PrintQueryVersion: + swaps(&stuff->length, temp); + return ProcXpQueryVersion(client); + case X_PrintGetPrinterList: + return SProcXpGetPrinterList(client); + case X_PrintCreateContext: + return SProcXpCreateContext(client); + case X_PrintSetContext: + return SProcXpSetContext(client); + case X_PrintGetContext: + return SProcXpGetContext(client); + case X_PrintDestroyContext: + return SProcXpDestroyContext(client); + case X_PrintGetContextScreen: + return SProcXpGetContextScreen(client); + case X_PrintStartJob: + return SProcXpStartJob(client); + case X_PrintEndJob: + return SProcXpEndJob(client); + case X_PrintStartDoc: + return SProcXpStartDoc(client); + case X_PrintEndDoc: + return SProcXpEndDoc(client); + case X_PrintStartPage: + return SProcXpStartPage(client); + case X_PrintEndPage: + return SProcXpEndPage(client); + case X_PrintSelectInput: + return SProcXpSelectInput(client); + case X_PrintInputSelected: + return SProcXpInputSelected(client); + case X_PrintPutDocumentData: + return SProcXpPutDocumentData(client); + case X_PrintGetDocumentData: + return SProcXpGetDocumentData(client); + case X_PrintSetAttributes: + return SProcXpSetAttributes(client); + case X_PrintGetAttributes: + return SProcXpGetAttributes(client); + case X_PrintGetOneAttribute: + return SProcXpGetOneAttribute(client); + case X_PrintRehashPrinterList: + return SProcXpRehashPrinterList(client); + case X_PrintQueryScreens: + swaps(&stuff->length, temp); + return ProcXpQueryScreens(client); + case X_PrintGetPageDimensions: + return SProcXpGetPageDimensions(client); + case X_PrintSetImageResolution: + return SProcXpSetImageResolution(client); + case X_PrintGetImageResolution: + return SProcXpGetImageResolution(client); + default: + return BadRequest; + } +} + +static int +ProcXpQueryVersion(client) + ClientPtr client; +{ + REQUEST(xPrintQueryVersionReq); + xPrintQueryVersionReply rep; + register int n; + long l; + + REQUEST_SIZE_MATCH(xPrintQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = XP_MAJOR_VERSION; + rep.minorVersion = XP_MINOR_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, l); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, sz_xPrintQueryVersionReply, (char *)&rep); + return client->noClientException; +} + +/******************************************************************************* + * + * GetPrinterList : Return a list of all printers associated with this + * server. Calls XpDiGetPrinterList, which is defined in + * the device-independent code in Xserver/Xprint. + * + ******************************************************************************/ + +static int +ProcXpGetPrinterList(client) + ClientPtr client; +{ + REQUEST(xPrintGetPrinterListReq); + int totalSize, numEntries; + XpDiListEntry **pList, *pEntry; + xPrintGetPrinterListReply *rep; + int n, i, totalBytes; + long l; + char *curByte; + + REQUEST_AT_LEAST_SIZE(xPrintGetPrinterListReq); + + totalSize = ((sz_xPrintGetPrinterListReq) >> 2) + + ((stuff->printerNameLen + 3) >> 2) + + ((stuff->localeLen + 3) >> 2); + if(totalSize != client->req_len) + return BadLength; + + pList = XpDiGetPrinterList(stuff->printerNameLen, (char *)(stuff + 1), + stuff->localeLen, (char *)((stuff + 1) + + QUADPAD(stuff->printerNameLen))); + + for(numEntries = 0, totalBytes = sz_xPrintGetPrinterListReply; + pList[numEntries] != (XpDiListEntry *)NULL; + numEntries++) + { + totalBytes += 2 * sizeof(CARD32); + totalBytes += QUADPAD(strlen(pList[numEntries]->name)); + totalBytes += QUADPAD(strlen(pList[numEntries]->description)); + } + + if((rep = (xPrintGetPrinterListReply *)xalloc(totalBytes)) == + (xPrintGetPrinterListReply *)NULL) + return BadAlloc; + + rep->type = X_Reply; + rep->length = (totalBytes - sz_xPrintGetPrinterListReply) >> 2; + rep->sequenceNumber = client->sequence; + rep->listCount = numEntries; + if (client->swapped) { + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, l); + swapl(&rep->listCount, l); + } + + for(i = 0, curByte = (char *)(rep + 1); i < numEntries; i++) + { + CARD32 *pCrd; + int len; + + pCrd = (CARD32 *)curByte; + len = strlen(pList[i]->name); + *pCrd = len; + if (client->swapped) + swapl((long *)curByte, l); + curByte += sizeof(CARD32); + strncpy(curByte, pList[i]->name, len); + curByte += QUADPAD(len); + + pCrd = (CARD32 *)curByte; + len = strlen(pList[i]->description); + *pCrd = len; + if (client->swapped) + swapl((long *)curByte, l); + curByte += sizeof(CARD32); + strncpy(curByte, pList[i]->description, len); + curByte += QUADPAD(len); + } + + XpDiFreePrinterList(pList); + + WriteToClient(client, totalBytes, (char *)rep); + xfree(rep); + return client->noClientException; +} + +/******************************************************************************* + * + * QueryScreens: Returns the list of screens which are associated with + * print drivers. + * + ******************************************************************************/ + +static int +ProcXpQueryScreens(client) + ClientPtr client; +{ + REQUEST(xPrintQueryScreensReq); + int i, numPrintScreens, totalSize; + WINDOW *pWinId; + xPrintQueryScreensReply *rep; + long l; + + REQUEST_SIZE_MATCH(xPrintQueryScreensReq); + + rep = (xPrintQueryScreensReply *)xalloc(sz_xPrintQueryScreensReply); + pWinId = (WINDOW *)(rep + 1); + + for(i = 0, numPrintScreens = 0, totalSize = sz_xPrintQueryScreensReply; + i < MAXSCREENS; i++) + { + /* + * If a screen has registered with our extension, then it's + * a printer screen. + */ + if(XpScreens[i] != (XpScreenPtr)NULL) + { + numPrintScreens++; + totalSize += sizeof(WINDOW); + rep = (xPrintQueryScreensReply *)xrealloc(rep, totalSize); + *pWinId = WindowTable[i]->drawable.id; + if (client->swapped) + swapl((long *)pWinId, l); + pWinId++; + } + } + + rep->type = X_Reply; + rep->sequenceNumber = client->sequence; + rep->length = (totalSize - sz_xPrintQueryScreensReply) >> 2; + rep->listCount = numPrintScreens; + if (client->swapped) + { + int n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, l); + swapl(&rep->listCount, l); + } + + WriteToClient(client, totalSize, (char *)rep); + xfree(rep); + return client->noClientException; +} + +static int +ProcXpGetPageDimensions(client) + ClientPtr client; +{ + REQUEST(xPrintGetPageDimensionsReq); + CARD16 width, height; + xRectangle rect; + xPrintGetPageDimensionsReply rep; + XpContextPtr pContext; + int result; + + REQUEST_SIZE_MATCH(xPrintGetPageDimensionsReq); + + if((pContext =(XpContextPtr)SecurityLookupIDByType(client, + stuff->printContext, + RTcontext, + SecurityReadAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + if(pContext->funcs.GetMediumDimensions != (int (*)())NULL) + result = pContext->funcs.GetMediumDimensions(pContext, &width, &height); + else + return BadImplementation; + + if(pContext->funcs.GetReproducibleArea != (int (*)())NULL) + result = pContext->funcs.GetReproducibleArea(pContext, &rect); + else + return BadImplementation; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.width = width; + rep.height = height; + rep.rx = rect.x; + rep.ry = rect.y; + rep.rwidth = rect.width; + rep.rheight = rect.height; + + if(client->swapped) + { + int n; + long l; + + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, l); + swaps(&rep.width, n); + swaps(&rep.height, n); + swaps(&rep.rx, n); + swaps(&rep.ry, n); + swaps(&rep.rwidth, n); + swaps(&rep.rheight, n); + } + + WriteToClient(client, sz_xPrintGetPageDimensionsReply, (char *)&rep); + return client->noClientException; +} + +static int +ProcXpSetImageResolution(client) + ClientPtr client; +{ + REQUEST(xPrintSetImageResolutionReq); + xPrintSetImageResolutionReply rep; + XpContextPtr pContext; + Bool status; + int result; + + REQUEST_SIZE_MATCH(xPrintSetImageResolutionReq); + + if((pContext =(XpContextPtr)SecurityLookupIDByType(client, + stuff->printContext, + RTcontext, + SecurityWriteAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + rep.prevRes = pContext->imageRes; + if(pContext->funcs.SetImageResolution != (int (*)())NULL) + result = pContext->funcs.SetImageResolution(pContext, + (int)stuff->imageRes, + &status); + else + status = FALSE; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.status = status; + + if(client->swapped) + { + int n; + long l; + + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, l); + swaps(&rep.prevRes, n); + } + + WriteToClient(client, sz_xPrintSetImageResolutionReply, (char *)&rep); + return client->noClientException; +} + +static int +ProcXpGetImageResolution(client) + ClientPtr client; +{ + REQUEST(xPrintGetImageResolutionReq); + xPrintGetImageResolutionReply rep; + XpContextPtr pContext; + Bool status; + int result; + + REQUEST_SIZE_MATCH(xPrintGetImageResolutionReq); + + if((pContext =(XpContextPtr)SecurityLookupIDByType(client, + stuff->printContext, + RTcontext, + SecurityReadAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.imageRes = pContext->imageRes; + + if(client->swapped) + { + int n; + long l; + + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, l); + swaps(&rep.imageRes, n); + } + + WriteToClient(client, sz_xPrintGetImageResolutionReply, (char *)&rep); + return client->noClientException; +} + +/******************************************************************************* + * + * RehashPrinterList : Cause the server's list of printers to be rebuilt. + * This allows new printers to be added, or old ones + * deleted without needing to restart the server. + * + ******************************************************************************/ + +static int +ProcXpRehashPrinterList(client) + ClientPtr client; +{ + REQUEST(xPrintRehashPrinterListReq); + + REQUEST_SIZE_MATCH(xPrintRehashPrinterListReq); + + return XpRehashPrinterList(); +} + +/****************************************************************************** + * + * Context functions: Init, Set, Destroy, FreeContext + * AllocateContextPrivateIndex, AllocateContextPrivate + * and supporting functions. + * + * Init creates a context, creates a XpClientRec for the calling + * client, and stores the contextPtr in the client's devPrivates. + * + * Set creates a XpClientRec for the calling client, and stores the + * contextPtr in the client's devPrivates unless the context is None. + * If the context is None, then the client's connection association + * with any context is removed. + * + * Destroy frees any and all XpClientRecs associated with the context, + * frees the context itself, and removes the contextPtr from any + * relevant client devPrivates. + * + * FreeContext is called by FreeResource to free up a context. + * + ******************************************************************************/ + +/* + * CreateContext creates and initializes the memory for the context itself. + * The driver's CreateContext function + * is then called. + */ +static int +ProcXpCreateContext(client) + ClientPtr client; +{ + REQUEST(xPrintCreateContextReq); + XpScreenPtr pPrintScreen; + WindowPtr pRoot; + char *printerName, *driverName; + XpContextPtr pContext; + XpClientPtr pNewPrintClient; + int result = Success; + XpDriverPtr pDriver; + + REQUEST_AT_LEAST_SIZE(xPrintCreateContextReq); + + LEGAL_NEW_RESOURCE(stuff->contextID, client); + + /* + * Check to see if the printer name is valid. + */ + if((pRoot = XpDiValidatePrinter(stuff + 1, stuff->printerNameLen)) == + (WindowPtr)NULL) + return BadMatch; + + pPrintScreen = XpScreens[pRoot->drawable.pScreen->myNum]; + + /* + * Allocate and add the context resource. + */ + if((pContext = (XpContextPtr) xalloc(totalContextSize)) == + (XpContextPtr) NULL) + return BadAlloc; + + InitContextPrivates(pContext); + + if(AddResource(stuff->contextID, RTcontext, (pointer) pContext) + != TRUE) + { + xfree(pContext); + return BadAlloc; + } + + pContext->contextID = stuff->contextID; + pContext->clientHead = (XpClientPtr)NULL; + pContext->screenNum = pRoot->drawable.pScreen->myNum; + pContext->state = 0; + pContext->clientSlept = (ClientPtr)NULL; + pContext->imageRes = 0; + + pContext->funcs.DestroyContext = (int (*)())NULL; + pContext->funcs.StartJob = (int (*)())NULL; + pContext->funcs.EndJob = (int (*)())NULL; + pContext->funcs.StartDoc = (int (*)())NULL; + pContext->funcs.EndDoc = (int (*)())NULL; + pContext->funcs.StartPage = (int (*)())NULL; + pContext->funcs.EndPage = (int (*)())NULL; + pContext->funcs.PutDocumentData = (int (*)())NULL; + pContext->funcs.GetDocumentData = (int (*)())NULL; + pContext->funcs.GetAttributes = (char * (*)())NULL; + pContext->funcs.GetOneAttribute = (char * (*)())NULL; + pContext->funcs.SetAttributes = (int (*)())NULL; + pContext->funcs.AugmentAttributes = (int (*)())NULL; + pContext->funcs.GetMediumDimensions = (int (*)())NULL; + pContext->funcs.GetReproducibleArea = (int (*)())NULL; + pContext->funcs.SetImageResolution = (int (*)())NULL; + + if((pContext->printerName = (char *)xalloc(stuff->printerNameLen + 1)) == + (char *)NULL) + { + /* Freeing the context also causes the XpClients to be freed. */ + FreeResource(stuff->contextID, RT_NONE); + return BadAlloc; + } + strncpy(pContext->printerName, (char *)(stuff + 1), stuff->printerNameLen); + pContext->printerName[stuff->printerNameLen] = (char)'\0'; + + driverName = XpDiGetDriverName(pRoot->drawable.pScreen->myNum, + pContext->printerName); + + for(pDriver = pPrintScreen->drivers; + pDriver != (XpDriverPtr)NULL; + pDriver = pDriver->next) + { + if(!strcmp(driverName, pDriver->name)) + { + if(pDriver->CreateContext != (Bool (*)())NULL) + pDriver->CreateContext(pContext); + else + return BadImplementation; + break; + } + } + + if (client->noClientException != Success) + return client->noClientException; + else + return result; +} + +/* + * SetContext creates the calling client's contextClient resource, + * and stashes the contextID in the client's devPrivate. + */ +static int +ProcXpSetContext(client) + ClientPtr client; +{ + REQUEST(xPrintSetContextReq); + + XpContextPtr pContext; + XpClientPtr pPrintClient; + int result = Success; + + REQUEST_AT_LEAST_SIZE(xPrintSetContextReq); + + if((pContext = client->devPrivates[XpClientPrivateIndex].ptr) != + (pointer)NULL) + { + /* + * Erase this client's knowledge of its old context, if any. + */ + if((pPrintClient = FindClient(pContext, client)) != (XpClientPtr)NULL) + { + XpUnsetFontResFunc(client); + + if(pPrintClient->eventMask == 0) + FreeXpClient(pPrintClient, TRUE); + } + + client->devPrivates[XpClientPrivateIndex].ptr = (pointer)NULL; + } + if(stuff->printContext == None) + return Success; + + /* + * Check to see that the supplied XID is really a valid print context + * in this server. + */ + if((pContext =(XpContextPtr)SecurityLookupIDByType(client, + stuff->printContext, + RTcontext, + SecurityWriteAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + if((pPrintClient = AcquireClient(pContext, client)) == (XpClientPtr)NULL) + return BadAlloc; + + client->devPrivates[XpClientPrivateIndex].ptr = pContext; + + XpSetFontResFunc(client); + + if (client->noClientException != Success) + return client->noClientException; + else + return result; +} + +XpContextPtr +XpGetPrintContext(client) + ClientPtr client; +{ + return (client->devPrivates[XpClientPrivateIndex].ptr); +} + +static int +ProcXpGetContext(client) + ClientPtr client; +{ + REQUEST(xPrintGetContextReq); + xPrintGetContextReply rep; + + XpContextPtr pContext; + XpClientPtr pNewPrintClient; + int result = Success; + register int n; + register long l; + + REQUEST_SIZE_MATCH(xPrintGetContextReq); + + if((pContext = client->devPrivates[XpClientPrivateIndex].ptr) == + (pointer)NULL) + rep.printContext = None; + else + rep.printContext = pContext->contextID; + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, l); + swapl(&rep.printContext, l); + } + WriteToClient(client, sz_xPrintGetContextReply, (char *)&rep); + return client->noClientException; +} + + +/* + * DestroyContext frees the context associated with the calling client. + * It operates by freeing the context resource ID, thus causing XpFreeContext + * to be called. + */ +static int +ProcXpDestroyContext(client) + ClientPtr client; +{ + REQUEST(xPrintDestroyContextReq); + + XpContextPtr pContext; + XpClientPtr pXpClient; + ClientPtr curClient; + + REQUEST_SIZE_MATCH(xPrintDestroyContextReq); + + if((pContext =(XpContextPtr)SecurityLookupIDByType(client, + stuff->printContext, + RTcontext, + SecurityDestroyAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + XpUnsetFontResFunc(client); + + FreeResource(pContext->contextID, RT_NONE); + + return Success; +} + +static int +ProcXpGetContextScreen(client) + ClientPtr client; +{ + REQUEST(xPrintGetContextScreenReq); + xPrintGetContextScreenReply rep; + XpContextPtr pContext; + int n; + long l; + + if((pContext =(XpContextPtr)SecurityLookupIDByType(client, + stuff->printContext, + RTcontext, + SecurityReadAccess)) + == (XpContextPtr)NULL) + return XpErrorBase+XPBadContext; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.rootWindow = WindowTable[pContext->screenNum]->drawable.id; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, l); + swapl(&rep.rootWindow, l); + } + + WriteToClient(client, sz_xPrintGetContextScreenReply, (char *)&rep); + return client->noClientException; +} + +/* + * XpFreeContext is the routine called by dix:FreeResource when a context + * resource ID is freed. + * It checks to see if there's a partial job pending on the context, and + * if so it calls the appropriate End procs with the cancel flag set. + * It calls the driver's DestroyContext routine to allow the driver to clean + * up any context-related memory or state. + * It calls FreeXpClient to free all the + * associated XpClientRecs and to set all the client->devPrivates to NULL. + * It frees the printer name string, and frees the context + * itself. + */ +static int +XpFreeContext(data, id) + pointer data; + XID id; +{ + XpContextPtr pContext = (XpContextPtr)data; + + /* Clean up any pending job on this context */ + if(pContext->state != 0) + { + if(pContext->state & PAGE_STARTED) + { + WindowPtr pWin = (WindowPtr )LookupIDByType( + pContext->pageWin, RT_WINDOW); + XpPagePtr pPage = (XpPagePtr)LookupIDByType( + pContext->pageWin, RTpage); + + pContext->funcs.EndPage(pContext, pWin, TRUE); + SendXpNotify(pContext, XPEndPageNotify, TRUE); + pContext->state &= ~PAGE_STARTED; + if(pPage) + pPage->context = (XpContextPtr)NULL; + } + if((pContext->state & DOC_RAW_STARTED) || + (pContext->state & DOC_COOKED_STARTED)) + { + pContext->funcs.EndDoc(pContext, TRUE); + SendXpNotify(pContext, XPEndDocNotify, TRUE); + pContext->state &= ~DOC_RAW_STARTED; + pContext->state &= ~DOC_COOKED_STARTED; + } + if(pContext->funcs.EndJob != (int (*)())NULL) + { + pContext->funcs.EndJob(pContext, TRUE); + SendXpNotify(pContext, XPEndJobNotify, TRUE); + pContext->state &= ~JOB_STARTED; + pContext->state &= ~GET_DOC_DATA_STARTED; + } + } + + /* + * Tell the driver we're destroying the context + * This allows the driver to free and ContextPrivate data + */ + if(pContext->funcs.DestroyContext != (int (*)())NULL) + pContext->funcs.DestroyContext(pContext); + + /* Free up all the XpClientRecs */ + while(pContext->clientHead != (XpClientPtr)NULL) + { + FreeXpClient(pContext->clientHead, TRUE); + } + + xfree(pContext->printerName); + xfree(pContext); + return Success; /* ??? */ +} + +/* + * XpFreeClient is the routine called by dix:FreeResource when a RTclient + * is freed. It simply calls the FreeXpClient routine to do the work. + */ +static int +XpFreeClient(data, id) + pointer data; + XID id; +{ + FreeXpClient((XpClientPtr)data, FALSE); +} + +/* + * FreeXpClient + * frees the ClientRec passed in, and sets the client->devPrivates to NULL + * if the client->devPrivates points to the same context as the XpClient. + * Called from XpFreeContext(from FreeResource), and + * XpFreeClient. The boolean freeResource specifies whether or not to call + * FreeResource for the XpClientRec's XID. We should free it except if we're + * called from XpFreeClient (which is itself called from FreeResource for the + * XpClientRec's XID). + */ +static void +FreeXpClient(pXpClient, freeResource) + XpClientPtr pXpClient; + Bool freeResource; +{ + XpClientPtr pCurrent, pPrev; + XpContextPtr pContext = pXpClient->context; + + /* + * If we're freeing the clientRec associated with the context tied + * to the client's devPrivates, then we need to clear the devPrivates. + */ + if(pXpClient->client->devPrivates[XpClientPrivateIndex].ptr == + pXpClient->context) + { + pXpClient->client->devPrivates[XpClientPrivateIndex].ptr = + (pointer)NULL; + } + + for(pPrev = (XpClientPtr)NULL, pCurrent = pContext->clientHead; + pCurrent != (XpClientPtr)NULL; + pCurrent = pCurrent->pNext) + { + if(pCurrent == pXpClient) + { + if(freeResource == TRUE) + FreeResource (pCurrent->contextClientID, RTclient); + + if (pPrev != (XpClientPtr)NULL) + pPrev->pNext = pCurrent->pNext; + else + pContext->clientHead = pCurrent->pNext; + + xfree (pCurrent); + break; + } + pPrev = pCurrent; + } +} + +/* + * CreateXpClient takes a ClientPtr and returns a pointer to a + * XpClientRec which it allocates. It also initializes the Rec, + * including adding a resource on behalf of the client to enable the + * freeing of the Rec when the client's connection is closed. + */ +static XpClientPtr +CreateXpClient(client) + ClientPtr client; +{ + XpClientPtr pNewPrintClient; + XID clientResource; + + if((pNewPrintClient = (XpClientPtr)xalloc(sizeof(XpClientRec))) == + (XpClientPtr)NULL) + return (XpClientPtr)NULL; + + clientResource = FakeClientID(client->index); + if(!AddResource(clientResource, RTclient, (pointer)pNewPrintClient)) + { + xfree (pNewPrintClient); + return (XpClientPtr)NULL; + } + + pNewPrintClient->pNext = (XpClientPtr)NULL; + pNewPrintClient->client = client; + pNewPrintClient->context = (XpContextPtr)NULL; + pNewPrintClient->eventMask = 0; + pNewPrintClient->contextClientID = clientResource; + + return pNewPrintClient; +} + +/* + * XpFreePage is the routine called by dix:FreeResource to free the page + * resource built with the same ID as a page window. It checks to see + * if we're in the middle of a page, and if so calls the driver's EndPage + * function with 'cancel' set TRUE. It frees the memory associated with + * the page resource. + */ +static int +XpFreePage(data, id) + pointer data; + XID id; +{ + XpPagePtr page = (XpPagePtr)data; + int result = Success; + WindowPtr pWin = (WindowPtr )LookupIDByType(id, RT_WINDOW); + + /* Check to see if the window's being deleted in the middle of a page */ + if(page->context != (XpContextPtr)NULL && + page->context->state & PAGE_STARTED) + { + XpScreenPtr pPrintScreen = XpScreens[page->context->screenNum]; + if(page->context->funcs.EndPage != (int (*)())NULL) + result = page->context->funcs.EndPage(page->context, pWin, TRUE); + SendXpNotify(page->context, XPEndPageNotify, (int)TRUE); + page->context->pageWin = 0; /* None, NULL??? XXX */ + } + + xfree(page); + return result; +} + +/* + * ContextPrivate machinery. + * Context privates are intended for use by the drivers, allowing the + * drivers to maintain context-specific data. The driver should free + * the associated data at DestroyContext time. + */ + +static void +InitContextPrivates(context) + XpContextPtr context; +{ + register char *ptr; + DevUnion *ppriv; + register unsigned *sizes; + register unsigned size; + register int i; + + if (totalContextSize == sizeof(XpContextRec)) + ppriv = (DevUnion *)NULL; + else + ppriv = (DevUnion *)(context + 1); + + context->devPrivates = ppriv; + sizes = contextPrivateSizes; + ptr = (char *)(ppriv + contextPrivateLen); + for (i = contextPrivateLen; --i >= 0; ppriv++, sizes++) + { + if ( (size = *sizes) ) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } +} + +static void +ResetContextPrivates() +{ + contextPrivateCount = 0; + contextPrivateLen = 0; + xfree(contextPrivateSizes); + contextPrivateSizes = (unsigned *)NULL; + totalContextSize = sizeof(XpContextRec); + +} + +int +XpAllocateContextPrivateIndex() +{ + return contextPrivateCount++; +} + +Bool +XpAllocateContextPrivate(index, amount) + int index; + unsigned amount; +{ + unsigned oldamount; + + if (index >= contextPrivateLen) + { + unsigned *nsizes; + nsizes = (unsigned *)xrealloc(contextPrivateSizes, + (index + 1) * sizeof(unsigned)); + if (!nsizes) + return FALSE; + while (contextPrivateLen <= index) + { + nsizes[contextPrivateLen++] = 0; + totalContextSize += sizeof(DevUnion); + } + contextPrivateSizes = nsizes; + } + oldamount = contextPrivateSizes[index]; + if (amount > oldamount) + { + contextPrivateSizes[index] = amount; + totalContextSize += (amount - oldamount); + } + return TRUE; +} + +static XpClientPtr +AcquireClient(pContext, client) + XpContextPtr pContext; + ClientPtr client; +{ + XpClientPtr pXpClient; + + if((pXpClient = FindClient(pContext, client)) != (XpClientPtr)NULL) + return pXpClient; + + if((pXpClient = CreateXpClient(client)) == (XpClientPtr)NULL) + return (XpClientPtr)NULL; + + pXpClient->context = pContext; + pXpClient->pNext = pContext->clientHead; + pContext->clientHead = pXpClient; + + return pXpClient; +} + +static XpClientPtr +FindClient(pContext, client) + XpContextPtr pContext; + ClientPtr client; +{ + XpClientPtr pXpClient; + + for(pXpClient = pContext->clientHead; pXpClient != (XpClientPtr)NULL; + pXpClient = pXpClient->pNext) + { + if(pXpClient->client == client) return pXpClient; + } + return (XpClientPtr)NULL; +} + + +/****************************************************************************** + * + * Start/End Functions: StartJob, EndJob, StartDoc, EndDoc, StartPage, EndPage + * + ******************************************************************************/ + +static int +ProcXpStartJob(client) + ClientPtr client; +{ + REQUEST(xPrintStartJobReq); + XpContextPtr pContext; + int result = Success; + XpScreenPtr pPrintScreen; + + REQUEST_SIZE_MATCH(xPrintStartJobReq); + + /* Check to see that a context has been established by this client. */ + if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr) + == (XpContextPtr)NULL) + return XpErrorBase+XPBadContext; + + if(pContext->state != 0) + return XpErrorBase+XPBadSequence; + + if(stuff->saveData != XPSpool && stuff->saveData != XPGetData) + { + client->errorValue = stuff->saveData; + return BadValue; + } + + pPrintScreen = XpScreens[pContext->screenNum]; + if(pContext->funcs.StartJob != (int (*)())NULL) + result = pContext->funcs.StartJob(pContext, + (stuff->saveData == XPGetData)? TRUE:FALSE); + else + return BadImplementation; + + pContext->state = JOB_STARTED; + if(stuff->saveData == XPGetData) + pContext->state |= JOB_GET_DATA; + + SendXpNotify(pContext, XPStartJobNotify, FALSE); + + if (client->noClientException != Success) + return client->noClientException; + else + return result; +} + +static int +ProcXpEndJob(client) + ClientPtr client; +{ + REQUEST(xPrintEndJobReq); + XpScreenPtr pPrintScreen; + WindowPtr pWin; + int result = Success; + XpContextPtr pContext; + + REQUEST_SIZE_MATCH(xPrintEndJobReq); + + if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr) + == (XpContextPtr)NULL) + return XpErrorBase+XPBadSequence; + + pPrintScreen = XpScreens[pContext->screenNum]; + + if(!(pContext->state & JOB_STARTED)) + return XpErrorBase+XPBadSequence; + + /* Check for missing EndDoc */ + if((pContext->state & DOC_RAW_STARTED) || + (pContext->state & DOC_COOKED_STARTED)) + { + if(pContext->state & PAGE_STARTED) + { + WindowPtr pWin = (WindowPtr )LookupIDByType( + pContext->pageWin, RT_WINDOW); + XpPagePtr pPage = (XpPagePtr)LookupIDByType( + pContext->pageWin, RTpage); + + if(stuff->cancel != TRUE) + return XpErrorBase+XPBadSequence; + + if(pContext->funcs.EndPage != (int (*)())NULL) + result = pContext->funcs.EndPage(pContext, pWin, TRUE); + else + return BadImplementation; + + SendXpNotify(pContext, XPEndPageNotify, TRUE); + + pContext->state &= ~PAGE_STARTED; + + if(pPage) + pPage->context = (XpContextPtr)NULL; + + if(result != Success) return result; + } + + if(pContext->funcs.EndDoc != (int (*)())NULL) + result = pContext->funcs.EndDoc(pContext, stuff->cancel); + else + return BadImplementation; + + SendXpNotify(pContext, XPEndDocNotify, stuff->cancel); + } + + if(pContext->funcs.EndJob != (int (*)())NULL) + result = pContext->funcs.EndJob(pContext, stuff->cancel); + else + return BadImplementation; + + pContext->state = 0; + + SendXpNotify(pContext, XPEndJobNotify, stuff->cancel); + + if (client->noClientException != Success) + return client->noClientException; + else + return result; +} + +static Bool +DoStartDoc(client, c) + ClientPtr client; + XpStDocPtr c; +{ + XpScreenPtr pPrintScreen; + int result = Success; + XpContextPtr pContext = c->pContext; + + if(c->pContext->state & JOB_GET_DATA && + !(c->pContext->state & GET_DOC_DATA_STARTED)) + { + if(!c->slept) + { + c->slept = TRUE; + ClientSleep(client, (ClientSleepProcPtr)DoStartDoc, (pointer) c); + c->pContext->clientSlept = client; + } + return TRUE; + } + + pPrintScreen = XpScreens[pContext->screenNum]; + + if(pContext->funcs.StartDoc != (int (*)())NULL) + result = pContext->funcs.StartDoc(pContext, c->type); + else + { + SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0, + BadImplementation); + return TRUE; + } + + if(c->type == XPDocNormal) + pContext->state |= DOC_COOKED_STARTED; + else + pContext->state |= DOC_RAW_STARTED; + + SendXpNotify(pContext, XPStartDocNotify, (int)FALSE); + + xfree(c); + return TRUE; +} + +static int +ProcXpStartDoc(client) + ClientPtr client; +{ + REQUEST(xPrintStartDocReq); + XpScreenPtr pPrintScreen; + int result = Success; + XpContextPtr pContext; + XpStDocPtr c; + + REQUEST_SIZE_MATCH(xPrintStartDocReq); + + if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr) + == (XpContextPtr)NULL) + return XpErrorBase+XPBadSequence; + + if(!(pContext->state & JOB_STARTED) || + pContext->state & DOC_RAW_STARTED || + pContext->state & DOC_COOKED_STARTED) + return XpErrorBase+XPBadSequence; + + if(stuff->type != XPDocNormal && stuff->type != XPDocRaw) + { + client->errorValue = stuff->type; + return BadValue; + } + + c = (XpStDocPtr)xalloc(sizeof(XpStDocRec)); + c->pContext = pContext; + c->type = stuff->type; + c->slept = FALSE; + (void)DoStartDoc(client, c); + + if (client->noClientException != Success) + return client->noClientException; + else + return result; +} + +static int +ProcXpEndDoc(client) + ClientPtr client; +{ + REQUEST(xPrintEndDocReq); + XpScreenPtr pPrintScreen; + XpContextPtr pContext; + int result = Success; + + REQUEST_SIZE_MATCH(xPrintEndDocReq); + + if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr) + == (XpContextPtr)NULL) + return XpErrorBase+XPBadSequence; + + pPrintScreen = XpScreens[pContext->screenNum]; + + if(!(pContext->state & DOC_RAW_STARTED) && + !(pContext->state & DOC_COOKED_STARTED)) + return XpErrorBase+XPBadSequence; + + if(pContext->state & PAGE_STARTED) + { + if(stuff->cancel == TRUE) + { + WindowPtr pWin = (WindowPtr )LookupIDByType( + pContext->pageWin, RT_WINDOW); + XpPagePtr pPage = (XpPagePtr)LookupIDByType( + pContext->pageWin, RTpage); + + if(pContext->funcs.EndPage != (int (*)())NULL) + result = pContext->funcs.EndPage(pContext, pWin, TRUE); + else + return BadImplementation; + + SendXpNotify(pContext, XPEndPageNotify, TRUE); + + if(pPage) + pPage->context = (XpContextPtr)NULL; + } + else + return XpErrorBase+XPBadSequence; + if(result != Success) + return result; + } + + if(pContext->funcs.EndDoc != (int (*)())NULL) + result = pContext->funcs.EndDoc(pContext, stuff->cancel); + else + return BadImplementation; + + pContext->state &= ~DOC_RAW_STARTED; + pContext->state &= ~DOC_COOKED_STARTED; + + SendXpNotify(pContext, XPEndDocNotify, stuff->cancel); + + if (client->noClientException != Success) + return client->noClientException; + else + return result; +} + +static Bool +DoStartPage(client, c) + ClientPtr client; + XpStPagePtr c; +{ + XpScreenPtr pPrintScreen; + WindowPtr pWin = c->pWin; + int result = Success; + XpContextPtr pContext = c->pContext; + XpPagePtr pPage; + + if(c->pContext->state & JOB_GET_DATA && + !(c->pContext->state & GET_DOC_DATA_STARTED)) + { + if(!c->slept) + { + c->slept = TRUE; + ClientSleep(client, (ClientSleepProcPtr)DoStartPage, (pointer) c); + c->pContext->clientSlept = client; + } + return TRUE; + } + + if(!(pContext->state & DOC_COOKED_STARTED)) + { + /* Implied StartDoc if it was omitted */ + if(pContext->funcs.StartDoc != (int (*)())NULL) + result = pContext->funcs.StartDoc(pContext, XPDocNormal); + else + { + SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0, + BadImplementation); + return TRUE; + } + + if(result != Success) + { + SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0, result); + return TRUE; + } + + pContext->state |= DOC_COOKED_STARTED; + SendXpNotify(pContext, XPStartDocNotify, (int)FALSE); + } + + /* ensure the window's not already being used as a page */ + if((pPage = (XpPagePtr)LookupIDByType(c->pWin->drawable.id, RTpage)) != + (XpPagePtr)NULL) + { + if(pPage->context != (XpContextPtr)NULL) + { + SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0, + BadWindow); + return TRUE; + } + } + else + { + if((pPage = (XpPagePtr)xalloc(sizeof(XpPageRec))) == (XpPagePtr)NULL) + { + SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0, + BadAlloc); + return TRUE; + } + if(AddResource(c->pWin->drawable.id, RTpage, pPage) == FALSE) + { + xfree(pPage); + SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0, + BadAlloc); + return TRUE; + } + } + + pPage->context = pContext; + pContext->pageWin = c->pWin->drawable.id; + + pPrintScreen = XpScreens[pContext->screenNum]; + + + if(pContext->funcs.StartPage != (int (*)())NULL) + result = pContext->funcs.StartPage(pContext, pWin); + else + { + SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0, + BadImplementation); + return TRUE; + } + + pContext->state |= PAGE_STARTED; + + (void)MapWindow(pWin, client); + + SendXpNotify(pContext, XPStartPageNotify, (int)FALSE); + + return TRUE; +} + +static int +ProcXpStartPage(client) + ClientPtr client; +{ + REQUEST(xPrintStartPageReq); + XpScreenPtr pPrintScreen; + WindowPtr pWin; + int result = Success; + XpContextPtr pContext; + XpPagePtr pPage; + XpStPagePtr c; + + REQUEST_SIZE_MATCH(xPrintStartPageReq); + + if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr) + == (XpContextPtr)NULL) + return XpErrorBase+XPBadSequence; + + if(!(pContext->state & JOB_STARTED)) + return XpErrorBase+XPBadSequence; + + /* can't have pages in a raw documented */ + if(pContext->state & DOC_RAW_STARTED) + return XpErrorBase+XPBadSequence; + + if(pContext->state & PAGE_STARTED) + return XpErrorBase+XPBadSequence; + + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin || pWin->drawable.pScreen->myNum != pContext->screenNum) + return BadWindow; + + if((c = (XpStPagePtr)xalloc(sizeof(XpStPageRec))) == (XpStPagePtr)NULL) + return BadAlloc; + c->pContext = pContext; + c->slept = FALSE; + c->pWin = pWin; + + (void)DoStartPage(client, c); + + if (client->noClientException != Success) + return client->noClientException; + else + return result; +} + +static int +ProcXpEndPage(client) + ClientPtr client; +{ + REQUEST(xPrintEndPageReq); + XpScreenPtr pPrintScreen; + int result = Success; + XpContextPtr pContext; + XpPagePtr page; + WindowPtr pWin; + + REQUEST_SIZE_MATCH(xPrintEndPageReq); + + if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr) + == (XpContextPtr)NULL) + return XpErrorBase+XPBadSequence; + + if(!(pContext->state & PAGE_STARTED)) + return XpErrorBase+XPBadSequence; + + pPrintScreen = XpScreens[pContext->screenNum]; + pWin = (WindowPtr )LookupIDByType(pContext->pageWin, RT_WINDOW); + + /* Call the ddx's EndPage proc. */ + if(pContext->funcs.EndPage != (int (*)())NULL) + result = pContext->funcs.EndPage(pContext, pWin, stuff->cancel); + else + return BadImplementation; + + if((page = (XpPagePtr)LookupIDByType(pContext->pageWin, RTpage)) != + (XpPagePtr)NULL) + page->context = (XpContextPtr)NULL; + + pContext->state &= ~PAGE_STARTED; + pContext->pageWin = 0; /* None, NULL??? XXX */ + + (void)UnmapWindow(pWin, FALSE); + + SendXpNotify(pContext, XPEndPageNotify, stuff->cancel); + + if (client->noClientException != Success) + return client->noClientException; + else + return result; +} + +/******************************************************************************* + * + * Document Data Functions: PutDocumentData, GetDocumentData + * + ******************************************************************************/ + +static int +ProcXpPutDocumentData(client) + ClientPtr client; +{ + REQUEST(xPrintPutDocumentDataReq); + XpContextPtr pContext; + DrawablePtr pDraw; + int result = Success; + int len, totalSize; + char *pData, *pDoc_fmt, *pOptions; + + REQUEST_AT_LEAST_SIZE(xPrintPutDocumentDataReq); + + if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr) + == (XpContextPtr)NULL) + return XpErrorBase+XPBadSequence; + + if(!(pContext->state & DOC_RAW_STARTED) && + !(pContext->state & DOC_COOKED_STARTED)) + return XpErrorBase+XPBadSequence; + + if (stuff->drawable) { + if (pContext->state & DOC_RAW_STARTED) + return BadDrawable; + pDraw = (DrawablePtr)LookupDrawable(stuff->drawable, client); + if (!pDraw || pDraw->pScreen->myNum != pContext->screenNum) + return BadDrawable; + } else { + if (pContext->state & DOC_COOKED_STARTED) + return BadDrawable; + pDraw = NULL; + } + + pData = (char *)(&stuff[1]); + + totalSize = (stuff->len_data + 3) >> 2; + pDoc_fmt = pData + (totalSize << 2); + + totalSize += (stuff->len_fmt + 3) >> 2; + pOptions = pData + (totalSize << 2); + + totalSize += (stuff->len_options + 3) >> 2; + if((totalSize + (sz_xPrintPutDocumentDataReq >> 2)) != client->req_len) + return BadLength; + + if(pContext->funcs.PutDocumentData != (int (*)())NULL) + { + result = (*pContext->funcs.PutDocumentData)(pContext, pDraw, + pData, stuff->len_data, + pDoc_fmt, stuff->len_fmt, + pOptions, stuff->len_options, + client); + } + else + return BadImplementation; + + if (client->noClientException != Success) + return client->noClientException; + else + return result; +} + +static int +ProcXpGetDocumentData(client) + ClientPtr client; +{ + REQUEST(xPrintGetDocumentDataReq); + xPrintGetDocumentDataReply rep; + XpScreenPtr pPrintScreen; + XpContextPtr pContext; + int result = Success; + + REQUEST_SIZE_MATCH(xPrintGetDocumentDataReq); + + if((pContext = (XpContextPtr)SecurityLookupIDByType(client, + stuff->printContext, + RTcontext, + SecurityWriteAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + if(pContext->funcs.GetDocumentData == (int (*)())NULL) + return BadImplementation; + + if(!(pContext->state & JOB_GET_DATA) || + pContext->state & GET_DOC_DATA_STARTED) + return XpErrorBase+XPBadSequence; + + if(stuff->maxBufferSize <= 0) + { + client->errorValue = stuff->maxBufferSize; + return BadValue; /* gotta have a positive buffer size */ + } + + result = (*pContext->funcs.GetDocumentData)(pContext, client, + stuff->maxBufferSize); + if(result != Success) + { + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.dataLen = 0; + rep.statusCode = 1; + rep.finishedFlag = TRUE; + if (client->swapped) { + int n; + long l; + + swaps(&rep.sequenceNumber, n); + swapl(&rep.statusCode, l); /* XXX Why are these longs??? */ + swapl(&rep.finishedFlag, l); /* XXX Why are these longs??? */ + } + (void)WriteToClient(client,sz_xPrintGetDocumentDataReply,(char *)&rep); + } + else + pContext->state |= GET_DOC_DATA_STARTED; + + if(pContext->clientSlept != (ClientPtr)NULL) + { + ClientSignal(pContext->clientSlept); + ClientWakeup(pContext->clientSlept); + pContext->clientSlept = (ClientPtr)NULL; + } + + return result; +} + +/******************************************************************************* + * + * Attribute requests: GetAttributes, SetAttributes, GetOneAttribute + * + ******************************************************************************/ + +static int +ProcXpGetAttributes(client) + ClientPtr client; +{ + REQUEST(xPrintGetAttributesReq); + XpContextPtr pContext; + char *attrs; + xPrintGetAttributesReply *pRep; + int totalSize, n; + unsigned long l; + + REQUEST_SIZE_MATCH(xPrintGetAttributesReq); + + if(stuff->type < XPJobAttr || stuff->type > XPServerAttr) + { + client->errorValue = stuff->type; + return BadValue; + } + + if(stuff->type != XPServerAttr) + { + if((pContext = (XpContextPtr)SecurityLookupIDByType( + client, + stuff->printContext, + RTcontext, + SecurityReadAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + if(pContext->funcs.GetAttributes == (char *(*)())NULL) + return BadImplementation; + if((attrs = (*pContext->funcs.GetAttributes)(pContext, stuff->type)) == + (char *)NULL) + return BadAlloc; + } + else + { + if((attrs = XpGetAttributes((XpContextPtr)NULL, XPServerAttr)) == + (char *)NULL) + return BadAlloc; + } + + totalSize = sz_xPrintGetAttributesReply + QUADPAD(strlen(attrs)); + if((pRep = (xPrintGetAttributesReply *)malloc(totalSize)) == + (xPrintGetAttributesReply *)NULL) + return BadAlloc; + + pRep->type = X_Reply; + pRep->length = (totalSize - sz_xPrintGetAttributesReply) >> 2; + pRep->sequenceNumber = client->sequence; + pRep->stringLen = strlen(attrs); + + if (client->swapped) { + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, l); + swapl(&pRep->stringLen, l); + } + + strncpy((char*)(pRep + 1), attrs, strlen(attrs)); + xfree(attrs); + + WriteToClient(client, totalSize, (char *)pRep); + + xfree(pRep); + + return client->noClientException; +} + +static int +ProcXpSetAttributes(client) + ClientPtr client; +{ + REQUEST(xPrintSetAttributesReq); + int result = Success; + XpContextPtr pContext; + char *attr; + + REQUEST_AT_LEAST_SIZE(xPrintSetAttributesReq); + + if(stuff->type < XPJobAttr || stuff->type > XPServerAttr) + { + client->errorValue = stuff->type; + return BadValue; + } + + /* + * Disallow changing of read-only attribute pools + */ + if(stuff->type == XPPrinterAttr || stuff->type == XPServerAttr) + return BadMatch; + + if((pContext = (XpContextPtr)SecurityLookupIDByType( + client, + stuff->printContext, + RTcontext, + SecurityWriteAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + if(pContext->funcs.SetAttributes == (int (*)())NULL) + return BadImplementation; + + /* + * Check for attributes being set after their relevant phase + * has already begun (e.g. Job attributes set after StartJob). + */ + if((pContext->state & JOB_STARTED) && stuff->type == XPJobAttr) + return XpErrorBase+XPBadSequence; + if(((pContext->state & DOC_RAW_STARTED) || + (pContext->state & DOC_COOKED_STARTED)) && stuff->type == XPDocAttr) + return XpErrorBase+XPBadSequence; + if((pContext->state & PAGE_STARTED) && stuff->type == XPPageAttr) + return XpErrorBase+XPBadSequence; + + if((attr = (char *)malloc(stuff->stringLen + 1)) == (char *)NULL) + return BadAlloc; + + strncpy(attr, (char *)(stuff + 1), stuff->stringLen); + attr[stuff->stringLen] = (char)'\0'; + + if(stuff->rule == XPAttrReplace) + (*pContext->funcs.SetAttributes)(pContext, stuff->type, attr); + else if(stuff->rule == XPAttrMerge) + (*pContext->funcs.AugmentAttributes)(pContext, stuff->type, attr); + else + { + client->errorValue = stuff->rule; + result = BadValue; + } + + xfree(attr); + + SendAttributeNotify(pContext, stuff->type); + + return result; +} + +static int +ProcXpGetOneAttribute(client) + ClientPtr client; +{ + REQUEST(xPrintGetOneAttributeReq); + XpContextPtr pContext; + char *value, *attrName; + xPrintGetOneAttributeReply *pRep; + int totalSize, n; + unsigned long l; + + REQUEST_AT_LEAST_SIZE(xPrintGetOneAttributeReq); + + totalSize = ((sz_xPrintGetOneAttributeReq) >> 2) + + ((stuff->nameLen + 3) >> 2); + if(totalSize != client->req_len) + return BadLength; + + if(stuff->type < XPJobAttr || stuff->type > XPServerAttr) + { + client->errorValue = stuff->type; + return BadValue; + } + + if((attrName = (char *)malloc(stuff->nameLen + 1)) == (char *)NULL) + return BadAlloc; + strncpy(attrName, (char *)(stuff+1), stuff->nameLen); + attrName[stuff->nameLen] = (char)'\0'; + + if(stuff->type != XPServerAttr) + { + if((pContext = (XpContextPtr)SecurityLookupIDByType( + client, + stuff->printContext, + RTcontext, + SecurityReadAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + if(pContext->funcs.GetOneAttribute == (char *(*)())NULL) + return BadImplementation; + if((value = (*pContext->funcs.GetOneAttribute)(pContext, stuff->type, + attrName)) == (char *)NULL) + return BadAlloc; + } + else + { + if((value = XpGetOneAttribute((XpContextPtr)NULL, XPServerAttr, + attrName)) == (char *)NULL) + return BadAlloc; + } + + free(attrName); + + totalSize = sz_xPrintGetOneAttributeReply + QUADPAD(strlen(value)); + if((pRep = (xPrintGetOneAttributeReply *)malloc(totalSize)) == + (xPrintGetOneAttributeReply *)NULL) + return BadAlloc; + + pRep->type = X_Reply; + pRep->length = (totalSize - sz_xPrintGetOneAttributeReply) >> 2; + pRep->sequenceNumber = client->sequence; + pRep->valueLen = strlen(value); + + if (client->swapped) { + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, l); + swapl(&pRep->valueLen, l); + } + + strncpy((char*)(pRep + 1), value, strlen(value)); + + WriteToClient(client, totalSize, (char *)pRep); + + xfree(pRep); + + return client->noClientException; +} + +/******************************************************************************* + * + * Print Event requests: SelectInput InputSelected, SendXpNotify + * + ******************************************************************************/ + + +static int +ProcXpSelectInput(client) + ClientPtr client; +{ + REQUEST(xPrintSelectInputReq); + int result = Success; + XpContextPtr pContext; + XpClientPtr pPrintClient; + + REQUEST_SIZE_MATCH(xPrintSelectInputReq); + + /* + * Check to see that the supplied XID is really a valid print context + * in this server. + */ + if((pContext=(XpContextPtr)SecurityLookupIDByType(client, + stuff->printContext, + RTcontext, + SecurityWriteAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + if(stuff->eventMask & ~allEvents) + { + client->errorValue = stuff->eventMask; + return BadValue; /* bogus event mask bits */ + } + + if((pPrintClient = AcquireClient(pContext, client)) == (XpClientPtr)NULL) + return BadAlloc; + + pPrintClient->eventMask = stuff->eventMask; + + return result; +} + +static int +ProcXpInputSelected(client) + ClientPtr client; +{ + REQUEST(xPrintInputSelectedReq); + xPrintInputSelectedReply rep; + register int n; + long l, allMask; + WindowPtr pWin; + XpClientPtr pXpClient; + XpContextPtr pContext; + + REQUEST_SIZE_MATCH(xPrintInputSelectedReq); + + if((pContext=(XpContextPtr)SecurityLookupIDByType(client, + stuff->printContext, + RTcontext, + SecurityReadAccess)) + == (XpContextPtr)NULL) + { + client->errorValue = stuff->printContext; + return XpErrorBase+XPBadContext; + } + + pXpClient = FindClient(pContext, client); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.eventMask = (pXpClient != (XpClientPtr)NULL)? pXpClient->eventMask : 0; + rep.allEventsMask = GetAllEventMasks(pContext); + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, l); + swapl(&rep.eventMask, l); + swapl(&rep.allEventsMask, l); + } + + WriteToClient(client, sz_xPrintInputSelectedReply, (char *)&rep); + return client->noClientException; +} + +static void +SendAttributeNotify(pContext, which) + XpContextPtr pContext; + int which; +{ + XpClientPtr pXpClient; + xPrintAttributeEvent ae; + ClientPtr client; + + pXpClient = pContext->clientHead; + if(pXpClient == (XpClientPtr)NULL) + return; /* Nobody's interested in the events (or this context). */ + + for (pXpClient = pContext->clientHead; + pXpClient != (XpClientPtr)NULL; + pXpClient = pXpClient->pNext) + { + client = pXpClient->client; + if (client == serverClient || client->clientGone || + !(pXpClient->eventMask & XPAttributeMask)) + continue; + ae.type = XPAttributeNotify + XpEventBase; + ae.detail = which; + ae.printContext = pContext->contextID; + ae.sequenceNumber = client->sequence; + WriteEventsToClient (client, 1, (xEvent *) &ae); + } +} +static void +SendXpNotify(pContext, which, val) + XpContextPtr pContext; + int which; + int val; +{ + XpClientPtr pXpClient; + xPrintPrintEvent pe; + ClientPtr client; + + pXpClient = pContext->clientHead; + if(pXpClient == (XpClientPtr)NULL) + return; /* Nobody's interested in the events (or this context). */ + + for (pXpClient = pContext->clientHead; + pXpClient != (XpClientPtr)NULL; + pXpClient = pXpClient->pNext) + { + client = pXpClient->client; + if (client == serverClient || client->clientGone || + !(pXpClient->eventMask & XPPrintMask)) + continue; + pe.type = XPPrintNotify + XpEventBase; + pe.detail = which; + pe.printContext = pContext->contextID; + pe.cancel = (Bool)val; + pe.sequenceNumber = client->sequence; + WriteEventsToClient (client, 1, (xEvent *) &pe); + } +} + +static CARD32 +GetAllEventMasks(pContext) + XpContextPtr pContext; +{ + XpClientPtr pPrintClient; + CARD32 totalMask = (CARD32)0; + + for (pPrintClient = pContext->clientHead; + pPrintClient != (XpClientPtr)NULL; + pPrintClient = pPrintClient->pNext) + { + totalMask |= pPrintClient->eventMask; + } + return totalMask; +} + +/* + * XpContextOfClient - returns the XpContextPtr to the context + * associated with the specified client, or NULL if the client + * does not currently have a context set. + */ +XpContextPtr +XpContextOfClient(client) + ClientPtr client; +{ + XpContextPtr pContext; + + return (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr; +} + + +/******************************************************************************* + * + * Swap-request functions + * + ******************************************************************************/ + +static int +SProcXpCreateContext(client) + ClientPtr client; +{ + int i; + long n; + + REQUEST(xPrintCreateContextReq); + + swaps(&stuff->length, i); + swapl(&stuff->contextID, n); + swapl(&stuff->printerNameLen, n); + swapl(&stuff->localeLen, n); + return ProcXpCreateContext(client); +} + +static int +SProcXpGetPrinterList(client) + ClientPtr client; +{ + int i; + long n; + + REQUEST(xPrintGetPrinterListReq); + + swaps(&stuff->length, i); + swapl(&stuff->printerNameLen, n); + swapl(&stuff->localeLen, n); + return ProcXpGetPrinterList(client); +} + +static int +SProcXpRehashPrinterList(client) + ClientPtr client; +{ + int i; + long n; + + REQUEST(xPrintRehashPrinterListReq); + swaps(&stuff->length, i); + return ProcXpRehashPrinterList(client); +} + +static int +SProcXpSetContext(client) + ClientPtr client; +{ + int i; + long n; + + REQUEST(xPrintSetContextReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, i); + return ProcXpSetContext(client); +} + +static int +SProcXpGetContext(client) + ClientPtr client; +{ + int i; + + REQUEST(xPrintGetContextReq); + swaps(&stuff->length, i); + return ProcXpGetContext(client); +} + +static int +SProcXpDestroyContext(client) + ClientPtr client; +{ + int i; + long n; + + REQUEST(xPrintDestroyContextReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, n); + return ProcXpDestroyContext(client); +} + +static int +SProcXpGetContextScreen(client) + ClientPtr client; +{ + int i; + long n; + + REQUEST(xPrintGetContextScreenReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, n); + return ProcXpGetContextScreen(client); +} + +static int +SProcXpInputSelected(client) + ClientPtr client; +{ + int i; + long n; + + REQUEST(xPrintInputSelectedReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, n); + return ProcXpInputSelected(client); +} + +static int +SProcXpStartJob(client) + ClientPtr client; +{ + int i; + + REQUEST(xPrintStartJobReq); + swaps(&stuff->length, i); + return ProcXpStartJob(client); +} + +static int +SProcXpEndJob(client) + ClientPtr client; +{ + int i; + + REQUEST(xPrintEndJobReq); + swaps(&stuff->length, i); + return ProcXpEndJob(client); +} + +static int +SProcXpStartDoc(client) + ClientPtr client; +{ + int i; + + REQUEST(xPrintStartDocReq); + swaps(&stuff->length, i); + return ProcXpStartDoc(client); +} + +static int +SProcXpEndDoc(client) + ClientPtr client; +{ + int i; + + REQUEST(xPrintEndDocReq); + swaps(&stuff->length, i); + return ProcXpEndDoc(client); +} + +static int +SProcXpStartPage(client) + ClientPtr client; +{ + int i; + long n; + + REQUEST(xPrintStartPageReq); + swaps(&stuff->length, i); + swapl(&stuff->window, n); + return ProcXpStartPage(client); +} + +static int +SProcXpEndPage(client) + ClientPtr client; +{ + int i; + + REQUEST(xPrintEndPageReq); + swaps(&stuff->length, i); + return ProcXpEndPage(client); +} + +static int +SProcXpPutDocumentData(client) + ClientPtr client; +{ + long n; + int i; + + REQUEST(xPrintPutDocumentDataReq); + swaps(&stuff->length, i); + swapl(&stuff->drawable, n); + swapl(&stuff->len_data, n); + swaps(&stuff->len_fmt, i); + swaps(&stuff->len_options, i); + return ProcXpPutDocumentData(client); +} + +static int +SProcXpGetDocumentData(client) + ClientPtr client; +{ + long n; + int i; + + REQUEST(xPrintGetDocumentDataReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, n); + swapl(&stuff->maxBufferSize, n); + return ProcXpGetDocumentData(client); +} + +static int +SProcXpGetAttributes(client) + ClientPtr client; +{ + long n; + int i; + + REQUEST(xPrintGetAttributesReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, n); + return ProcXpGetAttributes(client); +} + +static int +SProcXpSetAttributes(client) + ClientPtr client; +{ + long n; + int i; + + REQUEST(xPrintSetAttributesReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, n); + swapl(&stuff->stringLen, n); + return ProcXpSetAttributes(client); +} + +static int +SProcXpGetOneAttribute(client) + ClientPtr client; +{ + long n; + int i; + + REQUEST(xPrintGetOneAttributeReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, n); + swapl(&stuff->nameLen, n); + return ProcXpGetOneAttribute(client); +} + +static int +SProcXpSelectInput(client) + ClientPtr client; +{ + long n; + int i; + + REQUEST(xPrintSelectInputReq); + swaps(&stuff->length, i); + swapl(&stuff->eventMask, n); + swapl(&stuff->printContext, n); + return ProcXpSelectInput(client); +} +static int +SProcXpGetPageDimensions(client) + ClientPtr client; +{ + long n; + int i; + + REQUEST(xPrintGetPageDimensionsReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, n); + return ProcXpGetPageDimensions(client); +} +static int +SProcXpSetImageResolution(client) + ClientPtr client; +{ + long n; + int i; + + REQUEST(xPrintSetImageResolutionReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, n); + swaps(&stuff->imageRes, i); + return ProcXpSetImageResolution(client); +} +static int +SProcXpGetImageResolution(client) + ClientPtr client; +{ + long n; + int i; + + REQUEST(xPrintGetImageResolutionReq); + swaps(&stuff->length, i); + swapl(&stuff->printContext, n); + return ProcXpGetImageResolution(client); +} + +static void +SwapXpNotifyEvent(src, dst) + xPrintPrintEvent *src, *dst; +{ + /* + * Swap the sequence number and context fields. + */ + cpswaps(src->sequenceNumber, dst->sequenceNumber); + cpswapl(src->printContext, dst->printContext); + + /* + * Copy the byte-long fields. + */ + dst->type = src->type; + dst->detail = src->detail; + dst->cancel = src->cancel; +} + +static void +SwapXpAttributeEvent(src, dst) + xPrintAttributeEvent *src, *dst; +{ + /* + * Swap the sequence number and context fields. + */ + cpswaps(src->sequenceNumber, dst->sequenceNumber); + cpswapl(src->printContext, dst->printContext); + + /* + * Copy the byte-long fields. + */ + dst->type = src->type; + dst->detail = src->detail; +}