First import
[xorg_rtime.git] / xorg-server-1.4 / Xext / xprint.c
blob4ac13e6d1278d6351170850ef320e3fddfa38205
1 /*
2 (c) Copyright 1996 Hewlett-Packard Company
3 (c) Copyright 1996 International Business Machines Corp.
4 (c) Copyright 1996 Sun Microsystems, Inc.
5 (c) Copyright 1996 Novell, Inc.
6 (c) Copyright 1996 Digital Equipment Corp.
7 (c) Copyright 1996 Fujitsu Limited
8 (c) Copyright 1996 Hitachi, Ltd.
10 Permission is hereby granted, free of charge, to any person obtaining a copy
11 of this software and associated documentation files (the "Software"), to deal
12 in the Software without restriction, including without limitation the rights
13 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 copies of the Software, and to permit persons to whom the Software is
15 furnished to do so, subject to the following conditions:
17 The above copyright notice and this permission notice shall be included in
18 all copies or substantial portions of the Software.
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
24 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 Except as contained in this notice, the names of the copyright holders shall
28 not be used in advertising or otherwise to promote the sale, use or other
29 dealings in this Software without prior written authorization from said
30 copyright holders.
32 /*******************************************************************
34 ** *********************************************************
35 ** *
36 ** * File: xprint.c
37 ** *
38 ** * Copyright: Copyright 1993, 1995 Hewlett-Packard Company
39 ** *
40 ** * Copyright 1989 by The Massachusetts Institute of Technology
41 ** *
42 ** * Permission to use, copy, modify, and distribute this
43 ** * software and its documentation for any purpose and without
44 ** * fee is hereby granted, provided that the above copyright
45 ** * notice appear in all copies and that both that copyright
46 ** * notice and this permission notice appear in supporting
47 ** * documentation, and that the name of MIT not be used in
48 ** * advertising or publicity pertaining to distribution of the
49 ** * software without specific prior written permission.
50 ** * M.I.T. makes no representation about the suitability of
51 ** * this software for any purpose. It is provided "as is"
52 ** * without any express or implied warranty.
53 ** *
54 ** * MIT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
55 ** * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
56 ** * NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MIT BE LI-
57 ** * ABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
58 ** * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
59 ** * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
60 ** * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
61 ** * THE USE OR PERFORMANCE OF THIS SOFTWARE.
62 ** *
63 ** *********************************************************
65 ********************************************************************/
67 #define _XP_PRINT_SERVER_
68 #ifdef HAVE_DIX_CONFIG_H
69 #include <dix-config.h>
70 #endif
72 #include <X11/X.h>
73 #include <X11/Xos.h>
74 #define NEED_EVENTS
75 #include <X11/Xproto.h>
76 #undef NEED_EVENTS
77 #include "misc.h"
78 #include "windowstr.h"
79 #include "scrnintstr.h"
80 #include "pixmapstr.h"
81 #include "extnsionst.h"
82 #include "dixstruct.h"
83 #include <X11/Xatom.h>
84 #include <X11/extensions/Print.h>
85 #include <X11/extensions/Printstr.h>
86 #include "../hw/xprint/DiPrint.h"
87 #include "../hw/xprint/attributes.h"
88 #include "modinit.h"
90 static void XpResetProc(ExtensionEntry *);
92 static int ProcXpDispatch(ClientPtr);
93 static int ProcXpSwappedDispatch(ClientPtr);
95 static int ProcXpQueryVersion(ClientPtr);
96 static int ProcXpGetPrinterList(ClientPtr);
97 static int ProcXpCreateContext(ClientPtr);
98 static int ProcXpSetContext(ClientPtr);
99 static int ProcXpGetContext(ClientPtr);
100 static int ProcXpDestroyContext(ClientPtr);
101 static int ProcXpGetContextScreen(ClientPtr);
102 static int ProcXpStartJob(ClientPtr);
103 static int ProcXpEndJob(ClientPtr);
104 static int ProcXpStartDoc(ClientPtr);
105 static int ProcXpEndDoc(ClientPtr);
106 static int ProcXpStartPage(ClientPtr);
107 static int ProcXpEndPage(ClientPtr);
108 static int ProcXpSelectInput(ClientPtr);
109 static int ProcXpInputSelected(ClientPtr);
110 static int ProcXpPutDocumentData(ClientPtr);
111 static int ProcXpGetDocumentData(ClientPtr);
112 static int ProcXpGetAttributes(ClientPtr);
113 static int ProcXpGetOneAttribute(ClientPtr);
114 static int ProcXpSetAttributes(ClientPtr);
115 static int ProcXpRehashPrinterList(ClientPtr);
116 static int ProcXpQueryScreens(ClientPtr);
117 static int ProcXpGetPageDimensions(ClientPtr);
118 static int ProcXpSetImageResolution(ClientPtr);
119 static int ProcXpGetImageResolution(ClientPtr);
121 static void SwapXpNotifyEvent(xPrintPrintEvent *, xPrintPrintEvent *);
122 static void SwapXpAttributeEvent(xPrintAttributeEvent *, xPrintAttributeEvent *);
124 static int SProcXpGetPrinterList(ClientPtr);
125 static int SProcXpCreateContext(ClientPtr);
126 static int SProcXpSetContext(ClientPtr);
127 static int SProcXpGetContext(ClientPtr);
128 static int SProcXpDestroyContext(ClientPtr);
129 static int SProcXpGetContextScreen(ClientPtr);
130 static int SProcXpStartJob(ClientPtr);
131 static int SProcXpEndJob(ClientPtr);
132 static int SProcXpStartDoc(ClientPtr);
133 static int SProcXpEndDoc(ClientPtr);
134 static int SProcXpStartPage(ClientPtr);
135 static int SProcXpEndPage(ClientPtr);
136 static int SProcXpSelectInput(ClientPtr);
137 static int SProcXpInputSelected(ClientPtr);
138 static int SProcXpPutDocumentData(ClientPtr);
139 static int SProcXpGetDocumentData(ClientPtr);
140 static int SProcXpGetAttributes(ClientPtr);
141 static int SProcXpGetOneAttribute(ClientPtr);
142 static int SProcXpSetAttributes(ClientPtr);
143 static int SProcXpRehashPrinterList(ClientPtr);
144 static int SProcXpGetPageDimensions(ClientPtr);
145 static int SProcXpSetImageResolution(ClientPtr);
146 static int SProcXpGetImageResolution(ClientPtr);
148 static void SendXpNotify(XpContextPtr, int, int);
149 static void SendAttributeNotify(XpContextPtr, int);
150 static int XpFreeClient(pointer, XID);
151 static int XpFreeContext(pointer, XID);
152 static int XpFreePage(pointer, XID);
153 static Bool XpCloseScreen(int, ScreenPtr);
154 static CARD32 GetAllEventMasks(XpContextPtr);
155 static struct _XpClient *CreateXpClient(ClientPtr);
156 static void InitContextPrivates(XpContextPtr);
157 static void ResetContextPrivates(void);
158 static struct _XpClient *FindClient(XpContextPtr, ClientPtr);
159 static struct _XpClient *AcquireClient(XpContextPtr, ClientPtr);
161 typedef struct _driver {
162 struct _driver *next;
163 char *name;
164 int (* CreateContext)(XpContextPtr);
165 } XpDriverRec, *XpDriverPtr;
167 typedef struct _xpScreen {
168 Bool (* CloseScreen)(int, ScreenPtr);
169 struct _driver *drivers;
170 } XpScreenRec, *XpScreenPtr;
173 * Each context has a list of XpClients indicating which clients have
174 * associated this context with their connection.
175 * Each such client has a RTclient resource allocated for it,
176 * and this per-client
177 * resource is used to delete the XpClientRec if/when the client closes
178 * its connection.
179 * The list of XpClients is also walked if/when the context is destroyed
180 * so that the ContextPtr can be removed from the client's devPrivates.
182 typedef struct _XpClient {
183 struct _XpClient *pNext;
184 ClientPtr client;
185 XpContextPtr context;
186 CARD32 eventMask;
187 XID contextClientID; /* unneeded sanity check? */
188 } XpClientRec, *XpClientPtr;
190 static void FreeXpClient(XpClientPtr, Bool);
193 * Each StartPage request specifies a window which forms the top level
194 * window of the page. One of the following structs is created as a
195 * RTpage resource with the same ID as the window itself. This enables
196 * us to clean up when/if the window is destroyed, and to prevent the
197 * same window from being simultaneously referenced in multiple contexts.
198 * The page resource is created at the first StartPage on a given window,
199 * and is only destroyed when/if the window is destroyed. When the
200 * EndPage is recieved (or an EndDoc or EndJob) the context field is
201 * set to NULL, but the resource remains alive.
203 typedef struct _XpPage {
204 XpContextPtr context;
205 } XpPageRec, *XpPagePtr;
207 typedef struct _XpStPageRec {
208 XpContextPtr pContext;
209 Bool slept;
210 XpPagePtr pPage;
211 WindowPtr pWin;
212 } XpStPageRec, *XpStPagePtr;
214 typedef struct _XpStDocRec {
215 XpContextPtr pContext;
216 Bool slept;
217 CARD8 type;
218 } XpStDocRec, *XpStDocPtr;
220 #define QUADPAD(x) ((((x)+3)>>2)<<2)
223 * Possible bit-mask values in the "state" field of a XpContextRec.
225 #define JOB_STARTED (1 << 0)
226 #define DOC_RAW_STARTED (1 << 1)
227 #define DOC_COOKED_STARTED (1 << 2)
228 #define PAGE_STARTED (1 << 3)
229 #define GET_DOC_DATA_STARTED (1 << 4)
230 #define JOB_GET_DATA (1 << 5)
232 static XpScreenPtr XpScreens[MAXSCREENS];
233 static unsigned char XpReqCode;
234 static int XpEventBase;
235 static int XpErrorBase;
236 static unsigned long XpGeneration = 0;
237 static int XpClientPrivateIndex;
239 /* Variables for the context private machinery.
240 * These must be initialized at compile time because
241 * main() calls InitOutput before InitExtensions, and the
242 * output drivers are likely to call AllocateContextPrivate.
243 * These variables are reset at CloseScreen time. CloseScreen
244 * is used because it occurs after FreeAllResources, and before
245 * the next InitOutput cycle.
247 static int contextPrivateCount = 0;
248 static int contextPrivateLen = 0;
249 static unsigned *contextPrivateSizes = (unsigned *)NULL;
250 static unsigned totalContextSize = sizeof(XpContextRec);
253 * There are three types of resources involved. One is the resource associated
254 * with the context itself, with an ID specified by a printing client. The
255 * next is a resource created by us on the client's behalf (and unknown to
256 * the client) when a client inits or sets a context which allows us to
257 * track each client's interest in events
258 * on a particular context, and also allows us to clean up this interest
259 * record when/if the client's connection is closed. Finally, there is
260 * a resource created for each window that's specified in a StartPage. This
261 * resource carries the same ID as the window itself, and enables us to
262 * easily prevent the same window being referenced in multiple contexts
263 * simultaneously, and enables us to clean up if the window is destroyed
264 * before the EndPage.
266 static RESTYPE RTclient, RTcontext, RTpage;
269 * allEvents is the OR of all the legal event mask bits.
271 static CARD32 allEvents = XPPrintMask | XPAttributeMask;
274 /*******************************************************************************
276 * ExtensionInit, Driver Init functions, QueryVersion, and Dispatch procs
278 ******************************************************************************/
281 * XpExtensionInit
283 * Called from InitExtensions in main() usually through miinitextension
287 void
288 XpExtensionInit(INITARGS)
290 ExtensionEntry *extEntry;
291 int i;
293 RTclient = CreateNewResourceType(XpFreeClient);
294 RTcontext = CreateNewResourceType(XpFreeContext);
295 RTpage = CreateNewResourceType(XpFreePage);
296 if (RTclient && RTcontext && RTpage &&
297 (extEntry = AddExtension(XP_PRINTNAME, XP_EVENTS, XP_ERRORS,
298 ProcXpDispatch, ProcXpSwappedDispatch,
299 XpResetProc, StandardMinorOpcode)))
301 XpReqCode = (unsigned char)extEntry->base;
302 XpEventBase = extEntry->eventBase;
303 XpErrorBase = extEntry->errorBase;
304 EventSwapVector[XpEventBase] = (EventSwapPtr) SwapXpNotifyEvent;
305 EventSwapVector[XpEventBase+1] = (EventSwapPtr) SwapXpAttributeEvent;
308 if(XpGeneration != serverGeneration)
310 XpClientPrivateIndex = AllocateClientPrivateIndex();
312 * We allocate 0 length & simply stuff a pointer to the
313 * ContextRec in the DevUnion.
315 if(AllocateClientPrivate(XpClientPrivateIndex, 0) != TRUE)
317 /* we can't alloc a client private, should we bail??? XXX */
319 XpGeneration = serverGeneration;
322 for(i = 0; i < MAXSCREENS; i++)
325 * If a screen has registered with our extension, then we
326 * wrap the screen's CloseScreen function to allow us to
327 * reset our ContextPrivate stuff. Note that this
328 * requires a printing DDX to call XpRegisterInitFunc
329 * _before_ this extension is initialized - i.e. at screen init
330 * time, _not_ at root window creation time.
332 if(XpScreens[i] != (XpScreenPtr)NULL)
334 XpScreens[i]->CloseScreen = screenInfo.screens[i]->CloseScreen;
335 screenInfo.screens[i]->CloseScreen = XpCloseScreen;
338 DeclareExtensionSecurity(XP_PRINTNAME, TRUE);
341 static void
342 XpResetProc(ExtensionEntry *extEntry)
345 * We can't free up the XpScreens recs here, because extensions are
346 * closed before screens, and our CloseScreen function uses the XpScreens
347 * recs.
349 int i;
351 for(i = 0; i < MAXSCREENS; i++)
353 if(XpScreens[i] != (XpScreenPtr)NULL)
354 Xfree(XpScreens[i]);
355 XpScreens[i] = (XpScreenPtr)NULL;
360 static Bool
361 XpCloseScreen(int index, ScreenPtr pScreen)
363 Bool (* CloseScreen)(int, ScreenPtr);
365 CloseScreen = XpScreens[index]->CloseScreen;
366 if(XpScreens[index] != (XpScreenPtr)NULL)
368 XpDriverPtr pDriv, nextDriv;
370 pDriv = XpScreens[index]->drivers;
371 while(pDriv != (XpDriverPtr)NULL)
373 nextDriv = pDriv->next;
374 Xfree(pDriv);
375 pDriv = nextDriv;
377 Xfree(XpScreens[index]);
379 XpScreens[index] = (XpScreenPtr)NULL;
382 * It's wasteful to call ResetContextPrivates() at every CloseScreen,
383 * but it's the best we know how to do for now. We do this because we
384 * have to wait until after all resources have been freed (so we know
385 * how to free the ContextRecs), and before the next InitOutput cycle.
386 * See dix/main.c for the order of initialization and reset.
388 ResetContextPrivates();
389 return (*CloseScreen)(index, pScreen);
392 #if 0 /* NOT USED */
393 static void
394 FreeScreenEntry(XpScreenPtr pScreenEntry)
396 XpDriverPtr pDriver;
398 pDriver = pScreenEntry->drivers;
399 while(pDriver != (XpDriverPtr)NULL)
401 XpDriverPtr tmp;
403 tmp = pDriver->next;
404 xfree(pDriver);
405 pDriver = tmp;
407 xfree(pScreenEntry);
409 #endif
412 * XpRegisterInitFunc tells the print extension which screens
413 * are printers as opposed to displays, and what drivers are
414 * supported on each screen. This eliminates the need of
415 * allocating print-related private structures on windows on _all_ screens.
416 * It also hands the extension a pointer to the routine to be called
417 * whenever a context gets created for a particular driver on this screen.
419 void
420 XpRegisterInitFunc(ScreenPtr pScreen, char *driverName, int (*initContext)(struct _XpContext *))
422 XpDriverPtr pDriver;
424 if(XpScreens[pScreen->myNum] == 0)
426 if((XpScreens[pScreen->myNum] =
427 (XpScreenPtr) Xalloc(sizeof(XpScreenRec))) == 0)
428 return;
429 XpScreens[pScreen->myNum]->CloseScreen = 0;
430 XpScreens[pScreen->myNum]->drivers = 0;
433 if((pDriver = (XpDriverPtr)Xalloc(sizeof(XpDriverRec))) == 0)
434 return;
435 pDriver->next = XpScreens[pScreen->myNum]->drivers;
436 pDriver->name = driverName;
437 pDriver->CreateContext = initContext;
438 XpScreens[pScreen->myNum]->drivers = pDriver;
441 static int
442 ProcXpDispatch(ClientPtr client)
444 REQUEST(xReq);
446 switch(stuff->data)
448 case X_PrintQueryVersion:
449 return ProcXpQueryVersion(client);
450 case X_PrintGetPrinterList:
451 return ProcXpGetPrinterList(client);
452 case X_PrintCreateContext:
453 return ProcXpCreateContext(client);
454 case X_PrintSetContext:
455 return ProcXpSetContext(client);
456 case X_PrintGetContext:
457 return ProcXpGetContext(client);
458 case X_PrintDestroyContext:
459 return ProcXpDestroyContext(client);
460 case X_PrintGetContextScreen:
461 return ProcXpGetContextScreen(client);
462 case X_PrintStartJob:
463 return ProcXpStartJob(client);
464 case X_PrintEndJob:
465 return ProcXpEndJob(client);
466 case X_PrintStartDoc:
467 return ProcXpStartDoc(client);
468 case X_PrintEndDoc:
469 return ProcXpEndDoc(client);
470 case X_PrintStartPage:
471 return ProcXpStartPage(client);
472 case X_PrintEndPage:
473 return ProcXpEndPage(client);
474 case X_PrintSelectInput:
475 return ProcXpSelectInput(client);
476 case X_PrintInputSelected:
477 return ProcXpInputSelected(client);
478 case X_PrintPutDocumentData:
479 return ProcXpPutDocumentData(client);
480 case X_PrintGetDocumentData:
481 return ProcXpGetDocumentData(client);
482 case X_PrintSetAttributes:
483 return ProcXpSetAttributes(client);
484 case X_PrintGetAttributes:
485 return ProcXpGetAttributes(client);
486 case X_PrintGetOneAttribute:
487 return ProcXpGetOneAttribute(client);
488 case X_PrintRehashPrinterList:
489 return ProcXpRehashPrinterList(client);
490 case X_PrintQueryScreens:
491 return ProcXpQueryScreens(client);
492 case X_PrintGetPageDimensions:
493 return ProcXpGetPageDimensions(client);
494 case X_PrintSetImageResolution:
495 return ProcXpSetImageResolution(client);
496 case X_PrintGetImageResolution:
497 return ProcXpGetImageResolution(client);
498 default:
499 return BadRequest;
503 static int
504 ProcXpSwappedDispatch(ClientPtr client)
506 int temp;
507 REQUEST(xReq);
509 switch(stuff->data)
511 case X_PrintQueryVersion:
512 swaps(&stuff->length, temp);
513 return ProcXpQueryVersion(client);
514 case X_PrintGetPrinterList:
515 return SProcXpGetPrinterList(client);
516 case X_PrintCreateContext:
517 return SProcXpCreateContext(client);
518 case X_PrintSetContext:
519 return SProcXpSetContext(client);
520 case X_PrintGetContext:
521 return SProcXpGetContext(client);
522 case X_PrintDestroyContext:
523 return SProcXpDestroyContext(client);
524 case X_PrintGetContextScreen:
525 return SProcXpGetContextScreen(client);
526 case X_PrintStartJob:
527 return SProcXpStartJob(client);
528 case X_PrintEndJob:
529 return SProcXpEndJob(client);
530 case X_PrintStartDoc:
531 return SProcXpStartDoc(client);
532 case X_PrintEndDoc:
533 return SProcXpEndDoc(client);
534 case X_PrintStartPage:
535 return SProcXpStartPage(client);
536 case X_PrintEndPage:
537 return SProcXpEndPage(client);
538 case X_PrintSelectInput:
539 return SProcXpSelectInput(client);
540 case X_PrintInputSelected:
541 return SProcXpInputSelected(client);
542 case X_PrintPutDocumentData:
543 return SProcXpPutDocumentData(client);
544 case X_PrintGetDocumentData:
545 return SProcXpGetDocumentData(client);
546 case X_PrintSetAttributes:
547 return SProcXpSetAttributes(client);
548 case X_PrintGetAttributes:
549 return SProcXpGetAttributes(client);
550 case X_PrintGetOneAttribute:
551 return SProcXpGetOneAttribute(client);
552 case X_PrintRehashPrinterList:
553 return SProcXpRehashPrinterList(client);
554 case X_PrintQueryScreens:
555 swaps(&stuff->length, temp);
556 return ProcXpQueryScreens(client);
557 case X_PrintGetPageDimensions:
558 return SProcXpGetPageDimensions(client);
559 case X_PrintSetImageResolution:
560 return SProcXpSetImageResolution(client);
561 case X_PrintGetImageResolution:
562 return SProcXpGetImageResolution(client);
563 default:
564 return BadRequest;
568 static int
569 ProcXpQueryVersion(ClientPtr client)
571 /* REQUEST(xPrintQueryVersionReq); */
572 xPrintQueryVersionReply rep;
573 register int n;
574 long l;
576 REQUEST_SIZE_MATCH(xPrintQueryVersionReq);
577 rep.type = X_Reply;
578 rep.length = 0;
579 rep.sequenceNumber = client->sequence;
580 rep.majorVersion = XP_MAJOR_VERSION;
581 rep.minorVersion = XP_MINOR_VERSION;
582 if (client->swapped) {
583 swaps(&rep.sequenceNumber, n);
584 swapl(&rep.length, l);
585 swaps(&rep.majorVersion, n);
586 swaps(&rep.minorVersion, n);
588 WriteToClient(client, sz_xPrintQueryVersionReply, (char *)&rep);
589 return client->noClientException;
592 /*******************************************************************************
594 * GetPrinterList : Return a list of all printers associated with this
595 * server. Calls XpDiGetPrinterList, which is defined in
596 * the device-independent code in Xserver/Xprint.
598 ******************************************************************************/
600 static int
601 ProcXpGetPrinterList(ClientPtr client)
603 REQUEST(xPrintGetPrinterListReq);
604 int totalSize;
605 int numEntries;
606 XpDiListEntry **pList;
607 xPrintGetPrinterListReply *rep;
608 int n, i, totalBytes;
609 long l;
610 char *curByte;
612 REQUEST_AT_LEAST_SIZE(xPrintGetPrinterListReq);
614 totalSize = ((sz_xPrintGetPrinterListReq) >> 2) +
615 ((stuff->printerNameLen + 3) >> 2) +
616 ((stuff->localeLen + 3) >> 2);
617 if(totalSize != client->req_len)
618 return BadLength;
620 pList = XpDiGetPrinterList(stuff->printerNameLen, (char *)(stuff + 1),
621 stuff->localeLen, (char *)((stuff + 1) +
622 QUADPAD(stuff->printerNameLen)));
624 for(numEntries = 0, totalBytes = sz_xPrintGetPrinterListReply;
625 pList[numEntries] != (XpDiListEntry *)NULL;
626 numEntries++)
628 totalBytes += 2 * sizeof(CARD32);
629 totalBytes += QUADPAD(strlen(pList[numEntries]->name));
630 totalBytes += QUADPAD(strlen(pList[numEntries]->description));
633 if((rep = (xPrintGetPrinterListReply *)xalloc(totalBytes)) ==
634 (xPrintGetPrinterListReply *)NULL)
635 return BadAlloc;
637 rep->type = X_Reply;
638 rep->length = (totalBytes - sz_xPrintGetPrinterListReply) >> 2;
639 rep->sequenceNumber = client->sequence;
640 rep->listCount = numEntries;
641 if (client->swapped) {
642 swaps(&rep->sequenceNumber, n);
643 swapl(&rep->length, l);
644 swapl(&rep->listCount, l);
647 for(i = 0, curByte = (char *)(rep + 1); i < numEntries; i++)
649 CARD32 *pCrd;
650 int len;
652 pCrd = (CARD32 *)curByte;
653 len = strlen(pList[i]->name);
654 *pCrd = len;
655 if (client->swapped)
656 swapl((long *)curByte, l);
657 curByte += sizeof(CARD32);
658 strncpy(curByte, pList[i]->name, len);
659 curByte += QUADPAD(len);
661 pCrd = (CARD32 *)curByte;
662 len = strlen(pList[i]->description);
663 *pCrd = len;
664 if (client->swapped)
665 swapl((long *)curByte, l);
666 curByte += sizeof(CARD32);
667 strncpy(curByte, pList[i]->description, len);
668 curByte += QUADPAD(len);
671 XpDiFreePrinterList(pList);
673 WriteToClient(client, totalBytes, (char *)rep);
674 xfree(rep);
675 return client->noClientException;
678 /*******************************************************************************
680 * QueryScreens: Returns the list of screens which are associated with
681 * print drivers.
683 ******************************************************************************/
685 static int
686 ProcXpQueryScreens(ClientPtr client)
688 /* REQUEST(xPrintQueryScreensReq); */
689 int i, numPrintScreens, totalSize;
690 WINDOW *pWinId;
691 xPrintQueryScreensReply *rep;
692 long l;
694 REQUEST_SIZE_MATCH(xPrintQueryScreensReq);
696 rep = (xPrintQueryScreensReply *)xalloc(sz_xPrintQueryScreensReply);
697 pWinId = (WINDOW *)(rep + 1);
699 for(i = 0, numPrintScreens = 0, totalSize = sz_xPrintQueryScreensReply;
700 i < MAXSCREENS; i++)
703 * If a screen has registered with our extension, then it's
704 * a printer screen.
706 if(XpScreens[i] != (XpScreenPtr)NULL)
708 numPrintScreens++;
709 totalSize += sizeof(WINDOW);
710 rep = (xPrintQueryScreensReply *)xrealloc(rep, totalSize);
711 /* fix of bug: pWinId should be set again after reallocate rep */
712 pWinId = (WINDOW *)(rep + 1);
713 *pWinId = WindowTable[i]->drawable.id;
714 if (client->swapped)
715 swapl((long *)pWinId, l);
719 rep->type = X_Reply;
720 rep->sequenceNumber = client->sequence;
721 rep->length = (totalSize - sz_xPrintQueryScreensReply) >> 2;
722 rep->listCount = numPrintScreens;
723 if (client->swapped)
725 int n;
727 swaps(&rep->sequenceNumber, n);
728 swapl(&rep->length, l);
729 swapl(&rep->listCount, l);
732 WriteToClient(client, totalSize, (char *)rep);
733 xfree(rep);
734 return client->noClientException;
737 static int
738 ProcXpGetPageDimensions(ClientPtr client)
740 REQUEST(xPrintGetPageDimensionsReq);
741 CARD16 width, height;
742 xRectangle rect;
743 xPrintGetPageDimensionsReply rep;
744 XpContextPtr pContext;
745 int result;
747 REQUEST_SIZE_MATCH(xPrintGetPageDimensionsReq);
749 if((pContext =(XpContextPtr)SecurityLookupIDByType(client,
750 stuff->printContext,
751 RTcontext,
752 DixReadAccess))
753 == (XpContextPtr)NULL)
755 client->errorValue = stuff->printContext;
756 return XpErrorBase+XPBadContext;
759 if((pContext->funcs.GetMediumDimensions == 0) ||
760 (pContext->funcs.GetReproducibleArea == 0))
761 return BadImplementation;
763 result = pContext->funcs.GetMediumDimensions(pContext, &width, &height);
764 if(result != Success)
765 return result;
767 result = pContext->funcs.GetReproducibleArea(pContext, &rect);
768 if(result != Success)
769 return result;
771 rep.type = X_Reply;
772 rep.sequenceNumber = client->sequence;
773 rep.length = 0;
774 rep.width = width;
775 rep.height = height;
776 rep.rx = rect.x;
777 rep.ry = rect.y;
778 rep.rwidth = rect.width;
779 rep.rheight = rect.height;
781 if(client->swapped)
783 int n;
784 long l;
786 swaps(&rep.sequenceNumber, n);
787 swapl(&rep.length, l);
788 swaps(&rep.width, n);
789 swaps(&rep.height, n);
790 swaps(&rep.rx, n);
791 swaps(&rep.ry, n);
792 swaps(&rep.rwidth, n);
793 swaps(&rep.rheight, n);
796 WriteToClient(client, sz_xPrintGetPageDimensionsReply, (char *)&rep);
797 return client->noClientException;
800 static int
801 ProcXpSetImageResolution(ClientPtr client)
803 REQUEST(xPrintSetImageResolutionReq);
804 xPrintSetImageResolutionReply rep;
805 XpContextPtr pContext;
806 Bool status;
807 int result;
809 REQUEST_SIZE_MATCH(xPrintSetImageResolutionReq);
811 if((pContext =(XpContextPtr)SecurityLookupIDByType(client,
812 stuff->printContext,
813 RTcontext,
814 DixWriteAccess))
815 == (XpContextPtr)NULL)
817 client->errorValue = stuff->printContext;
818 return XpErrorBase+XPBadContext;
821 rep.prevRes = pContext->imageRes;
822 if(pContext->funcs.SetImageResolution != 0) {
823 result = pContext->funcs.SetImageResolution(pContext,
824 (int)stuff->imageRes,
825 &status);
826 if(result != Success)
827 status = FALSE;
828 } else
829 status = FALSE;
831 rep.type = X_Reply;
832 rep.sequenceNumber = client->sequence;
833 rep.length = 0;
834 rep.status = status;
836 if(client->swapped)
838 int n;
839 long l;
841 swaps(&rep.sequenceNumber, n);
842 swapl(&rep.length, l);
843 swaps(&rep.prevRes, n);
846 WriteToClient(client, sz_xPrintSetImageResolutionReply, (char *)&rep);
847 return client->noClientException;
850 static int
851 ProcXpGetImageResolution(ClientPtr client)
853 REQUEST(xPrintGetImageResolutionReq);
854 xPrintGetImageResolutionReply rep;
855 XpContextPtr pContext;
857 REQUEST_SIZE_MATCH(xPrintGetImageResolutionReq);
859 if((pContext =(XpContextPtr)SecurityLookupIDByType(client,
860 stuff->printContext,
861 RTcontext,
862 DixReadAccess))
863 == (XpContextPtr)NULL)
865 client->errorValue = stuff->printContext;
866 return XpErrorBase+XPBadContext;
869 rep.type = X_Reply;
870 rep.sequenceNumber = client->sequence;
871 rep.length = 0;
872 rep.imageRes = pContext->imageRes;
874 if(client->swapped)
876 int n;
877 long l;
879 swaps(&rep.sequenceNumber, n);
880 swapl(&rep.length, l);
881 swaps(&rep.imageRes, n);
884 WriteToClient(client, sz_xPrintGetImageResolutionReply, (char *)&rep);
885 return client->noClientException;
888 /*******************************************************************************
890 * RehashPrinterList : Cause the server's list of printers to be rebuilt.
891 * This allows new printers to be added, or old ones
892 * deleted without needing to restart the server.
894 ******************************************************************************/
896 static int
897 ProcXpRehashPrinterList(ClientPtr client)
899 /* REQUEST(xPrintRehashPrinterListReq); */
901 REQUEST_SIZE_MATCH(xPrintRehashPrinterListReq);
903 return XpRehashPrinterList();
906 /******************************************************************************
908 * Context functions: Init, Set, Destroy, FreeContext
909 * AllocateContextPrivateIndex, AllocateContextPrivate
910 * and supporting functions.
912 * Init creates a context, creates a XpClientRec for the calling
913 * client, and stores the contextPtr in the client's devPrivates.
915 * Set creates a XpClientRec for the calling client, and stores the
916 * contextPtr in the client's devPrivates unless the context is None.
917 * If the context is None, then the client's connection association
918 * with any context is removed.
920 * Destroy frees any and all XpClientRecs associated with the context,
921 * frees the context itself, and removes the contextPtr from any
922 * relevant client devPrivates.
924 * FreeContext is called by FreeResource to free up a context.
926 ******************************************************************************/
929 * CreateContext creates and initializes the memory for the context itself.
930 * The driver's CreateContext function
931 * is then called.
933 static int
934 ProcXpCreateContext(ClientPtr client)
936 REQUEST(xPrintCreateContextReq);
937 XpScreenPtr pPrintScreen;
938 WindowPtr pRoot;
939 char *driverName;
940 XpContextPtr pContext;
941 int result = Success;
942 XpDriverPtr pDriver;
944 REQUEST_AT_LEAST_SIZE(xPrintCreateContextReq);
946 LEGAL_NEW_RESOURCE(stuff->contextID, client);
949 * Check to see if the printer name is valid.
951 if((pRoot = XpDiValidatePrinter((char *)(stuff + 1), stuff->printerNameLen)) ==
952 (WindowPtr)NULL)
953 return BadMatch;
955 pPrintScreen = XpScreens[pRoot->drawable.pScreen->myNum];
958 * Allocate and add the context resource.
960 if((pContext = (XpContextPtr) xalloc(totalContextSize)) ==
961 (XpContextPtr) NULL)
962 return BadAlloc;
964 InitContextPrivates(pContext);
966 if(AddResource(stuff->contextID, RTcontext, (pointer) pContext)
967 != TRUE)
969 xfree(pContext);
970 return BadAlloc;
973 pContext->contextID = stuff->contextID;
974 pContext->clientHead = (XpClientPtr)NULL;
975 pContext->screenNum = pRoot->drawable.pScreen->myNum;
976 pContext->state = 0;
977 pContext->clientSlept = (ClientPtr)NULL;
978 pContext->imageRes = 0;
980 pContext->funcs.DestroyContext = 0;
981 pContext->funcs.StartJob = 0;
982 pContext->funcs.EndJob = 0;
983 pContext->funcs.StartDoc = 0;
984 pContext->funcs.EndDoc = 0;
985 pContext->funcs.StartPage = 0;
986 pContext->funcs.EndPage = 0;
987 pContext->funcs.PutDocumentData = 0;
988 pContext->funcs.GetDocumentData = 0;
989 pContext->funcs.GetAttributes = 0;
990 pContext->funcs.GetOneAttribute = 0;
991 pContext->funcs.SetAttributes = 0;
992 pContext->funcs.AugmentAttributes = 0;
993 pContext->funcs.GetMediumDimensions = 0;
994 pContext->funcs.GetReproducibleArea = 0;
995 pContext->funcs.SetImageResolution = 0;
997 if((pContext->printerName = (char *)xalloc(stuff->printerNameLen + 1)) ==
998 (char *)NULL)
1000 /* Freeing the context also causes the XpClients to be freed. */
1001 FreeResource(stuff->contextID, RT_NONE);
1002 return BadAlloc;
1004 strncpy(pContext->printerName, (char *)(stuff + 1), stuff->printerNameLen);
1005 pContext->printerName[stuff->printerNameLen] = (char)'\0';
1007 driverName = XpDiGetDriverName(pRoot->drawable.pScreen->myNum,
1008 pContext->printerName);
1010 for(pDriver = pPrintScreen->drivers;
1011 pDriver != (XpDriverPtr)NULL;
1012 pDriver = pDriver->next)
1014 if(!strcmp(driverName, pDriver->name))
1016 if(pDriver->CreateContext != 0)
1017 pDriver->CreateContext(pContext);
1018 else
1019 return BadImplementation;
1020 break;
1024 if (client->noClientException != Success)
1025 return client->noClientException;
1026 else
1027 return result;
1031 * SetContext creates the calling client's contextClient resource,
1032 * and stashes the contextID in the client's devPrivate.
1034 static int
1035 ProcXpSetContext(ClientPtr client)
1037 REQUEST(xPrintSetContextReq);
1039 XpContextPtr pContext;
1040 XpClientPtr pPrintClient;
1041 int result = Success;
1043 REQUEST_AT_LEAST_SIZE(xPrintSetContextReq);
1045 if((pContext = client->devPrivates[XpClientPrivateIndex].ptr) !=
1046 (pointer)NULL)
1049 * Erase this client's knowledge of its old context, if any.
1051 if((pPrintClient = FindClient(pContext, client)) != (XpClientPtr)NULL)
1053 XpUnsetFontResFunc(client);
1055 if(pPrintClient->eventMask == 0)
1056 FreeXpClient(pPrintClient, TRUE);
1059 client->devPrivates[XpClientPrivateIndex].ptr = (pointer)NULL;
1061 if(stuff->printContext == None)
1062 return Success;
1065 * Check to see that the supplied XID is really a valid print context
1066 * in this server.
1068 if((pContext =(XpContextPtr)SecurityLookupIDByType(client,
1069 stuff->printContext,
1070 RTcontext,
1071 DixWriteAccess))
1072 == (XpContextPtr)NULL)
1074 client->errorValue = stuff->printContext;
1075 return XpErrorBase+XPBadContext;
1078 if((pPrintClient = AcquireClient(pContext, client)) == (XpClientPtr)NULL)
1079 return BadAlloc;
1081 client->devPrivates[XpClientPrivateIndex].ptr = pContext;
1083 XpSetFontResFunc(client);
1085 if (client->noClientException != Success)
1086 return client->noClientException;
1087 else
1088 return result;
1091 XpContextPtr
1092 XpGetPrintContext(ClientPtr client)
1094 return (client->devPrivates[XpClientPrivateIndex].ptr);
1097 static int
1098 ProcXpGetContext(ClientPtr client)
1100 /* REQUEST(xPrintGetContextReq); */
1101 xPrintGetContextReply rep;
1103 XpContextPtr pContext;
1104 register int n;
1105 register long l;
1107 REQUEST_SIZE_MATCH(xPrintGetContextReq);
1109 if((pContext = client->devPrivates[XpClientPrivateIndex].ptr) ==
1110 (pointer)NULL)
1111 rep.printContext = None;
1112 else
1113 rep.printContext = pContext->contextID;
1114 rep.type = X_Reply;
1115 rep.length = 0;
1116 rep.sequenceNumber = client->sequence;
1117 if (client->swapped) {
1118 swaps(&rep.sequenceNumber, n);
1119 swapl(&rep.length, l);
1120 swapl(&rep.printContext, l);
1122 WriteToClient(client, sz_xPrintGetContextReply, (char *)&rep);
1123 return client->noClientException;
1128 * DestroyContext frees the context associated with the calling client.
1129 * It operates by freeing the context resource ID, thus causing XpFreeContext
1130 * to be called.
1132 static int
1133 ProcXpDestroyContext(ClientPtr client)
1135 REQUEST(xPrintDestroyContextReq);
1137 XpContextPtr pContext;
1139 REQUEST_SIZE_MATCH(xPrintDestroyContextReq);
1141 if((pContext =(XpContextPtr)SecurityLookupIDByType(client,
1142 stuff->printContext,
1143 RTcontext,
1144 DixDestroyAccess))
1145 == (XpContextPtr)NULL)
1147 client->errorValue = stuff->printContext;
1148 return XpErrorBase+XPBadContext;
1151 XpUnsetFontResFunc(client);
1153 FreeResource(pContext->contextID, RT_NONE);
1155 return Success;
1158 static int
1159 ProcXpGetContextScreen(ClientPtr client)
1161 REQUEST(xPrintGetContextScreenReq);
1162 xPrintGetContextScreenReply rep;
1163 XpContextPtr pContext;
1164 int n;
1165 long l;
1167 if((pContext =(XpContextPtr)SecurityLookupIDByType(client,
1168 stuff->printContext,
1169 RTcontext,
1170 DixReadAccess))
1171 == (XpContextPtr)NULL)
1172 return XpErrorBase+XPBadContext;
1174 rep.type = X_Reply;
1175 rep.sequenceNumber = client->sequence;
1176 rep.length = 0;
1177 rep.rootWindow = WindowTable[pContext->screenNum]->drawable.id;
1179 if (client->swapped) {
1180 swaps(&rep.sequenceNumber, n);
1181 swapl(&rep.length, l);
1182 swapl(&rep.rootWindow, l);
1185 WriteToClient(client, sz_xPrintGetContextScreenReply, (char *)&rep);
1186 return client->noClientException;
1190 * XpFreeContext is the routine called by dix:FreeResource when a context
1191 * resource ID is freed.
1192 * It checks to see if there's a partial job pending on the context, and
1193 * if so it calls the appropriate End procs with the cancel flag set.
1194 * It calls the driver's DestroyContext routine to allow the driver to clean
1195 * up any context-related memory or state.
1196 * It calls FreeXpClient to free all the
1197 * associated XpClientRecs and to set all the client->devPrivates to NULL.
1198 * It frees the printer name string, and frees the context
1199 * itself.
1201 static int
1202 XpFreeContext(pointer data, XID id)
1204 XpContextPtr pContext = (XpContextPtr)data;
1206 /* Clean up any pending job on this context */
1207 if(pContext->state != 0)
1209 if(pContext->state & PAGE_STARTED)
1211 WindowPtr pWin = (WindowPtr )LookupIDByType(
1212 pContext->pageWin, RT_WINDOW);
1213 XpPagePtr pPage = (XpPagePtr)LookupIDByType(
1214 pContext->pageWin, RTpage);
1216 pContext->funcs.EndPage(pContext, pWin);
1217 SendXpNotify(pContext, XPEndPageNotify, TRUE);
1218 pContext->state &= ~PAGE_STARTED;
1219 if(pPage)
1220 pPage->context = (XpContextPtr)NULL;
1222 if((pContext->state & DOC_RAW_STARTED) ||
1223 (pContext->state & DOC_COOKED_STARTED))
1225 pContext->funcs.EndDoc(pContext, TRUE);
1226 SendXpNotify(pContext, XPEndDocNotify, TRUE);
1227 pContext->state &= ~DOC_RAW_STARTED;
1228 pContext->state &= ~DOC_COOKED_STARTED;
1230 if(pContext->funcs.EndJob != 0)
1232 pContext->funcs.EndJob(pContext, TRUE);
1233 SendXpNotify(pContext, XPEndJobNotify, TRUE);
1234 pContext->state &= ~JOB_STARTED;
1235 pContext->state &= ~GET_DOC_DATA_STARTED;
1240 * Tell the driver we're destroying the context
1241 * This allows the driver to free and ContextPrivate data
1243 if(pContext->funcs.DestroyContext != 0)
1244 pContext->funcs.DestroyContext(pContext);
1246 /* Free up all the XpClientRecs */
1247 while(pContext->clientHead != (XpClientPtr)NULL)
1249 FreeXpClient(pContext->clientHead, TRUE);
1252 xfree(pContext->printerName);
1253 xfree(pContext);
1254 return Success; /* ??? */
1258 * XpFreeClient is the routine called by dix:FreeResource when a RTclient
1259 * is freed. It simply calls the FreeXpClient routine to do the work.
1261 static int
1262 XpFreeClient(pointer data, XID id)
1264 FreeXpClient((XpClientPtr)data, TRUE);
1265 return Success;
1269 * FreeXpClient
1270 * frees the ClientRec passed in, and sets the client->devPrivates to NULL
1271 * if the client->devPrivates points to the same context as the XpClient.
1272 * Called from XpFreeContext(from FreeResource), and
1273 * XpFreeClient. The boolean freeResource specifies whether or not to call
1274 * FreeResource for the XpClientRec's XID. We should free it except if we're
1275 * called from XpFreeClient (which is itself called from FreeResource for the
1276 * XpClientRec's XID).
1278 static void
1279 FreeXpClient(XpClientPtr pXpClient, Bool freeResource)
1281 XpClientPtr pCurrent, pPrev;
1282 XpContextPtr pContext = pXpClient->context;
1285 * If we're freeing the clientRec associated with the context tied
1286 * to the client's devPrivates, then we need to clear the devPrivates.
1288 if(pXpClient->client->devPrivates[XpClientPrivateIndex].ptr ==
1289 pXpClient->context)
1291 pXpClient->client->devPrivates[XpClientPrivateIndex].ptr =
1292 (pointer)NULL;
1295 for(pPrev = (XpClientPtr)NULL, pCurrent = pContext->clientHead;
1296 pCurrent != (XpClientPtr)NULL;
1297 pCurrent = pCurrent->pNext)
1299 if(pCurrent == pXpClient)
1301 if(freeResource == TRUE)
1302 FreeResource (pCurrent->contextClientID, RTclient);
1304 if (pPrev != (XpClientPtr)NULL)
1305 pPrev->pNext = pCurrent->pNext;
1306 else
1307 pContext->clientHead = pCurrent->pNext;
1309 xfree (pCurrent);
1310 break;
1312 pPrev = pCurrent;
1317 * CreateXpClient takes a ClientPtr and returns a pointer to a
1318 * XpClientRec which it allocates. It also initializes the Rec,
1319 * including adding a resource on behalf of the client to enable the
1320 * freeing of the Rec when the client's connection is closed.
1322 static XpClientPtr
1323 CreateXpClient(ClientPtr client)
1325 XpClientPtr pNewPrintClient;
1326 XID clientResource;
1328 if((pNewPrintClient = (XpClientPtr)xalloc(sizeof(XpClientRec))) ==
1329 (XpClientPtr)NULL)
1330 return (XpClientPtr)NULL;
1332 clientResource = FakeClientID(client->index);
1333 if(!AddResource(clientResource, RTclient, (pointer)pNewPrintClient))
1335 xfree (pNewPrintClient);
1336 return (XpClientPtr)NULL;
1339 pNewPrintClient->pNext = (XpClientPtr)NULL;
1340 pNewPrintClient->client = client;
1341 pNewPrintClient->context = (XpContextPtr)NULL;
1342 pNewPrintClient->eventMask = 0;
1343 pNewPrintClient->contextClientID = clientResource;
1345 return pNewPrintClient;
1349 * XpFreePage is the routine called by dix:FreeResource to free the page
1350 * resource built with the same ID as a page window. It checks to see
1351 * if we're in the middle of a page, and if so calls the driver's EndPage
1352 * function with 'cancel' set TRUE. It frees the memory associated with
1353 * the page resource.
1355 static int
1356 XpFreePage(pointer data, XID id)
1358 XpPagePtr page = (XpPagePtr)data;
1359 int result = Success;
1360 WindowPtr pWin = (WindowPtr )LookupIDByType(id, RT_WINDOW);
1362 /* Check to see if the window's being deleted in the middle of a page */
1363 if(page->context != (XpContextPtr)NULL &&
1364 page->context->state & PAGE_STARTED)
1366 if(page->context->funcs.EndPage != 0)
1367 result = page->context->funcs.EndPage(page->context, pWin);
1368 SendXpNotify(page->context, XPEndPageNotify, (int)TRUE);
1369 page->context->pageWin = 0; /* None, NULL??? XXX */
1372 xfree(page);
1373 return result;
1377 * ContextPrivate machinery.
1378 * Context privates are intended for use by the drivers, allowing the
1379 * drivers to maintain context-specific data. The driver should free
1380 * the associated data at DestroyContext time.
1383 static void
1384 InitContextPrivates(XpContextPtr context)
1386 register char *ptr;
1387 DevUnion *ppriv;
1388 register unsigned *sizes;
1389 register unsigned size;
1390 register int i;
1392 if (totalContextSize == sizeof(XpContextRec))
1393 ppriv = (DevUnion *)NULL;
1394 else
1395 ppriv = (DevUnion *)(context + 1);
1397 context->devPrivates = ppriv;
1398 sizes = contextPrivateSizes;
1399 ptr = (char *)(ppriv + contextPrivateLen);
1400 for (i = contextPrivateLen; --i >= 0; ppriv++, sizes++)
1402 if ( (size = *sizes) )
1404 ppriv->ptr = (pointer)ptr;
1405 ptr += size;
1407 else
1408 ppriv->ptr = (pointer)NULL;
1412 static void
1413 ResetContextPrivates(void)
1415 contextPrivateCount = 0;
1416 contextPrivateLen = 0;
1417 xfree(contextPrivateSizes);
1418 contextPrivateSizes = (unsigned *)NULL;
1419 totalContextSize = sizeof(XpContextRec);
1424 XpAllocateContextPrivateIndex(void)
1426 return contextPrivateCount++;
1429 Bool
1430 XpAllocateContextPrivate(int index, unsigned amount)
1432 unsigned oldamount;
1434 if (index >= contextPrivateLen)
1436 unsigned *nsizes;
1437 nsizes = (unsigned *)xrealloc(contextPrivateSizes,
1438 (index + 1) * sizeof(unsigned));
1439 if (!nsizes)
1440 return FALSE;
1441 while (contextPrivateLen <= index)
1443 nsizes[contextPrivateLen++] = 0;
1444 totalContextSize += sizeof(DevUnion);
1446 contextPrivateSizes = nsizes;
1448 oldamount = contextPrivateSizes[index];
1449 if (amount > oldamount)
1451 contextPrivateSizes[index] = amount;
1452 totalContextSize += (amount - oldamount);
1454 return TRUE;
1457 static XpClientPtr
1458 AcquireClient(XpContextPtr pContext, ClientPtr client)
1460 XpClientPtr pXpClient;
1462 if((pXpClient = FindClient(pContext, client)) != (XpClientPtr)NULL)
1463 return pXpClient;
1465 if((pXpClient = CreateXpClient(client)) == (XpClientPtr)NULL)
1466 return (XpClientPtr)NULL;
1468 pXpClient->context = pContext;
1469 pXpClient->pNext = pContext->clientHead;
1470 pContext->clientHead = pXpClient;
1472 return pXpClient;
1475 static XpClientPtr
1476 FindClient(XpContextPtr pContext, ClientPtr client)
1478 XpClientPtr pXpClient;
1480 for(pXpClient = pContext->clientHead; pXpClient != (XpClientPtr)NULL;
1481 pXpClient = pXpClient->pNext)
1483 if(pXpClient->client == client) return pXpClient;
1485 return (XpClientPtr)NULL;
1489 /******************************************************************************
1491 * Start/End Functions: StartJob, EndJob, StartDoc, EndDoc, StartPage, EndPage
1493 ******************************************************************************/
1495 static int
1496 ProcXpStartJob(ClientPtr client)
1498 REQUEST(xPrintStartJobReq);
1499 XpContextPtr pContext;
1500 int result = Success;
1502 REQUEST_SIZE_MATCH(xPrintStartJobReq);
1504 /* Check to see that a context has been established by this client. */
1505 if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr)
1506 == (XpContextPtr)NULL)
1507 return XpErrorBase+XPBadContext;
1509 if(pContext->state != 0)
1510 return XpErrorBase+XPBadSequence;
1512 if(stuff->saveData != XPSpool && stuff->saveData != XPGetData)
1514 client->errorValue = stuff->saveData;
1515 return BadValue;
1518 if(pContext->funcs.StartJob != 0)
1519 result = pContext->funcs.StartJob(pContext,
1520 (stuff->saveData == XPGetData)? TRUE:FALSE,
1521 client);
1522 else
1523 return BadImplementation;
1525 pContext->state = JOB_STARTED;
1526 if(stuff->saveData == XPGetData)
1527 pContext->state |= JOB_GET_DATA;
1529 SendXpNotify(pContext, XPStartJobNotify, FALSE);
1531 if (client->noClientException != Success)
1532 return client->noClientException;
1533 else
1534 return result;
1537 static int
1538 ProcXpEndJob(ClientPtr client)
1540 REQUEST(xPrintEndJobReq);
1541 int result = Success;
1542 XpContextPtr pContext;
1544 REQUEST_SIZE_MATCH(xPrintEndJobReq);
1546 if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr)
1547 == (XpContextPtr)NULL)
1548 return XpErrorBase+XPBadSequence;
1550 if(!(pContext->state & JOB_STARTED))
1551 return XpErrorBase+XPBadSequence;
1553 /* Check for missing EndDoc */
1554 if((pContext->state & DOC_RAW_STARTED) ||
1555 (pContext->state & DOC_COOKED_STARTED))
1557 if(pContext->state & PAGE_STARTED)
1559 WindowPtr pWin = (WindowPtr )LookupIDByType(
1560 pContext->pageWin, RT_WINDOW);
1561 XpPagePtr pPage = (XpPagePtr)LookupIDByType(
1562 pContext->pageWin, RTpage);
1564 if(stuff->cancel != TRUE)
1565 return XpErrorBase+XPBadSequence;
1567 if(pContext->funcs.EndPage != 0)
1568 result = pContext->funcs.EndPage(pContext, pWin);
1569 else
1570 return BadImplementation;
1572 SendXpNotify(pContext, XPEndPageNotify, TRUE);
1574 pContext->state &= ~PAGE_STARTED;
1576 if(pPage)
1577 pPage->context = (XpContextPtr)NULL;
1579 if(result != Success) return result;
1582 if(pContext->funcs.EndDoc != 0)
1583 result = pContext->funcs.EndDoc(pContext, stuff->cancel);
1584 else
1585 return BadImplementation;
1587 SendXpNotify(pContext, XPEndDocNotify, stuff->cancel);
1590 if(pContext->funcs.EndJob != 0)
1591 result = pContext->funcs.EndJob(pContext, stuff->cancel);
1592 else
1593 return BadImplementation;
1595 pContext->state = 0;
1597 SendXpNotify(pContext, XPEndJobNotify, stuff->cancel);
1599 if (client->noClientException != Success)
1600 return client->noClientException;
1601 else
1602 return result;
1605 static Bool
1606 DoStartDoc(ClientPtr client, XpStDocPtr c)
1608 XpContextPtr pContext = c->pContext;
1610 if(c->pContext->state & JOB_GET_DATA &&
1611 !(c->pContext->state & GET_DOC_DATA_STARTED))
1613 if(!c->slept)
1615 c->slept = TRUE;
1616 ClientSleep(client, (ClientSleepProcPtr)DoStartDoc, (pointer) c);
1617 c->pContext->clientSlept = client;
1619 return TRUE;
1622 if(pContext->funcs.StartDoc != 0)
1623 (void) pContext->funcs.StartDoc(pContext, c->type);
1624 else
1626 SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0,
1627 BadImplementation);
1628 return TRUE;
1631 if(c->type == XPDocNormal)
1632 pContext->state |= DOC_COOKED_STARTED;
1633 else
1634 pContext->state |= DOC_RAW_STARTED;
1636 SendXpNotify(pContext, XPStartDocNotify, (int)FALSE);
1638 xfree(c);
1639 return TRUE;
1642 static int
1643 ProcXpStartDoc(ClientPtr client)
1645 REQUEST(xPrintStartDocReq);
1646 int result = Success;
1647 XpContextPtr pContext;
1648 XpStDocPtr c;
1650 REQUEST_SIZE_MATCH(xPrintStartDocReq);
1652 if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr)
1653 == (XpContextPtr)NULL)
1654 return XpErrorBase+XPBadSequence;
1656 if(!(pContext->state & JOB_STARTED) ||
1657 pContext->state & DOC_RAW_STARTED ||
1658 pContext->state & DOC_COOKED_STARTED)
1659 return XpErrorBase+XPBadSequence;
1661 if(stuff->type != XPDocNormal && stuff->type != XPDocRaw)
1663 client->errorValue = stuff->type;
1664 return BadValue;
1667 c = (XpStDocPtr)xalloc(sizeof(XpStDocRec));
1668 c->pContext = pContext;
1669 c->type = stuff->type;
1670 c->slept = FALSE;
1671 (void)DoStartDoc(client, c);
1673 if (client->noClientException != Success)
1674 return client->noClientException;
1675 else
1676 return result;
1679 static int
1680 ProcXpEndDoc(ClientPtr client)
1682 REQUEST(xPrintEndDocReq);
1683 XpContextPtr pContext;
1684 int result = Success;
1686 REQUEST_SIZE_MATCH(xPrintEndDocReq);
1688 if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr)
1689 == (XpContextPtr)NULL)
1690 return XpErrorBase+XPBadSequence;
1692 if(!(pContext->state & DOC_RAW_STARTED) &&
1693 !(pContext->state & DOC_COOKED_STARTED))
1694 return XpErrorBase+XPBadSequence;
1696 if(pContext->state & PAGE_STARTED)
1698 if(stuff->cancel == TRUE)
1700 WindowPtr pWin = (WindowPtr )LookupIDByType(
1701 pContext->pageWin, RT_WINDOW);
1702 XpPagePtr pPage = (XpPagePtr)LookupIDByType(
1703 pContext->pageWin, RTpage);
1705 if(pContext->funcs.EndPage != 0)
1706 result = pContext->funcs.EndPage(pContext, pWin);
1707 else
1708 return BadImplementation;
1710 SendXpNotify(pContext, XPEndPageNotify, TRUE);
1712 if(pPage)
1713 pPage->context = (XpContextPtr)NULL;
1715 else
1716 return XpErrorBase+XPBadSequence;
1717 if(result != Success)
1718 return result;
1721 if(pContext->funcs.EndDoc != 0)
1722 result = pContext->funcs.EndDoc(pContext, stuff->cancel);
1723 else
1724 return BadImplementation;
1726 pContext->state &= ~DOC_RAW_STARTED;
1727 pContext->state &= ~DOC_COOKED_STARTED;
1729 SendXpNotify(pContext, XPEndDocNotify, stuff->cancel);
1731 if (client->noClientException != Success)
1732 return client->noClientException;
1733 else
1734 return result;
1737 static Bool
1738 DoStartPage(
1739 ClientPtr client,
1740 XpStPagePtr c)
1742 WindowPtr pWin = c->pWin;
1743 int result = Success;
1744 XpContextPtr pContext = c->pContext;
1745 XpPagePtr pPage;
1747 if(c->pContext->state & JOB_GET_DATA &&
1748 !(c->pContext->state & GET_DOC_DATA_STARTED))
1750 if(!c->slept)
1752 c->slept = TRUE;
1753 ClientSleep(client, (ClientSleepProcPtr)DoStartPage, (pointer) c);
1754 c->pContext->clientSlept = client;
1756 return TRUE;
1759 if(!(pContext->state & DOC_COOKED_STARTED))
1761 /* Implied StartDoc if it was omitted */
1762 if(pContext->funcs.StartDoc != 0)
1763 result = pContext->funcs.StartDoc(pContext, XPDocNormal);
1764 else
1766 SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0,
1767 BadImplementation);
1768 return TRUE;
1771 if(result != Success)
1773 SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0, result);
1774 return TRUE;
1777 pContext->state |= DOC_COOKED_STARTED;
1778 SendXpNotify(pContext, XPStartDocNotify, (int)FALSE);
1781 /* ensure the window's not already being used as a page */
1782 if((pPage = (XpPagePtr)LookupIDByType(c->pWin->drawable.id, RTpage)) !=
1783 (XpPagePtr)NULL)
1785 if(pPage->context != (XpContextPtr)NULL)
1787 SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0,
1788 BadWindow);
1789 return TRUE;
1792 else
1794 if((pPage = (XpPagePtr)xalloc(sizeof(XpPageRec))) == (XpPagePtr)NULL)
1796 SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0,
1797 BadAlloc);
1798 return TRUE;
1800 if(AddResource(c->pWin->drawable.id, RTpage, pPage) == FALSE)
1802 xfree(pPage);
1803 SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0,
1804 BadAlloc);
1805 return TRUE;
1809 pPage->context = pContext;
1810 pContext->pageWin = c->pWin->drawable.id;
1812 if(pContext->funcs.StartPage != 0)
1813 result = pContext->funcs.StartPage(pContext, pWin);
1814 else
1816 SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0,
1817 BadImplementation);
1818 return TRUE;
1821 pContext->state |= PAGE_STARTED;
1823 (void)MapWindow(pWin, client);
1825 SendXpNotify(pContext, XPStartPageNotify, (int)FALSE);
1827 return TRUE;
1830 static int
1831 ProcXpStartPage(ClientPtr client)
1833 REQUEST(xPrintStartPageReq);
1834 WindowPtr pWin;
1835 int result = Success;
1836 XpContextPtr pContext;
1837 XpStPagePtr c;
1839 REQUEST_SIZE_MATCH(xPrintStartPageReq);
1841 if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr)
1842 == (XpContextPtr)NULL)
1843 return XpErrorBase+XPBadSequence;
1845 if(!(pContext->state & JOB_STARTED))
1846 return XpErrorBase+XPBadSequence;
1848 /* can't have pages in a raw documented */
1849 if(pContext->state & DOC_RAW_STARTED)
1850 return XpErrorBase+XPBadSequence;
1852 if(pContext->state & PAGE_STARTED)
1853 return XpErrorBase+XPBadSequence;
1855 result = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess);
1856 if (result != Success)
1857 return result;
1858 if (pWin->drawable.pScreen->myNum != pContext->screenNum)
1859 return BadWindow;
1861 if((c = (XpStPagePtr)xalloc(sizeof(XpStPageRec))) == (XpStPagePtr)NULL)
1862 return BadAlloc;
1863 c->pContext = pContext;
1864 c->slept = FALSE;
1865 c->pWin = pWin;
1867 (void)DoStartPage(client, c);
1869 if (client->noClientException != Success)
1870 return client->noClientException;
1871 else
1872 return result;
1875 static int
1876 ProcXpEndPage(ClientPtr client)
1878 REQUEST(xPrintEndPageReq);
1879 int result = Success;
1880 XpContextPtr pContext;
1881 XpPagePtr page;
1882 WindowPtr pWin;
1884 REQUEST_SIZE_MATCH(xPrintEndPageReq);
1886 if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr)
1887 == (XpContextPtr)NULL)
1888 return XpErrorBase+XPBadSequence;
1890 if(!(pContext->state & PAGE_STARTED))
1891 return XpErrorBase+XPBadSequence;
1893 pWin = (WindowPtr )LookupIDByType(pContext->pageWin, RT_WINDOW);
1895 /* Call the ddx's EndPage proc. */
1896 if(pContext->funcs.EndPage != 0)
1897 result = pContext->funcs.EndPage(pContext, pWin);
1898 else
1899 return BadImplementation;
1901 if((page = (XpPagePtr)LookupIDByType(pContext->pageWin, RTpage)) !=
1902 (XpPagePtr)NULL)
1903 page->context = (XpContextPtr)NULL;
1905 pContext->state &= ~PAGE_STARTED;
1906 pContext->pageWin = 0; /* None, NULL??? XXX */
1908 (void)UnmapWindow(pWin, FALSE);
1910 SendXpNotify(pContext, XPEndPageNotify, stuff->cancel);
1912 if (client->noClientException != Success)
1913 return client->noClientException;
1914 else
1915 return result;
1918 /*******************************************************************************
1920 * Document Data Functions: PutDocumentData, GetDocumentData
1922 ******************************************************************************/
1924 static int
1925 ProcXpPutDocumentData(ClientPtr client)
1927 REQUEST(xPrintPutDocumentDataReq);
1928 XpContextPtr pContext;
1929 DrawablePtr pDraw;
1930 int result = Success;
1931 unsigned totalSize;
1932 char *pData, *pDoc_fmt, *pOptions;
1934 REQUEST_AT_LEAST_SIZE(xPrintPutDocumentDataReq);
1936 if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr)
1937 == (XpContextPtr)NULL)
1938 return XpErrorBase+XPBadSequence;
1940 if(!(pContext->state & DOC_RAW_STARTED) &&
1941 !(pContext->state & DOC_COOKED_STARTED))
1942 return XpErrorBase+XPBadSequence;
1944 if (stuff->drawable) {
1945 if (pContext->state & DOC_RAW_STARTED)
1946 return BadDrawable;
1947 result = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
1948 DixUnknownAccess);
1949 if (result != Success)
1950 return result;
1951 if (pDraw->pScreen->myNum != pContext->screenNum)
1952 return BadDrawable;
1953 } else {
1954 if (pContext->state & DOC_COOKED_STARTED)
1955 return BadDrawable;
1956 pDraw = NULL;
1959 pData = (char *)(&stuff[1]);
1961 totalSize = (stuff->len_data + 3) >> 2;
1962 pDoc_fmt = pData + (totalSize << 2);
1964 totalSize += (stuff->len_fmt + 3) >> 2;
1965 pOptions = pData + (totalSize << 2);
1967 totalSize += (stuff->len_options + 3) >> 2;
1968 if((totalSize + (sz_xPrintPutDocumentDataReq >> 2)) != client->req_len)
1969 return BadLength;
1971 if(pContext->funcs.PutDocumentData != 0)
1973 result = (*pContext->funcs.PutDocumentData)(pContext, pDraw,
1974 pData, stuff->len_data,
1975 pDoc_fmt, stuff->len_fmt,
1976 pOptions, stuff->len_options,
1977 client);
1979 else
1980 return BadImplementation;
1982 if (client->noClientException != Success)
1983 return client->noClientException;
1984 else
1985 return result;
1988 static int
1989 ProcXpGetDocumentData(ClientPtr client)
1991 REQUEST(xPrintGetDocumentDataReq);
1992 xPrintGetDocumentDataReply rep;
1993 XpContextPtr pContext;
1994 int result = Success;
1996 REQUEST_SIZE_MATCH(xPrintGetDocumentDataReq);
1998 if((pContext = (XpContextPtr)SecurityLookupIDByType(client,
1999 stuff->printContext,
2000 RTcontext,
2001 DixWriteAccess))
2002 == (XpContextPtr)NULL)
2004 client->errorValue = stuff->printContext;
2005 return XpErrorBase+XPBadContext;
2008 if(pContext->funcs.GetDocumentData == 0)
2009 return BadImplementation;
2011 if(!(pContext->state & JOB_GET_DATA) ||
2012 pContext->state & GET_DOC_DATA_STARTED)
2013 return XpErrorBase+XPBadSequence;
2015 if(stuff->maxBufferSize <= 0)
2017 client->errorValue = stuff->maxBufferSize;
2018 return BadValue; /* gotta have a positive buffer size */
2021 result = (*pContext->funcs.GetDocumentData)(pContext, client,
2022 stuff->maxBufferSize);
2023 if(result != Success)
2025 rep.type = X_Reply;
2026 rep.sequenceNumber = client->sequence;
2027 rep.length = 0;
2028 rep.dataLen = 0;
2029 rep.statusCode = 1;
2030 rep.finishedFlag = TRUE;
2031 if (client->swapped) {
2032 int n;
2033 long l;
2035 swaps(&rep.sequenceNumber, n);
2036 swapl(&rep.statusCode, l); /* XXX Why are these longs??? */
2037 swapl(&rep.finishedFlag, l); /* XXX Why are these longs??? */
2039 (void)WriteToClient(client,sz_xPrintGetDocumentDataReply,(char *)&rep);
2041 else
2042 pContext->state |= GET_DOC_DATA_STARTED;
2044 if(pContext->clientSlept != (ClientPtr)NULL)
2046 ClientSignal(pContext->clientSlept);
2047 ClientWakeup(pContext->clientSlept);
2048 pContext->clientSlept = (ClientPtr)NULL;
2051 return result;
2054 /*******************************************************************************
2056 * Attribute requests: GetAttributes, SetAttributes, GetOneAttribute
2058 ******************************************************************************/
2060 static int
2061 ProcXpGetAttributes(ClientPtr client)
2063 REQUEST(xPrintGetAttributesReq);
2064 XpContextPtr pContext;
2065 char *attrs;
2066 xPrintGetAttributesReply *pRep;
2067 int totalSize, n;
2068 unsigned long l;
2070 REQUEST_SIZE_MATCH(xPrintGetAttributesReq);
2072 if(stuff->type < XPJobAttr || stuff->type > XPServerAttr)
2074 client->errorValue = stuff->type;
2075 return BadValue;
2078 if(stuff->type != XPServerAttr)
2080 if((pContext = (XpContextPtr)SecurityLookupIDByType(
2081 client,
2082 stuff->printContext,
2083 RTcontext,
2084 DixReadAccess))
2085 == (XpContextPtr)NULL)
2087 client->errorValue = stuff->printContext;
2088 return XpErrorBase+XPBadContext;
2091 if(pContext->funcs.GetAttributes == 0)
2092 return BadImplementation;
2093 if((attrs = (*pContext->funcs.GetAttributes)(pContext, stuff->type)) ==
2094 (char *)NULL)
2095 return BadAlloc;
2097 else
2099 if((attrs = XpGetAttributes((XpContextPtr)NULL, XPServerAttr)) ==
2100 (char *)NULL)
2101 return BadAlloc;
2104 totalSize = sz_xPrintGetAttributesReply + QUADPAD(strlen(attrs));
2105 if((pRep = (xPrintGetAttributesReply *)malloc(totalSize)) ==
2106 (xPrintGetAttributesReply *)NULL)
2107 return BadAlloc;
2109 pRep->type = X_Reply;
2110 pRep->length = (totalSize - sz_xPrintGetAttributesReply) >> 2;
2111 pRep->sequenceNumber = client->sequence;
2112 pRep->stringLen = strlen(attrs);
2114 if (client->swapped) {
2115 swaps(&pRep->sequenceNumber, n);
2116 swapl(&pRep->length, l);
2117 swapl(&pRep->stringLen, l);
2120 strncpy((char*)(pRep + 1), attrs, strlen(attrs));
2121 xfree(attrs);
2123 WriteToClient(client, totalSize, (char *)pRep);
2125 xfree(pRep);
2127 return client->noClientException;
2130 static int
2131 ProcXpSetAttributes(ClientPtr client)
2133 REQUEST(xPrintSetAttributesReq);
2134 int result = Success;
2135 XpContextPtr pContext;
2136 char *attr;
2138 REQUEST_AT_LEAST_SIZE(xPrintSetAttributesReq);
2140 if(stuff->type < XPJobAttr || stuff->type > XPServerAttr)
2142 client->errorValue = stuff->type;
2143 return BadValue;
2147 * Disallow changing of read-only attribute pools
2149 if(stuff->type == XPPrinterAttr || stuff->type == XPServerAttr)
2150 return BadMatch;
2152 if((pContext = (XpContextPtr)SecurityLookupIDByType(
2153 client,
2154 stuff->printContext,
2155 RTcontext,
2156 DixWriteAccess))
2157 == (XpContextPtr)NULL)
2159 client->errorValue = stuff->printContext;
2160 return XpErrorBase+XPBadContext;
2163 if(pContext->funcs.SetAttributes == 0)
2164 return BadImplementation;
2167 * Check for attributes being set after their relevant phase
2168 * has already begun (e.g. Job attributes set after StartJob).
2170 if((pContext->state & JOB_STARTED) && stuff->type == XPJobAttr)
2171 return XpErrorBase+XPBadSequence;
2172 if(((pContext->state & DOC_RAW_STARTED) ||
2173 (pContext->state & DOC_COOKED_STARTED)) && stuff->type == XPDocAttr)
2174 return XpErrorBase+XPBadSequence;
2175 if((pContext->state & PAGE_STARTED) && stuff->type == XPPageAttr)
2176 return XpErrorBase+XPBadSequence;
2178 if((attr = (char *)malloc(stuff->stringLen + 1)) == (char *)NULL)
2179 return BadAlloc;
2181 strncpy(attr, (char *)(stuff + 1), stuff->stringLen);
2182 attr[stuff->stringLen] = (char)'\0';
2184 if(stuff->rule == XPAttrReplace)
2185 (*pContext->funcs.SetAttributes)(pContext, stuff->type, attr);
2186 else if(stuff->rule == XPAttrMerge)
2187 (*pContext->funcs.AugmentAttributes)(pContext, stuff->type, attr);
2188 else
2190 client->errorValue = stuff->rule;
2191 result = BadValue;
2194 xfree(attr);
2196 SendAttributeNotify(pContext, stuff->type);
2198 return result;
2201 static int
2202 ProcXpGetOneAttribute(ClientPtr client)
2204 REQUEST(xPrintGetOneAttributeReq);
2205 XpContextPtr pContext;
2206 char *value, *attrName;
2207 xPrintGetOneAttributeReply *pRep;
2208 int totalSize;
2209 int n;
2210 unsigned long l;
2212 REQUEST_AT_LEAST_SIZE(xPrintGetOneAttributeReq);
2214 totalSize = ((sz_xPrintGetOneAttributeReq) >> 2) +
2215 ((stuff->nameLen + 3) >> 2);
2216 if(totalSize != client->req_len)
2217 return BadLength;
2219 if(stuff->type < XPJobAttr || stuff->type > XPServerAttr)
2221 client->errorValue = stuff->type;
2222 return BadValue;
2225 if((attrName = (char *)malloc(stuff->nameLen + 1)) == (char *)NULL)
2226 return BadAlloc;
2227 strncpy(attrName, (char *)(stuff+1), stuff->nameLen);
2228 attrName[stuff->nameLen] = (char)'\0';
2230 if(stuff->type != XPServerAttr)
2232 if((pContext = (XpContextPtr)SecurityLookupIDByType(
2233 client,
2234 stuff->printContext,
2235 RTcontext,
2236 DixReadAccess))
2237 == (XpContextPtr)NULL)
2239 client->errorValue = stuff->printContext;
2240 return XpErrorBase+XPBadContext;
2243 if(pContext->funcs.GetOneAttribute == 0)
2244 return BadImplementation;
2245 if((value = (*pContext->funcs.GetOneAttribute)(pContext, stuff->type,
2246 attrName)) == (char *)NULL)
2247 return BadAlloc;
2249 else
2251 if((value = XpGetOneAttribute((XpContextPtr)NULL, XPServerAttr,
2252 attrName)) == (char *)NULL)
2253 return BadAlloc;
2256 free(attrName);
2258 totalSize = sz_xPrintGetOneAttributeReply + QUADPAD(strlen(value));
2259 if((pRep = (xPrintGetOneAttributeReply *)malloc(totalSize)) ==
2260 (xPrintGetOneAttributeReply *)NULL)
2261 return BadAlloc;
2263 pRep->type = X_Reply;
2264 pRep->length = (totalSize - sz_xPrintGetOneAttributeReply) >> 2;
2265 pRep->sequenceNumber = client->sequence;
2266 pRep->valueLen = strlen(value);
2268 if (client->swapped) {
2269 swaps(&pRep->sequenceNumber, n);
2270 swapl(&pRep->length, l);
2271 swapl(&pRep->valueLen, l);
2274 strncpy((char*)(pRep + 1), value, strlen(value));
2276 WriteToClient(client, totalSize, (char *)pRep);
2278 xfree(pRep);
2280 return client->noClientException;
2283 /*******************************************************************************
2285 * Print Event requests: SelectInput InputSelected, SendXpNotify
2287 ******************************************************************************/
2290 static int
2291 ProcXpSelectInput(ClientPtr client)
2293 REQUEST(xPrintSelectInputReq);
2294 int result = Success;
2295 XpContextPtr pContext;
2296 XpClientPtr pPrintClient;
2298 REQUEST_SIZE_MATCH(xPrintSelectInputReq);
2301 * Check to see that the supplied XID is really a valid print context
2302 * in this server.
2304 if((pContext=(XpContextPtr)SecurityLookupIDByType(client,
2305 stuff->printContext,
2306 RTcontext,
2307 DixWriteAccess))
2308 == (XpContextPtr)NULL)
2310 client->errorValue = stuff->printContext;
2311 return XpErrorBase+XPBadContext;
2314 if(stuff->eventMask & ~allEvents)
2316 client->errorValue = stuff->eventMask;
2317 return BadValue; /* bogus event mask bits */
2320 if((pPrintClient = AcquireClient(pContext, client)) == (XpClientPtr)NULL)
2321 return BadAlloc;
2323 pPrintClient->eventMask = stuff->eventMask;
2325 return result;
2328 static int
2329 ProcXpInputSelected(ClientPtr client)
2331 REQUEST(xPrintInputSelectedReq);
2332 xPrintInputSelectedReply rep;
2333 register int n;
2334 long l;
2335 XpClientPtr pXpClient;
2336 XpContextPtr pContext;
2338 REQUEST_SIZE_MATCH(xPrintInputSelectedReq);
2340 if((pContext=(XpContextPtr)SecurityLookupIDByType(client,
2341 stuff->printContext,
2342 RTcontext,
2343 DixReadAccess))
2344 == (XpContextPtr)NULL)
2346 client->errorValue = stuff->printContext;
2347 return XpErrorBase+XPBadContext;
2350 pXpClient = FindClient(pContext, client);
2352 rep.type = X_Reply;
2353 rep.length = 0;
2354 rep.sequenceNumber = client->sequence;
2355 rep.eventMask = (pXpClient != (XpClientPtr)NULL)? pXpClient->eventMask : 0;
2356 rep.allEventsMask = GetAllEventMasks(pContext);
2358 if (client->swapped) {
2359 swaps(&rep.sequenceNumber, n);
2360 swapl(&rep.length, l);
2361 swapl(&rep.eventMask, l);
2362 swapl(&rep.allEventsMask, l);
2365 WriteToClient(client, sz_xPrintInputSelectedReply, (char *)&rep);
2366 return client->noClientException;
2369 static void
2370 SendAttributeNotify(XpContextPtr pContext, int which)
2372 XpClientPtr pXpClient;
2373 xPrintAttributeEvent ae;
2374 ClientPtr client;
2376 pXpClient = pContext->clientHead;
2377 if(pXpClient == (XpClientPtr)NULL)
2378 return; /* Nobody's interested in the events (or this context). */
2380 for (pXpClient = pContext->clientHead;
2381 pXpClient != (XpClientPtr)NULL;
2382 pXpClient = pXpClient->pNext)
2384 client = pXpClient->client;
2385 if (client == serverClient || client->clientGone ||
2386 !(pXpClient->eventMask & XPAttributeMask))
2387 continue;
2388 ae.type = XPAttributeNotify + XpEventBase;
2389 ae.detail = which;
2390 ae.printContext = pContext->contextID;
2391 ae.sequenceNumber = client->sequence;
2392 WriteEventsToClient (client, 1, (xEvent *) &ae);
2396 static void
2397 SendXpNotify(XpContextPtr pContext, int which, int val)
2399 XpClientPtr pXpClient;
2400 xPrintPrintEvent pe;
2401 ClientPtr client;
2403 pXpClient = pContext->clientHead;
2404 if(pXpClient == (XpClientPtr)NULL)
2405 return; /* Nobody's interested in the events (or this context). */
2407 for (pXpClient = pContext->clientHead;
2408 pXpClient != (XpClientPtr)NULL;
2409 pXpClient = pXpClient->pNext)
2411 client = pXpClient->client;
2412 if (client == serverClient || client->clientGone ||
2413 !(pXpClient->eventMask & XPPrintMask))
2414 continue;
2415 pe.type = XPPrintNotify + XpEventBase;
2416 pe.detail = which;
2417 pe.printContext = pContext->contextID;
2418 pe.cancel = (Bool)val;
2419 pe.sequenceNumber = client->sequence;
2420 WriteEventsToClient (client, 1, (xEvent *) &pe);
2424 static CARD32
2425 GetAllEventMasks(XpContextPtr pContext)
2427 XpClientPtr pPrintClient;
2428 CARD32 totalMask = (CARD32)0;
2430 for (pPrintClient = pContext->clientHead;
2431 pPrintClient != (XpClientPtr)NULL;
2432 pPrintClient = pPrintClient->pNext)
2434 totalMask |= pPrintClient->eventMask;
2436 return totalMask;
2440 * XpContextOfClient - returns the XpContextPtr to the context
2441 * associated with the specified client, or NULL if the client
2442 * does not currently have a context set.
2444 XpContextPtr
2445 XpContextOfClient(ClientPtr client)
2447 return (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr;
2451 /*******************************************************************************
2453 * Swap-request functions
2455 ******************************************************************************/
2457 static int
2458 SProcXpCreateContext(ClientPtr client)
2460 int i;
2461 long n;
2463 REQUEST(xPrintCreateContextReq);
2465 swaps(&stuff->length, i);
2466 swapl(&stuff->contextID, n);
2467 swapl(&stuff->printerNameLen, n);
2468 swapl(&stuff->localeLen, n);
2469 return ProcXpCreateContext(client);
2472 static int
2473 SProcXpGetPrinterList(ClientPtr client)
2475 int i;
2476 long n;
2478 REQUEST(xPrintGetPrinterListReq);
2480 swaps(&stuff->length, i);
2481 swapl(&stuff->printerNameLen, n);
2482 swapl(&stuff->localeLen, n);
2483 return ProcXpGetPrinterList(client);
2486 static int
2487 SProcXpRehashPrinterList(ClientPtr client)
2489 int i;
2491 REQUEST(xPrintRehashPrinterListReq);
2492 swaps(&stuff->length, i);
2493 return ProcXpRehashPrinterList(client);
2496 static int
2497 SProcXpSetContext(ClientPtr client)
2499 int i;
2501 REQUEST(xPrintSetContextReq);
2502 swaps(&stuff->length, i);
2503 swapl(&stuff->printContext, i);
2504 return ProcXpSetContext(client);
2507 static int
2508 SProcXpGetContext(ClientPtr client)
2510 int i;
2512 REQUEST(xPrintGetContextReq);
2513 swaps(&stuff->length, i);
2514 return ProcXpGetContext(client);
2517 static int
2518 SProcXpDestroyContext(ClientPtr client)
2520 int i;
2521 long n;
2523 REQUEST(xPrintDestroyContextReq);
2524 swaps(&stuff->length, i);
2525 swapl(&stuff->printContext, n);
2526 return ProcXpDestroyContext(client);
2529 static int
2530 SProcXpGetContextScreen(ClientPtr client)
2532 int i;
2533 long n;
2535 REQUEST(xPrintGetContextScreenReq);
2536 swaps(&stuff->length, i);
2537 swapl(&stuff->printContext, n);
2538 return ProcXpGetContextScreen(client);
2541 static int
2542 SProcXpInputSelected(ClientPtr client)
2544 int i;
2545 long n;
2547 REQUEST(xPrintInputSelectedReq);
2548 swaps(&stuff->length, i);
2549 swapl(&stuff->printContext, n);
2550 return ProcXpInputSelected(client);
2553 static int
2554 SProcXpStartJob(ClientPtr client)
2556 int i;
2558 REQUEST(xPrintStartJobReq);
2559 swaps(&stuff->length, i);
2560 return ProcXpStartJob(client);
2563 static int
2564 SProcXpEndJob(ClientPtr client)
2566 int i;
2568 REQUEST(xPrintEndJobReq);
2569 swaps(&stuff->length, i);
2570 return ProcXpEndJob(client);
2573 static int
2574 SProcXpStartDoc(ClientPtr client)
2576 int i;
2578 REQUEST(xPrintStartDocReq);
2579 swaps(&stuff->length, i);
2580 return ProcXpStartDoc(client);
2583 static int
2584 SProcXpEndDoc(ClientPtr client)
2586 int i;
2588 REQUEST(xPrintEndDocReq);
2589 swaps(&stuff->length, i);
2590 return ProcXpEndDoc(client);
2593 static int
2594 SProcXpStartPage(ClientPtr client)
2596 int i;
2597 long n;
2599 REQUEST(xPrintStartPageReq);
2600 swaps(&stuff->length, i);
2601 swapl(&stuff->window, n);
2602 return ProcXpStartPage(client);
2605 static int
2606 SProcXpEndPage(ClientPtr client)
2608 int i;
2610 REQUEST(xPrintEndPageReq);
2611 swaps(&stuff->length, i);
2612 return ProcXpEndPage(client);
2615 static int
2616 SProcXpPutDocumentData(ClientPtr client)
2618 long n;
2619 int i;
2621 REQUEST(xPrintPutDocumentDataReq);
2622 swaps(&stuff->length, i);
2623 swapl(&stuff->drawable, n);
2624 swapl(&stuff->len_data, n);
2625 swaps(&stuff->len_fmt, i);
2626 swaps(&stuff->len_options, i);
2627 return ProcXpPutDocumentData(client);
2630 static int
2631 SProcXpGetDocumentData(ClientPtr client)
2633 long n;
2634 int i;
2636 REQUEST(xPrintGetDocumentDataReq);
2637 swaps(&stuff->length, i);
2638 swapl(&stuff->printContext, n);
2639 swapl(&stuff->maxBufferSize, n);
2640 return ProcXpGetDocumentData(client);
2643 static int
2644 SProcXpGetAttributes(ClientPtr client)
2646 long n;
2647 int i;
2649 REQUEST(xPrintGetAttributesReq);
2650 swaps(&stuff->length, i);
2651 swapl(&stuff->printContext, n);
2652 return ProcXpGetAttributes(client);
2655 static int
2656 SProcXpSetAttributes(ClientPtr client)
2658 long n;
2659 int i;
2661 REQUEST(xPrintSetAttributesReq);
2662 swaps(&stuff->length, i);
2663 swapl(&stuff->printContext, n);
2664 swapl(&stuff->stringLen, n);
2665 return ProcXpSetAttributes(client);
2668 static int
2669 SProcXpGetOneAttribute(ClientPtr client)
2671 long n;
2672 int i;
2674 REQUEST(xPrintGetOneAttributeReq);
2675 swaps(&stuff->length, i);
2676 swapl(&stuff->printContext, n);
2677 swapl(&stuff->nameLen, n);
2678 return ProcXpGetOneAttribute(client);
2681 static int
2682 SProcXpSelectInput(ClientPtr client)
2684 long n;
2685 int i;
2687 REQUEST(xPrintSelectInputReq);
2688 swaps(&stuff->length, i);
2689 swapl(&stuff->eventMask, n);
2690 swapl(&stuff->printContext, n);
2691 return ProcXpSelectInput(client);
2694 static int
2695 SProcXpGetPageDimensions(ClientPtr client)
2697 long n;
2698 int i;
2700 REQUEST(xPrintGetPageDimensionsReq);
2701 swaps(&stuff->length, i);
2702 swapl(&stuff->printContext, n);
2703 return ProcXpGetPageDimensions(client);
2706 static int
2707 SProcXpSetImageResolution(ClientPtr client)
2709 long n;
2710 int i;
2712 REQUEST(xPrintSetImageResolutionReq);
2713 swaps(&stuff->length, i);
2714 swapl(&stuff->printContext, n);
2715 swaps(&stuff->imageRes, i);
2716 return ProcXpSetImageResolution(client);
2719 static int
2720 SProcXpGetImageResolution(ClientPtr client)
2722 long n;
2723 int i;
2725 REQUEST(xPrintGetImageResolutionReq);
2726 swaps(&stuff->length, i);
2727 swapl(&stuff->printContext, n);
2728 return ProcXpGetImageResolution(client);
2731 static void
2732 SwapXpNotifyEvent(xPrintPrintEvent *src, xPrintPrintEvent *dst)
2735 * Swap the sequence number and context fields.
2737 cpswaps(src->sequenceNumber, dst->sequenceNumber);
2738 cpswapl(src->printContext, dst->printContext);
2741 * Copy the byte-long fields.
2743 dst->type = src->type;
2744 dst->detail = src->detail;
2745 dst->cancel = src->cancel;
2748 static void
2749 SwapXpAttributeEvent(xPrintAttributeEvent *src, xPrintAttributeEvent *dst)
2752 * Swap the sequence number and context fields.
2754 cpswaps(src->sequenceNumber, dst->sequenceNumber);
2755 cpswapl(src->printContext, dst->printContext);
2758 * Copy the byte-long fields.
2760 dst->type = src->type;
2761 dst->detail = src->detail;