1 /* $XConsortium: xprint.c /main/3 1996/11/23 17:11:55 rws $ */
2 /*
3 (c) Copyright 1996 Hewlett-Packard Company
4 (c) Copyright 1996 International Business Machines Corp.
5 (c) Copyright 1996 Sun Microsystems, Inc.
6 (c) Copyright 1996 Novell, Inc.
7 (c) Copyright 1996 Digital Equipment Corp.
8 (c) Copyright 1996 Fujitsu Limited
9 (c) Copyright 1996 Hitachi, Ltd.
10 
11 Permission is hereby granted, free of charge, to any person obtaining a copy
12 of this software and associated documentation files (the "Software"), to deal
13 in the Software without restriction, including without limitation the rights
14 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 copies of the Software, and to permit persons to whom the Software is
16 furnished to do so, subject to the following conditions:
17 
18 The above copyright notice and this permission notice shall be included in
19 all copies or substantial portions of the Software.
20 
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
24 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
25 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 
28 Except as contained in this notice, the names of the copyright holders shall
29 not be used in advertising or otherwise to promote the sale, use or other
30 dealings in this Software without prior written authorization from said
31 copyright holders.
32 */
33 /*******************************************************************
34 **
35 **    *********************************************************
36 **    *
37 **    *  File:          xprint.c
38 **    *
39 **    *  Copyright:     Copyright 1993, 1995 Hewlett-Packard Company
40 **    *
41 **    *		Copyright 1989 by The Massachusetts Institute of Technology
42 **    *
43 **    *		Permission to use, copy, modify, and distribute this
44 **    *		software and its documentation for any purpose and without
45 **    *		fee is hereby granted, provided that the above copyright
46 **    *		notice appear in all copies and that both that copyright
47 **    *		notice and this permission notice appear in supporting
48 **    *		documentation, and that the name of MIT not be used in
49 **    *		advertising or publicity pertaining to distribution of the
50 **    *		software without specific prior written permission.
51 **    *		M.I.T. makes no representation about the suitability of
52 **    *		this software for any purpose. It is provided "as is"
53 **    *		without any express or implied warranty.
54 **    *
55 **    *		MIT DISCLAIMS ALL WARRANTIES WITH REGARD TO  THIS  SOFTWARE,
56 **    *		INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
57 **    *		NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MIT BE  LI-
58 **    *		ABLE  FOR  ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
59 **    *		ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,  DATA  OR
60 **    *		PROFITS,  WHETHER  IN  AN  ACTION OF CONTRACT, NEGLIGENCE OR
61 **    *		OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
62 **    *		THE USE OR PERFORMANCE OF THIS SOFTWARE.
63 **    *
64 **    *********************************************************
65 **
66 ********************************************************************/
67 /* $XFree86: xc/programs/Xserver/Xext/xprint.c,v 1.4 1997/01/02 04:05:05 dawes Exp $ */
68 
69 #include "X.h"
70 #define NEED_EVENTS
71 #include "Xproto.h"
72 #undef NEED_EVENTS
73 #include "misc.h"
74 #include "windowstr.h"
75 #include "scrnintstr.h"
76 #include "pixmapstr.h"
77 #include "extnsionst.h"
78 #include "dixstruct.h"
79 #include "Xatom.h"
80 #define _XP_PRINT_SERVER_
81 #include "Print.h"
82 #include "Printstr.h"
83 #undef _XP_PRINT_SERVER_
84 #include "../Xprint/DiPrint.h"
85 
86 extern WindowPtr *WindowTable; /* declared in dix:globals.c */
87 
88 extern WindowPtr XpDiValidatePrinter();
89 extern char *XpDiGetDriverName();
90 extern char *XpGetAttributes();
91 extern char *XpGetOneAttribute();
92 extern int XpRehashPrinterList();
93 extern void XpSetFontResFunc();
94 
95 static void XpResetProc();
96 
97 static int ProcXpDispatch();
98 static int ProcXpSwappedDispatch();
99 
100 static int ProcXpQueryVersion();
101 static int ProcXpGetPrinterList();
102 static int ProcXpCreateContext();
103 static int ProcXpSetContext();
104 static int ProcXpGetContext();
105 static int ProcXpDestroyContext();
106 static int ProcXpGetContextScreen();
107 static int ProcXpStartJob();
108 static int ProcXpEndJob();
109 static int ProcXpStartDoc();
110 static int ProcXpEndDoc();
111 static int ProcXpStartPage();
112 static int ProcXpEndPage();
113 static int ProcXpSelectInput();
114 static int ProcXpInputSelected();
115 static int ProcXpPutDocumentData();
116 static int ProcXpGetDocumentData();
117 static int ProcXpGetAttributes();
118 static int ProcXpGetOneAttribute();
119 static int ProcXpSetAttributes();
120 static int ProcXpRehashPrinterList();
121 static int ProcXpQueryScreens();
122 static int ProcXpGetPageDimensions();
123 static int ProcXpSetImageResolution();
124 static int ProcXpGetImageResolution();
125 
126 static void SwapXpNotifyEvent();
127 static void SwapXpAttributeEvent();
128 
129 static int SProcXpGetPrinterList();
130 static int SProcXpCreateContext();
131 static int SProcXpSetContext();
132 static int SProcXpGetContext();
133 static int SProcXpDestroyContext();
134 static int SProcXpGetContextScreen();
135 static int SProcXpStartJob();
136 static int SProcXpEndJob();
137 static int SProcXpStartDoc();
138 static int SProcXpEndDoc();
139 static int SProcXpStartPage();
140 static int SProcXpEndPage();
141 static int SProcXpSelectInput();
142 static int SProcXpInputSelected();
143 static int SProcXpPutDocumentData();
144 static int SProcXpGetDocumentData();
145 static int SProcXpGetAttributes();
146 static int SProcXpGetOneAttribute();
147 static int SProcXpSetAttributes();
148 static int SProcXpRehashPrinterList();
149 static int SProcXpGetPageDimensions();
150 static int SProcXpSetImageResolution();
151 static int SProcXpGetImageResolution();
152 
153 static void SendXpNotify();
154 static void SendAttributeNotify();
155 static int XpFreeClient();
156 static int XpFreeContext();
157 static int XpFreePage();
158 static int XpFreeEvents();
159 static Bool XpCloseScreen();
160 static CARD32 GetAllEventMasks();
161 static struct _XpEvent *AddEventRec();
162 static void DeleteEventRec();
163 static struct _XpEvent *FindEventRec();
164 static struct _XpClient *CreateXpClient();
165 static void FreeXpClient();
166 static void InitContextPrivates();
167 static void ResetContextPrivates();
168 static struct _XpClient *FindClient();
169 static struct _XpClient *AcquireClient();
170 
171 typedef struct _driver {
172     struct _driver *next;
173     char *name;
174     int (* CreateContext)();
175 } XpDriverRec, *XpDriverPtr;
176 
177 typedef struct  _xpScreen {
178     Bool (* CloseScreen)();
179     struct _driver *drivers;
180 } XpScreenRec, *XpScreenPtr;
181 
182 /*
183  * Each context has a list of XpClients indicating which clients have
184  * associated this context with their connection.
185  * Each such client has a RTclient resource allocated for it,
186  * and this per-client
187  * resource is used to delete the XpClientRec if/when the client closes
188  * its connection.
189  * The list of XpClients is also walked if/when the context is destroyed
190  * so that the ContextPtr can be removed from the client's devPrivates.
191  */
192 typedef struct _XpClient {
193 	struct _XpClient *pNext;
194 	ClientPtr	client;
195 	XpContextPtr	context;
196 	CARD32		eventMask;
197 	XID		contextClientID; /* unneeded sanity check? */
198 } XpClientRec, *XpClientPtr;
199 
200 /*
201  * Each StartPage request specifies a window which forms the top level
202  * window of the page.  One of the following structs is created as a
203  * RTpage resource with the same ID as the window itself.  This enables
204  * us to clean up when/if the window is destroyed, and to prevent the
205  * same window from being simultaneously referenced in multiple contexts.
206  * The page resource is created at the first StartPage on a given window,
207  * and is only destroyed when/if the window is destroyed.  When the
208  * EndPage is recieved (or an EndDoc or EndJob) the context field is
209  * set to NULL, but the resource remains alive.
210  */
211 typedef struct _XpPage {
212 	XpContextPtr	context;
213 } XpPageRec, *XpPagePtr;
214 
215 typedef struct _XpStPageRec {
216     XpContextPtr pContext;
217     Bool slept;
218     XpPagePtr pPage;
219     WindowPtr pWin;
220 } XpStPageRec, *XpStPagePtr;
221 
222 typedef struct _XpStDocRec {
223     XpContextPtr pContext;
224     Bool slept;
225     CARD8 type;
226 } XpStDocRec, *XpStDocPtr;
227 
228 #define QUADPAD(x) ((((x)+3)>>2)<<2)
229 
230 /*
231  * Possible bit-mask values in the "state" field of a XpContextRec.
232  */
233 #define JOB_STARTED (1 << 0)
234 #define DOC_RAW_STARTED (1 << 1)
235 #define DOC_COOKED_STARTED (1 << 2)
236 #define PAGE_STARTED (1 << 3)
237 #define GET_DOC_DATA_STARTED (1 << 4)
238 #define JOB_GET_DATA (1 << 5)
239 
240 static XpScreenPtr XpScreens[MAXSCREENS];
241 static unsigned char XpReqCode;
242 static int XpEventBase;
243 static int XpErrorBase;
244 static int XpGeneration = 0;
245 static int XpWindowPrivateIndex;
246 static int XpClientPrivateIndex;
247 
248 /* Variables for the context private machinery.
249  * These must be initialized at compile time because
250  * main() calls InitOutput before InitExtensions, and the
251  * output drivers are likely to call AllocateContextPrivate.
252  * These variables are reset at CloseScreen time.  CloseScreen
253  * is used because it occurs after FreeAllResources, and before
254  * the next InitOutput cycle.
255  */
256 static int  contextPrivateCount = 0;
257 static int contextPrivateLen = 0;
258 static unsigned *contextPrivateSizes = (unsigned *)NULL;
259 static unsigned totalContextSize = sizeof(XpContextRec);
260 
261 /*
262  * There are three types of resources involved.  One is the resource associated
263  * with the context itself, with an ID specified by a printing client.  The
264  * next is a resource created by us on the client's behalf (and unknown to
265  * the client) when a client inits or sets a context which allows us to
266  * track each client's interest in events
267  * on a particular context, and also allows us to clean up this interest
268  * record when/if the client's connection is closed.  Finally, there is
269  * a resource created for each window that's specified in a StartPage.  This
270  * resource carries the same ID as the window itself, and enables us to
271  * easily prevent the same window being referenced in multiple contexts
272  * simultaneously, and enables us to clean up if the window is destroyed
273  * before the EndPage.
274  */
275 static RESTYPE RTclient, RTcontext, RTpage;
276 
277 /*
278  * allEvents is the OR of all the legal event mask bits.
279  */
280 static CARD32 allEvents = XPPrintMask | XPAttributeMask;
281 
282 
283 /*******************************************************************************
284  *
285  * ExtensionInit, Driver Init functions, QueryVersion, and Dispatch procs
286  *
287  ******************************************************************************/
288 
289 /*
290  * XpExtensionInit
291  *
292  * Called from InitExtensions in main() usually through miinitextension
293  *
294  */
295 
296 void
XpExtensionInit()297 XpExtensionInit()
298 {
299     ExtensionEntry *extEntry, *AddExtension();
300     int i;
301 
302     RTclient = CreateNewResourceType(XpFreeClient);
303     RTcontext = CreateNewResourceType(XpFreeContext);
304     RTpage = CreateNewResourceType(XpFreePage);
305     if (RTclient && RTcontext && RTpage &&
306         (extEntry = AddExtension(XP_PRINTNAME, XP_EVENTS, XP_ERRORS,
307                                ProcXpDispatch, ProcXpSwappedDispatch,
308                                XpResetProc, StandardMinorOpcode)))
309     {
310         XpReqCode = (unsigned char)extEntry->base;
311         XpEventBase = extEntry->eventBase;
312         XpErrorBase = extEntry->errorBase;
313         EventSwapVector[XpEventBase] = SwapXpNotifyEvent;
314         EventSwapVector[XpEventBase+1] = SwapXpAttributeEvent;
315     }
316 
317     if(XpGeneration != serverGeneration)
318     {
319 	XpClientPrivateIndex = AllocateClientPrivateIndex();
320 	/*
321 	 * We allocate 0 length & simply stuff a pointer to the
322 	 * ContextRec in the DevUnion.
323 	 */
324 	if(AllocateClientPrivate(XpClientPrivateIndex, 0) != TRUE)
325 	{
326 		/* we can't alloc a client private, should we bail??? XXX */
327 	}
328 	XpGeneration = serverGeneration;
329     }
330 
331     for(i = 0; i < MAXSCREENS; i++)
332     {
333 	/*
334 	 * If a screen has registered with our extension, then we
335 	 * wrap the screen's CloseScreen function to allow us to
336 	 * reset our ContextPrivate stuff.  Note that this
337 	 * requires a printing DDX to call XpRegisterInitFunc
338 	 * _before_ this extension is initialized - i.e. at screen init
339 	 * time, _not_ at root window creation time.
340 	 */
341 	if(XpScreens[i] != (XpScreenPtr)NULL)
342 	{
343 	    XpScreens[i]->CloseScreen = screenInfo.screens[i]->CloseScreen;
344 	    screenInfo.screens[i]->CloseScreen = XpCloseScreen;
345 	}
346     }
347     DeclareExtensionSecurity(XP_PRINTNAME, TRUE);
348 }
349 
350 static void
XpResetProc(extEntry)351 XpResetProc(extEntry)
352     ExtensionEntry extEntry;
353 {
354     int i;
355 
356     /*
357      * We can't free up the XpScreens recs here, because extensions are
358      * closed before screens, and our CloseScreen function uses the XpScreens
359      * recs.
360     for(i = 0; i < MAXSCREENS; i++)
361     {
362 	if(XpScreens[i] != (XpScreenPtr)NULL)
363 	    Xfree(XpScreens[i]);
364 	XpScreens[i] = (XpScreenPtr)NULL;
365     }
366     */
367 }
368 
369 static Bool
XpCloseScreen(index,pScreen)370 XpCloseScreen(index, pScreen)
371     int index;
372     ScreenPtr pScreen;
373 {
374     Bool (* CloseScreen)();
375 
376     CloseScreen = XpScreens[index]->CloseScreen;
377     if(XpScreens[index] != (XpScreenPtr)NULL)
378     {
379 	XpDriverPtr pDriv, nextDriv;
380 
381 	pDriv = XpScreens[index]->drivers;
382 	while(pDriv != (XpDriverPtr)NULL)
383 	{
384 	    nextDriv = pDriv->next;
385             Xfree(pDriv);
386 	    pDriv = nextDriv;
387 	}
388 	Xfree(XpScreens[index]);
389     }
390     XpScreens[index] = (XpScreenPtr)NULL;
391 
392     /*
393      * It's wasteful to call ResetContextPrivates() at every CloseScreen,
394      * but it's the best we know how to do for now.  We do this because we
395      * have to wait until after all resources have been freed (so we know
396      * how to free the ContextRecs), and before the next InitOutput cycle.
397      * See dix/main.c for the order of initialization and reset.
398      */
399     ResetContextPrivates();
400     return (*CloseScreen)(index, pScreen);
401 }
402 
403 static void
FreeScreenEntry(pScreenEntry)404 FreeScreenEntry(pScreenEntry)
405     XpScreenPtr pScreenEntry;
406 {
407     XpDriverPtr pDriver;
408 
409     pDriver = pScreenEntry->drivers;
410     while(pDriver != (XpDriverPtr)NULL)
411     {
412 	XpDriverPtr tmp;
413 
414 	tmp = pDriver->next;
415 	xfree(pDriver);
416 	pDriver = tmp;
417     }
418     xfree(pScreenEntry);
419 }
420 
421 /*
422  * XpRegisterInitFunc tells the print extension which screens
423  * are printers as opposed to displays, and what drivers are
424  * supported on each screen.  This eliminates the need of
425  * allocating print-related private structures on windows on _all_ screens.
426  * It also hands the extension a pointer to the routine to be called
427  * whenever a context gets created for a particular driver on this screen.
428  */
429 void
XpRegisterInitFunc(pScreen,driverName,initContext)430 XpRegisterInitFunc(pScreen, driverName, initContext)
431     ScreenPtr pScreen;
432     char *driverName;
433     int (*initContext)();
434 {
435     XpDriverPtr pDriver;
436 
437     if(XpScreens[pScreen->myNum] == (XpScreenPtr)NULL)
438     {
439         if((XpScreens[pScreen->myNum] =
440            (XpScreenPtr) Xalloc(sizeof(XpScreenRec))) == (XpScreenPtr)NULL)
441             return;
442 	XpScreens[pScreen->myNum]->CloseScreen = (Bool(*)())NULL;
443 	XpScreens[pScreen->myNum]->drivers = (XpDriverPtr)NULL;
444     }
445 
446     if((pDriver = (XpDriverPtr)Xalloc(sizeof(XpDriverRec))) ==
447        (XpDriverPtr)NULL)
448 	return;
449     pDriver->next = XpScreens[pScreen->myNum]->drivers;
450     pDriver->name = driverName;
451     pDriver->CreateContext = initContext;
452     XpScreens[pScreen->myNum]->drivers = pDriver;
453 }
454 
455 static int
ProcXpDispatch(client)456 ProcXpDispatch(client)
457     ClientPtr client;
458 {
459     REQUEST(xReq);
460 
461     switch(stuff->data)
462     {
463 	case X_PrintQueryVersion:
464             return ProcXpQueryVersion(client);
465 	case X_PrintGetPrinterList:
466 	    return ProcXpGetPrinterList(client);
467 	case X_PrintCreateContext:
468 	    return ProcXpCreateContext(client);
469 	case X_PrintSetContext:
470 	    return ProcXpSetContext(client);
471 	case X_PrintGetContext:
472 	    return ProcXpGetContext(client);
473 	case X_PrintDestroyContext:
474 	    return ProcXpDestroyContext(client);
475 	case X_PrintGetContextScreen:
476 	    return ProcXpGetContextScreen(client);
477 	case X_PrintStartJob:
478             return ProcXpStartJob(client);
479 	case X_PrintEndJob:
480             return ProcXpEndJob(client);
481 	case X_PrintStartDoc:
482             return ProcXpStartDoc(client);
483 	case X_PrintEndDoc:
484             return ProcXpEndDoc(client);
485 	case X_PrintStartPage:
486             return ProcXpStartPage(client);
487 	case X_PrintEndPage:
488             return ProcXpEndPage(client);
489 	case X_PrintSelectInput:
490             return ProcXpSelectInput(client);
491 	case X_PrintInputSelected:
492             return ProcXpInputSelected(client);
493 	case X_PrintPutDocumentData:
494             return ProcXpPutDocumentData(client);
495 	case X_PrintGetDocumentData:
496             return ProcXpGetDocumentData(client);
497 	case X_PrintSetAttributes:
498 	    return ProcXpSetAttributes(client);
499 	case X_PrintGetAttributes:
500 	    return ProcXpGetAttributes(client);
501 	case X_PrintGetOneAttribute:
502 	    return ProcXpGetOneAttribute(client);
503 	case X_PrintRehashPrinterList:
504 	    return ProcXpRehashPrinterList(client);
505 	case X_PrintQueryScreens:
506             return ProcXpQueryScreens(client);
507 	case X_PrintGetPageDimensions:
508             return ProcXpGetPageDimensions(client);
509 	case X_PrintSetImageResolution:
510             return ProcXpSetImageResolution(client);
511 	case X_PrintGetImageResolution:
512             return ProcXpGetImageResolution(client);
513 	default:
514 	    return BadRequest;
515     }
516 }
517 
518 static int
ProcXpSwappedDispatch(client)519 ProcXpSwappedDispatch(client)
520     ClientPtr client;
521 {
522     int temp;
523     REQUEST(xReq);
524 
525     switch(stuff->data)
526     {
527 	case X_PrintQueryVersion:
528 	    swaps(&stuff->length, temp);
529             return ProcXpQueryVersion(client);
530 	case X_PrintGetPrinterList:
531 	    return SProcXpGetPrinterList(client);
532 	case X_PrintCreateContext:
533 	    return SProcXpCreateContext(client);
534 	case X_PrintSetContext:
535 	    return SProcXpSetContext(client);
536 	case X_PrintGetContext:
537 	    return SProcXpGetContext(client);
538 	case X_PrintDestroyContext:
539 	    return SProcXpDestroyContext(client);
540 	case X_PrintGetContextScreen:
541 	    return SProcXpGetContextScreen(client);
542 	case X_PrintStartJob:
543             return SProcXpStartJob(client);
544 	case X_PrintEndJob:
545             return SProcXpEndJob(client);
546 	case X_PrintStartDoc:
547             return SProcXpStartDoc(client);
548 	case X_PrintEndDoc:
549             return SProcXpEndDoc(client);
550 	case X_PrintStartPage:
551             return SProcXpStartPage(client);
552 	case X_PrintEndPage:
553             return SProcXpEndPage(client);
554 	case X_PrintSelectInput:
555 	    return SProcXpSelectInput(client);
556 	case X_PrintInputSelected:
557 	    return SProcXpInputSelected(client);
558 	case X_PrintPutDocumentData:
559             return SProcXpPutDocumentData(client);
560 	case X_PrintGetDocumentData:
561             return SProcXpGetDocumentData(client);
562 	case X_PrintSetAttributes:
563 	    return SProcXpSetAttributes(client);
564 	case X_PrintGetAttributes:
565 	    return SProcXpGetAttributes(client);
566 	case X_PrintGetOneAttribute:
567 	    return SProcXpGetOneAttribute(client);
568 	case X_PrintRehashPrinterList:
569 	    return SProcXpRehashPrinterList(client);
570 	case X_PrintQueryScreens:
571 	    swaps(&stuff->length, temp);
572             return ProcXpQueryScreens(client);
573 	case X_PrintGetPageDimensions:
574             return SProcXpGetPageDimensions(client);
575 	case X_PrintSetImageResolution:
576             return SProcXpSetImageResolution(client);
577 	case X_PrintGetImageResolution:
578             return SProcXpGetImageResolution(client);
579 	default:
580 	    return BadRequest;
581     }
582 }
583 
584 static int
ProcXpQueryVersion(client)585 ProcXpQueryVersion(client)
586     ClientPtr client;
587 {
588     REQUEST(xPrintQueryVersionReq);
589     xPrintQueryVersionReply rep;
590     register int n;
591     long l;
592 
593     REQUEST_SIZE_MATCH(xPrintQueryVersionReq);
594     rep.type = X_Reply;
595     rep.length = 0;
596     rep.sequenceNumber = client->sequence;
597     rep.majorVersion = XP_MAJOR_VERSION;
598     rep.minorVersion = XP_MINOR_VERSION;
599     if (client->swapped) {
600         swaps(&rep.sequenceNumber, n);
601         swapl(&rep.length, l);
602         swaps(&rep.majorVersion, n);
603         swaps(&rep.minorVersion, n);
604     }
605     WriteToClient(client, sz_xPrintQueryVersionReply, (char *)&rep);
606     return client->noClientException;
607 }
608 
609 /*******************************************************************************
610  *
611  * GetPrinterList : Return a list of all printers associated with this
612  *                  server.  Calls XpDiGetPrinterList, which is defined in
613  *		    the device-independent code in Xserver/Xprint.
614  *
615  ******************************************************************************/
616 
617 static int
ProcXpGetPrinterList(client)618 ProcXpGetPrinterList(client)
619     ClientPtr client;
620 {
621     REQUEST(xPrintGetPrinterListReq);
622     int totalSize, numEntries;
623     XpDiListEntry **pList, *pEntry;
624     xPrintGetPrinterListReply *rep;
625     int n, i, totalBytes;
626     long l;
627     char *curByte;
628 
629     REQUEST_AT_LEAST_SIZE(xPrintGetPrinterListReq);
630 
631     totalSize = ((sz_xPrintGetPrinterListReq) >> 2) +
632                 ((stuff->printerNameLen + 3) >> 2) +
633                 ((stuff->localeLen + 3) >> 2);
634     if(totalSize != client->req_len)
635 	 return BadLength;
636 
637     pList = XpDiGetPrinterList(stuff->printerNameLen, (char *)(stuff + 1),
638 			       stuff->localeLen, (char *)((stuff + 1) +
639 			       QUADPAD(stuff->printerNameLen)));
640 
641     for(numEntries = 0, totalBytes = sz_xPrintGetPrinterListReply;
642 	pList[numEntries] != (XpDiListEntry *)NULL;
643 	numEntries++)
644     {
645 	totalBytes += 2 * sizeof(CARD32);
646 	totalBytes += QUADPAD(strlen(pList[numEntries]->name));
647 	totalBytes += QUADPAD(strlen(pList[numEntries]->description));
648     }
649 
650     if((rep = (xPrintGetPrinterListReply *)xalloc(totalBytes)) ==
651        (xPrintGetPrinterListReply *)NULL)
652 	return BadAlloc;
653 
654     rep->type = X_Reply;
655     rep->length = (totalBytes - sz_xPrintGetPrinterListReply) >> 2;
656     rep->sequenceNumber = client->sequence;
657     rep->listCount = numEntries;
658     if (client->swapped) {
659         swaps(&rep->sequenceNumber, n);
660         swapl(&rep->length, l);
661         swapl(&rep->listCount, l);
662     }
663 
664     for(i = 0, curByte = (char *)(rep + 1); i < numEntries; i++)
665     {
666 	CARD32 *pCrd;
667 	int len;
668 
669 	pCrd = (CARD32 *)curByte;
670 	len = strlen(pList[i]->name);
671 	*pCrd = len;
672         if (client->swapped)
673             swapl((long *)curByte, l);
674 	curByte += sizeof(CARD32);
675 	strncpy(curByte, pList[i]->name, len);
676 	curByte += QUADPAD(len);
677 
678 	pCrd = (CARD32 *)curByte;
679 	len = strlen(pList[i]->description);
680 	*pCrd = len;
681         if (client->swapped)
682             swapl((long *)curByte, l);
683 	curByte += sizeof(CARD32);
684 	strncpy(curByte, pList[i]->description, len);
685 	curByte += QUADPAD(len);
686     }
687 
688     XpDiFreePrinterList(pList);
689 
690     WriteToClient(client, totalBytes, (char *)rep);
691     xfree(rep);
692     return client->noClientException;
693 }
694 
695 /*******************************************************************************
696  *
697  * QueryScreens: Returns the list of screens which are associated with
698  *               print drivers.
699  *
700  ******************************************************************************/
701 
702 static int
ProcXpQueryScreens(client)703 ProcXpQueryScreens(client)
704     ClientPtr client;
705 {
706     REQUEST(xPrintQueryScreensReq);
707     int i, numPrintScreens, totalSize;
708     WINDOW *pWinId;
709     xPrintQueryScreensReply *rep;
710     long l;
711 
712     REQUEST_SIZE_MATCH(xPrintQueryScreensReq);
713 
714     rep = (xPrintQueryScreensReply *)xalloc(sz_xPrintQueryScreensReply);
715     pWinId = (WINDOW *)(rep + 1);
716 
717     for(i = 0, numPrintScreens = 0, totalSize = sz_xPrintQueryScreensReply;
718 	i < MAXSCREENS; i++)
719     {
720 	/*
721 	 * If a screen has registered with our extension, then it's
722 	 * a printer screen.
723 	 */
724 	if(XpScreens[i] != (XpScreenPtr)NULL)
725 	{
726 	    numPrintScreens++;
727 	    totalSize += sizeof(WINDOW);
728 	    rep = (xPrintQueryScreensReply *)xrealloc(rep, totalSize);
729 	    *pWinId = WindowTable[i]->drawable.id;
730             if (client->swapped)
731                 swapl((long *)pWinId, l);
732 	    pWinId++;
733 	}
734     }
735 
736     rep->type = X_Reply;
737     rep->sequenceNumber = client->sequence;
738     rep->length = (totalSize - sz_xPrintQueryScreensReply) >> 2;
739     rep->listCount = numPrintScreens;
740     if (client->swapped)
741     {
742 	int n;
743 
744         swaps(&rep->sequenceNumber, n);
745         swapl(&rep->length, l);
746         swapl(&rep->listCount, l);
747     }
748 
749     WriteToClient(client, totalSize, (char *)rep);
750     xfree(rep);
751     return client->noClientException;
752 }
753 
754 static int
ProcXpGetPageDimensions(client)755 ProcXpGetPageDimensions(client)
756     ClientPtr client;
757 {
758     REQUEST(xPrintGetPageDimensionsReq);
759     CARD16 width, height;
760     xRectangle rect;
761     xPrintGetPageDimensionsReply rep;
762     XpContextPtr pContext;
763     int result;
764 
765     REQUEST_SIZE_MATCH(xPrintGetPageDimensionsReq);
766 
767     if((pContext =(XpContextPtr)SecurityLookupIDByType(client,
768 						       stuff->printContext,
769 						       RTcontext,
770 						       SecurityReadAccess))
771        == (XpContextPtr)NULL)
772     {
773 	client->errorValue = stuff->printContext;
774         return XpErrorBase+XPBadContext;
775     }
776 
777     if(pContext->funcs.GetMediumDimensions != (int (*)())NULL)
778         result = pContext->funcs.GetMediumDimensions(pContext, &width, &height);
779     else
780         return BadImplementation;
781 
782     if(pContext->funcs.GetReproducibleArea != (int (*)())NULL)
783         result = pContext->funcs.GetReproducibleArea(pContext, &rect);
784     else
785         return BadImplementation;
786 
787     rep.type = X_Reply;
788     rep.sequenceNumber = client->sequence;
789     rep.length = 0;
790     rep.width = width;
791     rep.height = height;
792     rep.rx = rect.x;
793     rep.ry = rect.y;
794     rep.rwidth = rect.width;
795     rep.rheight = rect.height;
796 
797     if(client->swapped)
798     {
799 	int n;
800 	long l;
801 
802         swaps(&rep.sequenceNumber, n);
803         swapl(&rep.length, l);
804         swaps(&rep.width, n);
805         swaps(&rep.height, n);
806         swaps(&rep.rx, n);
807         swaps(&rep.ry, n);
808         swaps(&rep.rwidth, n);
809         swaps(&rep.rheight, n);
810     }
811 
812     WriteToClient(client, sz_xPrintGetPageDimensionsReply, (char *)&rep);
813     return client->noClientException;
814 }
815 
816 static int
ProcXpSetImageResolution(client)817 ProcXpSetImageResolution(client)
818     ClientPtr client;
819 {
820     REQUEST(xPrintSetImageResolutionReq);
821     xPrintSetImageResolutionReply rep;
822     XpContextPtr pContext;
823     Bool status;
824     int result;
825 
826     REQUEST_SIZE_MATCH(xPrintSetImageResolutionReq);
827 
828     if((pContext =(XpContextPtr)SecurityLookupIDByType(client,
829 						       stuff->printContext,
830 						       RTcontext,
831 						       SecurityWriteAccess))
832        == (XpContextPtr)NULL)
833     {
834 	client->errorValue = stuff->printContext;
835         return XpErrorBase+XPBadContext;
836     }
837 
838     rep.prevRes = pContext->imageRes;
839     if(pContext->funcs.SetImageResolution != (int (*)())NULL)
840         result = pContext->funcs.SetImageResolution(pContext,
841 						    (int)stuff->imageRes,
842 						    &status);
843     else
844         status = FALSE;
845 
846     rep.type = X_Reply;
847     rep.sequenceNumber = client->sequence;
848     rep.length = 0;
849     rep.status = status;
850 
851     if(client->swapped)
852     {
853 	int n;
854 	long l;
855 
856         swaps(&rep.sequenceNumber, n);
857         swapl(&rep.length, l);
858         swaps(&rep.prevRes, n);
859     }
860 
861     WriteToClient(client, sz_xPrintSetImageResolutionReply, (char *)&rep);
862     return client->noClientException;
863 }
864 
865 static int
ProcXpGetImageResolution(client)866 ProcXpGetImageResolution(client)
867     ClientPtr client;
868 {
869     REQUEST(xPrintGetImageResolutionReq);
870     xPrintGetImageResolutionReply rep;
871     XpContextPtr pContext;
872     Bool status;
873     int result;
874 
875     REQUEST_SIZE_MATCH(xPrintGetImageResolutionReq);
876 
877     if((pContext =(XpContextPtr)SecurityLookupIDByType(client,
878 						       stuff->printContext,
879 						       RTcontext,
880 						       SecurityReadAccess))
881        == (XpContextPtr)NULL)
882     {
883 	client->errorValue = stuff->printContext;
884         return XpErrorBase+XPBadContext;
885     }
886 
887     rep.type = X_Reply;
888     rep.sequenceNumber = client->sequence;
889     rep.length = 0;
890     rep.imageRes = pContext->imageRes;
891 
892     if(client->swapped)
893     {
894 	int n;
895 	long l;
896 
897         swaps(&rep.sequenceNumber, n);
898         swapl(&rep.length, l);
899         swaps(&rep.imageRes, n);
900     }
901 
902     WriteToClient(client, sz_xPrintGetImageResolutionReply, (char *)&rep);
903     return client->noClientException;
904 }
905 
906 /*******************************************************************************
907  *
908  * RehashPrinterList : Cause the server's list of printers to be rebuilt.
909  *                     This allows new printers to be added, or old ones
910  *		       deleted without needing to restart the server.
911  *
912  ******************************************************************************/
913 
914 static int
ProcXpRehashPrinterList(client)915 ProcXpRehashPrinterList(client)
916     ClientPtr client;
917 {
918     REQUEST(xPrintRehashPrinterListReq);
919 
920     REQUEST_SIZE_MATCH(xPrintRehashPrinterListReq);
921 
922     return XpRehashPrinterList();
923 }
924 
925 /******************************************************************************
926  *
927  * Context functions: Init, Set, Destroy, FreeContext
928  *			AllocateContextPrivateIndex, AllocateContextPrivate
929  *			and supporting functions.
930  *
931  *     Init creates a context, creates a XpClientRec for the calling
932  *     client, and stores the contextPtr in the client's devPrivates.
933  *
934  *     Set creates a XpClientRec for the calling client, and stores the
935  *     contextPtr in the client's devPrivates unless the context is None.
936  *     If the context is None, then the client's connection association
937  *     with any context is removed.
938  *
939  *     Destroy frees any and all XpClientRecs associated with the context,
940  *     frees the context itself, and removes the contextPtr from any
941  *     relevant client devPrivates.
942  *
943  *     FreeContext is called by FreeResource to free up a context.
944  *
945  ******************************************************************************/
946 
947 /*
948  * CreateContext creates and initializes the memory for the context itself.
949  * The driver's CreateContext function
950  * is then called.
951  */
952 static int
ProcXpCreateContext(client)953 ProcXpCreateContext(client)
954     ClientPtr client;
955 {
956     REQUEST(xPrintCreateContextReq);
957     XpScreenPtr pPrintScreen;
958     WindowPtr pRoot;
959     char *printerName, *driverName;
960     XpContextPtr pContext;
961     XpClientPtr pNewPrintClient;
962     int result = Success;
963     XpDriverPtr pDriver;
964 
965     REQUEST_AT_LEAST_SIZE(xPrintCreateContextReq);
966 
967     LEGAL_NEW_RESOURCE(stuff->contextID, client);
968 
969     /*
970      * Check to see if the printer name is valid.
971      */
972     if((pRoot = XpDiValidatePrinter(stuff + 1, stuff->printerNameLen)) ==
973        (WindowPtr)NULL)
974 	return BadMatch;
975 
976     pPrintScreen = XpScreens[pRoot->drawable.pScreen->myNum];
977 
978     /*
979      * Allocate and add the context resource.
980      */
981     if((pContext = (XpContextPtr) xalloc(totalContextSize)) ==
982        (XpContextPtr) NULL)
983 	return BadAlloc;
984 
985     InitContextPrivates(pContext);
986 
987     if(AddResource(stuff->contextID, RTcontext, (pointer) pContext)
988        != TRUE)
989     {
990        xfree(pContext);
991        return BadAlloc;
992     }
993 
994     pContext->contextID = stuff->contextID;
995     pContext->clientHead = (XpClientPtr)NULL;
996     pContext->screenNum = pRoot->drawable.pScreen->myNum;
997     pContext->state = 0;
998     pContext->clientSlept = (ClientPtr)NULL;
999     pContext->imageRes = 0;
1000 
1001     pContext->funcs.DestroyContext = (int (*)())NULL;
1002     pContext->funcs.StartJob = (int (*)())NULL;
1003     pContext->funcs.EndJob = (int (*)())NULL;
1004     pContext->funcs.StartDoc = (int (*)())NULL;
1005     pContext->funcs.EndDoc = (int (*)())NULL;
1006     pContext->funcs.StartPage = (int (*)())NULL;
1007     pContext->funcs.EndPage = (int (*)())NULL;
1008     pContext->funcs.PutDocumentData = (int (*)())NULL;
1009     pContext->funcs.GetDocumentData = (int (*)())NULL;
1010     pContext->funcs.GetAttributes = (char * (*)())NULL;
1011     pContext->funcs.GetOneAttribute = (char * (*)())NULL;
1012     pContext->funcs.SetAttributes = (int (*)())NULL;
1013     pContext->funcs.AugmentAttributes = (int (*)())NULL;
1014     pContext->funcs.GetMediumDimensions = (int (*)())NULL;
1015     pContext->funcs.GetReproducibleArea = (int (*)())NULL;
1016     pContext->funcs.SetImageResolution = (int (*)())NULL;
1017 
1018     if((pContext->printerName = (char *)xalloc(stuff->printerNameLen + 1)) ==
1019        (char *)NULL)
1020     {
1021 	/* Freeing the context also causes the XpClients to be freed. */
1022 	FreeResource(stuff->contextID, RT_NONE);
1023 	return BadAlloc;
1024     }
1025     strncpy(pContext->printerName, (char *)(stuff + 1), stuff->printerNameLen);
1026     pContext->printerName[stuff->printerNameLen] = (char)'\0';
1027 
1028     driverName = XpDiGetDriverName(pRoot->drawable.pScreen->myNum,
1029 				   pContext->printerName);
1030 
1031     for(pDriver = pPrintScreen->drivers;
1032 	pDriver != (XpDriverPtr)NULL;
1033 	pDriver = pDriver->next)
1034     {
1035 	if(!strcmp(driverName, pDriver->name))
1036 	{
1037 	    if(pDriver->CreateContext != (Bool (*)())NULL)
1038 	        pDriver->CreateContext(pContext);
1039 	    else
1040 	        return BadImplementation;
1041 	    break;
1042 	}
1043     }
1044 
1045     if (client->noClientException != Success)
1046         return client->noClientException;
1047     else
1048 	return result;
1049 }
1050 
1051 /*
1052  * SetContext creates the calling client's contextClient resource,
1053  * and stashes the contextID in the client's devPrivate.
1054  */
1055 static int
ProcXpSetContext(client)1056 ProcXpSetContext(client)
1057     ClientPtr client;
1058 {
1059     REQUEST(xPrintSetContextReq);
1060 
1061     XpContextPtr pContext;
1062     XpClientPtr pPrintClient;
1063     int result = Success;
1064 
1065     REQUEST_AT_LEAST_SIZE(xPrintSetContextReq);
1066 
1067     if((pContext = client->devPrivates[XpClientPrivateIndex].ptr) !=
1068        (pointer)NULL)
1069     {
1070 	/*
1071 	 * Erase this client's knowledge of its old context, if any.
1072 	 */
1073         if((pPrintClient = FindClient(pContext, client)) != (XpClientPtr)NULL)
1074         {
1075 	    XpUnsetFontResFunc(client);
1076 
1077 	    if(pPrintClient->eventMask == 0)
1078 		FreeXpClient(pPrintClient, TRUE);
1079         }
1080 
1081         client->devPrivates[XpClientPrivateIndex].ptr = (pointer)NULL;
1082     }
1083     if(stuff->printContext == None)
1084         return Success;
1085 
1086     /*
1087      * Check to see that the supplied XID is really a valid print context
1088      * in this server.
1089      */
1090     if((pContext =(XpContextPtr)SecurityLookupIDByType(client,
1091 						       stuff->printContext,
1092 						       RTcontext,
1093 						       SecurityWriteAccess))
1094        == (XpContextPtr)NULL)
1095     {
1096 	client->errorValue = stuff->printContext;
1097         return XpErrorBase+XPBadContext;
1098     }
1099 
1100     if((pPrintClient = AcquireClient(pContext, client)) == (XpClientPtr)NULL)
1101         return BadAlloc;
1102 
1103     client->devPrivates[XpClientPrivateIndex].ptr = pContext;
1104 
1105     XpSetFontResFunc(client);
1106 
1107     if (client->noClientException != Success)
1108         return client->noClientException;
1109     else
1110 	return result;
1111 }
1112 
1113 XpContextPtr
XpGetPrintContext(client)1114 XpGetPrintContext(client)
1115     ClientPtr client;
1116 {
1117     return (client->devPrivates[XpClientPrivateIndex].ptr);
1118 }
1119 
1120 static int
ProcXpGetContext(client)1121 ProcXpGetContext(client)
1122     ClientPtr client;
1123 {
1124     REQUEST(xPrintGetContextReq);
1125     xPrintGetContextReply rep;
1126 
1127     XpContextPtr pContext;
1128     XpClientPtr pNewPrintClient;
1129     int result = Success;
1130     register int n;
1131     register long l;
1132 
1133     REQUEST_SIZE_MATCH(xPrintGetContextReq);
1134 
1135     if((pContext = client->devPrivates[XpClientPrivateIndex].ptr) ==
1136        (pointer)NULL)
1137 	rep.printContext = None;
1138     else
1139         rep.printContext = pContext->contextID;
1140     rep.type = X_Reply;
1141     rep.length = 0;
1142     rep.sequenceNumber = client->sequence;
1143     if (client->swapped) {
1144         swaps(&rep.sequenceNumber, n);
1145         swapl(&rep.length, l);
1146         swapl(&rep.printContext, l);
1147     }
1148     WriteToClient(client, sz_xPrintGetContextReply, (char *)&rep);
1149     return client->noClientException;
1150 }
1151 
1152 
1153 /*
1154  * DestroyContext frees the context associated with the calling client.
1155  * It operates by freeing the context resource ID, thus causing XpFreeContext
1156  * to be called.
1157  */
1158 static int
ProcXpDestroyContext(client)1159 ProcXpDestroyContext(client)
1160     ClientPtr client;
1161 {
1162     REQUEST(xPrintDestroyContextReq);
1163 
1164     XpContextPtr pContext;
1165     XpClientPtr pXpClient;
1166     ClientPtr curClient;
1167 
1168     REQUEST_SIZE_MATCH(xPrintDestroyContextReq);
1169 
1170     if((pContext =(XpContextPtr)SecurityLookupIDByType(client,
1171 						       stuff->printContext,
1172 						       RTcontext,
1173 						       SecurityDestroyAccess))
1174        == (XpContextPtr)NULL)
1175     {
1176 	client->errorValue = stuff->printContext;
1177         return XpErrorBase+XPBadContext;
1178     }
1179 
1180     XpUnsetFontResFunc(client);
1181 
1182     FreeResource(pContext->contextID, RT_NONE);
1183 
1184     return Success;
1185 }
1186 
1187 static int
ProcXpGetContextScreen(client)1188 ProcXpGetContextScreen(client)
1189     ClientPtr client;
1190 {
1191     REQUEST(xPrintGetContextScreenReq);
1192     xPrintGetContextScreenReply rep;
1193     XpContextPtr pContext;
1194     int n;
1195     long l;
1196 
1197     if((pContext =(XpContextPtr)SecurityLookupIDByType(client,
1198 						       stuff->printContext,
1199 						       RTcontext,
1200 						       SecurityReadAccess))
1201        == (XpContextPtr)NULL)
1202         return XpErrorBase+XPBadContext;
1203 
1204     rep.type = X_Reply;
1205     rep.sequenceNumber = client->sequence;
1206     rep.length = 0;
1207     rep.rootWindow = WindowTable[pContext->screenNum]->drawable.id;
1208 
1209     if (client->swapped) {
1210         swaps(&rep.sequenceNumber, n);
1211         swapl(&rep.length, l);
1212         swapl(&rep.rootWindow, l);
1213     }
1214 
1215     WriteToClient(client, sz_xPrintGetContextScreenReply, (char *)&rep);
1216     return client->noClientException;
1217 }
1218 
1219 /*
1220  * XpFreeContext is the routine called by dix:FreeResource when a context
1221  * resource ID is freed.
1222  * It checks to see if there's a partial job pending on the context, and
1223  * if so it calls the appropriate End procs with the cancel flag set.
1224  * It calls the driver's DestroyContext routine to allow the driver to clean
1225  * up any context-related memory or state.
1226  * It calls FreeXpClient to free all the
1227  * associated XpClientRecs and to set all the client->devPrivates to NULL.
1228  * It frees the printer name string, and frees the context
1229  * itself.
1230  */
1231 static int
XpFreeContext(data,id)1232 XpFreeContext(data, id)
1233     pointer data;
1234     XID id;
1235 {
1236     XpContextPtr pContext = (XpContextPtr)data;
1237 
1238     /* Clean up any pending job on this context */
1239     if(pContext->state != 0)
1240     {
1241 	if(pContext->state & PAGE_STARTED)
1242 	{
1243 	    WindowPtr pWin = (WindowPtr )LookupIDByType(
1244 				       pContext->pageWin, RT_WINDOW);
1245 	    XpPagePtr pPage = (XpPagePtr)LookupIDByType(
1246 				       pContext->pageWin, RTpage);
1247 
1248 	    pContext->funcs.EndPage(pContext, pWin, TRUE);
1249 	    SendXpNotify(pContext, XPEndPageNotify, TRUE);
1250 	    pContext->state &= ~PAGE_STARTED;
1251 	    if(pPage)
1252 	        pPage->context = (XpContextPtr)NULL;
1253 	}
1254 	if((pContext->state & DOC_RAW_STARTED) ||
1255 	   (pContext->state & DOC_COOKED_STARTED))
1256 	{
1257 	    pContext->funcs.EndDoc(pContext, TRUE);
1258 	    SendXpNotify(pContext, XPEndDocNotify, TRUE);
1259 	    pContext->state &= ~DOC_RAW_STARTED;
1260 	    pContext->state &= ~DOC_COOKED_STARTED;
1261 	}
1262 	if(pContext->funcs.EndJob != (int (*)())NULL)
1263 	{
1264 	    pContext->funcs.EndJob(pContext, TRUE);
1265 	    SendXpNotify(pContext, XPEndJobNotify, TRUE);
1266 	    pContext->state &= ~JOB_STARTED;
1267 	    pContext->state &= ~GET_DOC_DATA_STARTED;
1268 	}
1269     }
1270 
1271     /*
1272      * Tell the driver we're destroying the context
1273      * This allows the driver to free and ContextPrivate data
1274      */
1275     if(pContext->funcs.DestroyContext != (int (*)())NULL)
1276 	pContext->funcs.DestroyContext(pContext);
1277 
1278     /* Free up all the XpClientRecs */
1279     while(pContext->clientHead != (XpClientPtr)NULL)
1280     {
1281 	FreeXpClient(pContext->clientHead, TRUE);
1282     }
1283 
1284     xfree(pContext->printerName);
1285     xfree(pContext);
1286     return Success; /* ??? */
1287 }
1288 
1289 /*
1290  * XpFreeClient is the routine called by dix:FreeResource when a RTclient
1291  * is freed.  It simply calls the FreeXpClient routine to do the work.
1292  */
1293 static int
XpFreeClient(data,id)1294 XpFreeClient(data, id)
1295     pointer data;
1296     XID id;
1297 {
1298     FreeXpClient((XpClientPtr)data, FALSE);
1299 
1300     return Success;
1301 }
1302 
1303 /*
1304  * FreeXpClient
1305  * frees the ClientRec passed in, and sets the client->devPrivates to NULL
1306  * if the client->devPrivates points to the same context as the XpClient.
1307  * Called from XpFreeContext(from FreeResource), and
1308  * XpFreeClient.  The boolean freeResource specifies whether or not to call
1309  * FreeResource for the XpClientRec's XID.  We should free it except if we're
1310  * called from XpFreeClient (which is itself called from FreeResource for the
1311  * XpClientRec's XID).
1312  */
1313 static void
FreeXpClient(pXpClient,freeResource)1314 FreeXpClient(pXpClient, freeResource)
1315     XpClientPtr pXpClient;
1316     Bool freeResource;
1317 {
1318     XpClientPtr pCurrent, pPrev;
1319     XpContextPtr pContext = pXpClient->context;
1320 
1321     /*
1322      * If we're freeing the clientRec associated with the context tied
1323      * to the client's devPrivates, then we need to clear the devPrivates.
1324      */
1325     if(pXpClient->client->devPrivates[XpClientPrivateIndex].ptr ==
1326        pXpClient->context)
1327     {
1328         pXpClient->client->devPrivates[XpClientPrivateIndex].ptr =
1329 					(pointer)NULL;
1330     }
1331 
1332     for(pPrev = (XpClientPtr)NULL, pCurrent = pContext->clientHead;
1333 	pCurrent != (XpClientPtr)NULL;
1334 	pCurrent = pCurrent->pNext)
1335     {
1336 	if(pCurrent == pXpClient)
1337 	{
1338 	    if(freeResource == TRUE)
1339                 FreeResource (pCurrent->contextClientID, RTclient);
1340 
1341             if (pPrev != (XpClientPtr)NULL)
1342                 pPrev->pNext = pCurrent->pNext;
1343             else
1344                 pContext->clientHead = pCurrent->pNext;
1345 
1346             xfree (pCurrent);
1347 	    break;
1348 	}
1349 	pPrev = pCurrent;
1350     }
1351 }
1352 
1353 /*
1354  * CreateXpClient takes a ClientPtr and returns a pointer to a
1355  * XpClientRec which it allocates.  It also initializes the Rec,
1356  * including adding a resource on behalf of the client to enable the
1357  * freeing of the Rec when the client's connection is closed.
1358  */
1359 static XpClientPtr
CreateXpClient(client)1360 CreateXpClient(client)
1361     ClientPtr client;
1362 {
1363     XpClientPtr pNewPrintClient;
1364     XID clientResource;
1365 
1366     if((pNewPrintClient = (XpClientPtr)xalloc(sizeof(XpClientRec))) ==
1367       (XpClientPtr)NULL)
1368         return (XpClientPtr)NULL;
1369 
1370     clientResource = FakeClientID(client->index);
1371     if(!AddResource(clientResource, RTclient, (pointer)pNewPrintClient))
1372     {
1373         xfree (pNewPrintClient);
1374         return (XpClientPtr)NULL;
1375     }
1376 
1377     pNewPrintClient->pNext = (XpClientPtr)NULL;
1378     pNewPrintClient->client = client;
1379     pNewPrintClient->context = (XpContextPtr)NULL;
1380     pNewPrintClient->eventMask = 0;
1381     pNewPrintClient->contextClientID = clientResource;
1382 
1383     return pNewPrintClient;
1384 }
1385 
1386 /*
1387  * XpFreePage is the routine called by dix:FreeResource to free the page
1388  * resource built with the same ID as a page window.  It checks to see
1389  * if we're in the middle of a page, and if so calls the driver's EndPage
1390  * function with 'cancel' set TRUE.  It frees the memory associated with
1391  * the page resource.
1392  */
1393 static int
XpFreePage(data,id)1394 XpFreePage(data, id)
1395     pointer data;
1396     XID id;
1397 {
1398     XpPagePtr page = (XpPagePtr)data;
1399     int result = Success;
1400     WindowPtr pWin = (WindowPtr )LookupIDByType(id, RT_WINDOW);
1401 
1402     /* Check to see if the window's being deleted in the middle of a page */
1403     if(page->context != (XpContextPtr)NULL &&
1404        page->context->state & PAGE_STARTED)
1405     {
1406 	XpScreenPtr pPrintScreen = XpScreens[page->context->screenNum];
1407 	if(page->context->funcs.EndPage != (int (*)())NULL)
1408 	    result = page->context->funcs.EndPage(page->context, pWin, TRUE);
1409         SendXpNotify(page->context, XPEndPageNotify, (int)TRUE);
1410 	page->context->pageWin = 0; /* None, NULL??? XXX */
1411     }
1412 
1413     xfree(page);
1414     return result;
1415 }
1416 
1417 /*
1418  * ContextPrivate machinery.
1419  * Context privates are intended for use by the drivers, allowing the
1420  * drivers to maintain context-specific data.  The driver should free
1421  * the associated data at DestroyContext time.
1422  */
1423 
1424 static void
InitContextPrivates(context)1425 InitContextPrivates(context)
1426     XpContextPtr context;
1427 {
1428     register char *ptr;
1429     DevUnion *ppriv;
1430     register unsigned *sizes;
1431     register unsigned size;
1432     register int i;
1433 
1434     if (totalContextSize == sizeof(XpContextRec))
1435         ppriv = (DevUnion *)NULL;
1436     else
1437         ppriv = (DevUnion *)(context + 1);
1438 
1439     context->devPrivates = ppriv;
1440     sizes = contextPrivateSizes;
1441     ptr = (char *)(ppriv + contextPrivateLen);
1442     for (i = contextPrivateLen; --i >= 0; ppriv++, sizes++)
1443     {
1444         if ( (size = *sizes) )
1445         {
1446             ppriv->ptr = (pointer)ptr;
1447             ptr += size;
1448         }
1449         else
1450             ppriv->ptr = (pointer)NULL;
1451     }
1452 }
1453 
1454 static void
ResetContextPrivates()1455 ResetContextPrivates()
1456 {
1457     contextPrivateCount = 0;
1458     contextPrivateLen = 0;
1459     xfree(contextPrivateSizes);
1460     contextPrivateSizes = (unsigned *)NULL;
1461     totalContextSize = sizeof(XpContextRec);
1462 
1463 }
1464 
1465 int
XpAllocateContextPrivateIndex()1466 XpAllocateContextPrivateIndex()
1467 {
1468     return contextPrivateCount++;
1469 }
1470 
1471 Bool
XpAllocateContextPrivate(index,amount)1472 XpAllocateContextPrivate(index, amount)
1473     int index;
1474     unsigned amount;
1475 {
1476     unsigned oldamount;
1477 
1478     if (index >= contextPrivateLen)
1479     {
1480         unsigned *nsizes;
1481         nsizes = (unsigned *)xrealloc(contextPrivateSizes,
1482                                       (index + 1) * sizeof(unsigned));
1483         if (!nsizes)
1484             return FALSE;
1485         while (contextPrivateLen <= index)
1486         {
1487             nsizes[contextPrivateLen++] = 0;
1488             totalContextSize += sizeof(DevUnion);
1489         }
1490         contextPrivateSizes = nsizes;
1491     }
1492     oldamount = contextPrivateSizes[index];
1493     if (amount > oldamount)
1494     {
1495         contextPrivateSizes[index] = amount;
1496         totalContextSize += (amount - oldamount);
1497     }
1498     return TRUE;
1499 }
1500 
1501 static XpClientPtr
AcquireClient(pContext,client)1502 AcquireClient(pContext, client)
1503     XpContextPtr pContext;
1504     ClientPtr client;
1505 {
1506     XpClientPtr pXpClient;
1507 
1508     if((pXpClient = FindClient(pContext, client)) != (XpClientPtr)NULL)
1509 	return pXpClient;
1510 
1511     if((pXpClient = CreateXpClient(client)) == (XpClientPtr)NULL)
1512 	    return (XpClientPtr)NULL;
1513 
1514     pXpClient->context = pContext;
1515     pXpClient->pNext = pContext->clientHead;
1516     pContext->clientHead = pXpClient;
1517 
1518     return pXpClient;
1519 }
1520 
1521 static XpClientPtr
FindClient(pContext,client)1522 FindClient(pContext, client)
1523     XpContextPtr pContext;
1524     ClientPtr client;
1525 {
1526     XpClientPtr pXpClient;
1527 
1528     for(pXpClient = pContext->clientHead; pXpClient != (XpClientPtr)NULL;
1529 	pXpClient = pXpClient->pNext)
1530     {
1531 	if(pXpClient->client == client)  return pXpClient;
1532     }
1533     return (XpClientPtr)NULL;
1534 }
1535 
1536 
1537 /******************************************************************************
1538  *
1539  * Start/End Functions: StartJob, EndJob, StartDoc, EndDoc, StartPage, EndPage
1540  *
1541  ******************************************************************************/
1542 
1543 static int
ProcXpStartJob(client)1544 ProcXpStartJob(client)
1545     ClientPtr client;
1546 {
1547     REQUEST(xPrintStartJobReq);
1548     XpContextPtr pContext;
1549     int result = Success;
1550     XpScreenPtr pPrintScreen;
1551 
1552     REQUEST_SIZE_MATCH(xPrintStartJobReq);
1553 
1554     /* Check to see that a context has been established by this client. */
1555     if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr)
1556        == (XpContextPtr)NULL)
1557         return XpErrorBase+XPBadContext;
1558 
1559     if(pContext->state != 0)
1560 	return XpErrorBase+XPBadSequence;
1561 
1562     if(stuff->saveData != XPSpool && stuff->saveData != XPGetData)
1563     {
1564 	client->errorValue = stuff->saveData;
1565 	return BadValue;
1566     }
1567 
1568     pPrintScreen = XpScreens[pContext->screenNum];
1569     if(pContext->funcs.StartJob != (int (*)())NULL)
1570         result = pContext->funcs.StartJob(pContext,
1571 			 (stuff->saveData == XPGetData)? TRUE:FALSE);
1572     else
1573         return BadImplementation;
1574 
1575     pContext->state = JOB_STARTED;
1576     if(stuff->saveData == XPGetData)
1577 	pContext->state |= JOB_GET_DATA;
1578 
1579     SendXpNotify(pContext, XPStartJobNotify, FALSE);
1580 
1581     if (client->noClientException != Success)
1582         return client->noClientException;
1583     else
1584         return result;
1585 }
1586 
1587 static int
ProcXpEndJob(client)1588 ProcXpEndJob(client)
1589     ClientPtr client;
1590 {
1591     REQUEST(xPrintEndJobReq);
1592     XpScreenPtr pPrintScreen;
1593     WindowPtr pWin;
1594     int result = Success;
1595     XpContextPtr pContext;
1596 
1597     REQUEST_SIZE_MATCH(xPrintEndJobReq);
1598 
1599     if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr)
1600        == (XpContextPtr)NULL)
1601         return XpErrorBase+XPBadSequence;
1602 
1603     pPrintScreen = XpScreens[pContext->screenNum];
1604 
1605     if(!(pContext->state & JOB_STARTED))
1606 	return XpErrorBase+XPBadSequence;
1607 
1608     /* Check for missing EndDoc */
1609     if((pContext->state & DOC_RAW_STARTED) ||
1610        (pContext->state & DOC_COOKED_STARTED))
1611     {
1612 	if(pContext->state & PAGE_STARTED)
1613 	{
1614 	    WindowPtr pWin = (WindowPtr )LookupIDByType(
1615 					   pContext->pageWin, RT_WINDOW);
1616 	    XpPagePtr pPage = (XpPagePtr)LookupIDByType(
1617 				       pContext->pageWin, RTpage);
1618 
1619 	    if(stuff->cancel != TRUE)
1620 	        return XpErrorBase+XPBadSequence;
1621 
1622             if(pContext->funcs.EndPage != (int (*)())NULL)
1623                 result = pContext->funcs.EndPage(pContext, pWin, TRUE);
1624             else
1625 	        return BadImplementation;
1626 
1627 	    SendXpNotify(pContext, XPEndPageNotify, TRUE);
1628 
1629 	    pContext->state &= ~PAGE_STARTED;
1630 
1631 	    if(pPage)
1632 	        pPage->context = (XpContextPtr)NULL;
1633 
1634 	    if(result != Success) return result;
1635 	}
1636 
1637         if(pContext->funcs.EndDoc != (int (*)())NULL)
1638             result = pContext->funcs.EndDoc(pContext, stuff->cancel);
1639         else
1640 	    return BadImplementation;
1641 
1642         SendXpNotify(pContext, XPEndDocNotify, stuff->cancel);
1643     }
1644 
1645     if(pContext->funcs.EndJob != (int (*)())NULL)
1646         result = pContext->funcs.EndJob(pContext, stuff->cancel);
1647     else
1648 	return BadImplementation;
1649 
1650     pContext->state = 0;
1651 
1652     SendXpNotify(pContext, XPEndJobNotify, stuff->cancel);
1653 
1654     if (client->noClientException != Success)
1655         return client->noClientException;
1656     else
1657         return result;
1658 }
1659 
1660 static Bool
DoStartDoc(client,c)1661 DoStartDoc(client, c)
1662     ClientPtr client;
1663     XpStDocPtr c;
1664 {
1665     XpScreenPtr pPrintScreen;
1666     int result = Success;
1667     XpContextPtr pContext = c->pContext;
1668 
1669     if(c->pContext->state & JOB_GET_DATA &&
1670        !(c->pContext->state & GET_DOC_DATA_STARTED))
1671     {
1672 	if(!c->slept)
1673 	{
1674 	    c->slept = TRUE;
1675 	    ClientSleep(client, (ClientSleepProcPtr)DoStartDoc, (pointer) c);
1676 	    c->pContext->clientSlept = client;
1677 	}
1678 	return TRUE;
1679     }
1680 
1681     pPrintScreen = XpScreens[pContext->screenNum];
1682 
1683     if(pContext->funcs.StartDoc != (int (*)())NULL)
1684         result = pContext->funcs.StartDoc(pContext, c->type);
1685     else
1686     {
1687 	    SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0,
1688 			      BadImplementation);
1689 	    return TRUE;
1690     }
1691 
1692     if(c->type == XPDocNormal)
1693         pContext->state |= DOC_COOKED_STARTED;
1694     else
1695 	pContext->state |= DOC_RAW_STARTED;
1696 
1697     SendXpNotify(pContext, XPStartDocNotify, (int)FALSE);
1698 
1699     xfree(c);
1700     return TRUE;
1701 }
1702 
1703 static int
ProcXpStartDoc(client)1704 ProcXpStartDoc(client)
1705     ClientPtr client;
1706 {
1707     REQUEST(xPrintStartDocReq);
1708     XpScreenPtr pPrintScreen;
1709     int result = Success;
1710     XpContextPtr pContext;
1711     XpStDocPtr c;
1712 
1713     REQUEST_SIZE_MATCH(xPrintStartDocReq);
1714 
1715     if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr)
1716        == (XpContextPtr)NULL)
1717         return XpErrorBase+XPBadSequence;
1718 
1719     if(!(pContext->state & JOB_STARTED) ||
1720        pContext->state & DOC_RAW_STARTED ||
1721        pContext->state & DOC_COOKED_STARTED)
1722 	return XpErrorBase+XPBadSequence;
1723 
1724     if(stuff->type != XPDocNormal && stuff->type != XPDocRaw)
1725     {
1726 	client->errorValue = stuff->type;
1727 	return BadValue;
1728     }
1729 
1730     c = (XpStDocPtr)xalloc(sizeof(XpStDocRec));
1731     c->pContext = pContext;
1732     c->type = stuff->type;
1733     c->slept = FALSE;
1734     (void)DoStartDoc(client, c);
1735 
1736     if (client->noClientException != Success)
1737         return client->noClientException;
1738     else
1739         return result;
1740 }
1741 
1742 static int
ProcXpEndDoc(client)1743 ProcXpEndDoc(client)
1744     ClientPtr client;
1745 {
1746     REQUEST(xPrintEndDocReq);
1747     XpScreenPtr pPrintScreen;
1748     XpContextPtr pContext;
1749     int result = Success;
1750 
1751     REQUEST_SIZE_MATCH(xPrintEndDocReq);
1752 
1753     if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr)
1754        == (XpContextPtr)NULL)
1755         return XpErrorBase+XPBadSequence;
1756 
1757     pPrintScreen = XpScreens[pContext->screenNum];
1758 
1759     if(!(pContext->state & DOC_RAW_STARTED) &&
1760        !(pContext->state & DOC_COOKED_STARTED))
1761 	return XpErrorBase+XPBadSequence;
1762 
1763     if(pContext->state & PAGE_STARTED)
1764     {
1765 	if(stuff->cancel == TRUE)
1766 	{
1767 	    WindowPtr pWin = (WindowPtr )LookupIDByType(
1768 					   pContext->pageWin, RT_WINDOW);
1769 	    XpPagePtr pPage = (XpPagePtr)LookupIDByType(
1770 				       pContext->pageWin, RTpage);
1771 
1772             if(pContext->funcs.EndPage != (int (*)())NULL)
1773                 result = pContext->funcs.EndPage(pContext, pWin, TRUE);
1774             else
1775 	        return BadImplementation;
1776 
1777 	    SendXpNotify(pContext, XPEndPageNotify, TRUE);
1778 
1779 	    if(pPage)
1780 	        pPage->context = (XpContextPtr)NULL;
1781 	}
1782 	else
1783 	    return XpErrorBase+XPBadSequence;
1784 	if(result != Success)
1785 	    return result;
1786     }
1787 
1788     if(pContext->funcs.EndDoc != (int (*)())NULL)
1789         result = pContext->funcs.EndDoc(pContext, stuff->cancel);
1790     else
1791 	return BadImplementation;
1792 
1793     pContext->state &= ~DOC_RAW_STARTED;
1794     pContext->state &= ~DOC_COOKED_STARTED;
1795 
1796     SendXpNotify(pContext, XPEndDocNotify, stuff->cancel);
1797 
1798     if (client->noClientException != Success)
1799         return client->noClientException;
1800     else
1801         return result;
1802 }
1803 
1804 static Bool
DoStartPage(client,c)1805 DoStartPage(client, c)
1806     ClientPtr client;
1807     XpStPagePtr c;
1808 {
1809     XpScreenPtr pPrintScreen;
1810     WindowPtr pWin = c->pWin;
1811     int result = Success;
1812     XpContextPtr pContext = c->pContext;
1813     XpPagePtr pPage;
1814 
1815     if(c->pContext->state & JOB_GET_DATA &&
1816        !(c->pContext->state & GET_DOC_DATA_STARTED))
1817     {
1818 	if(!c->slept)
1819 	{
1820 	    c->slept = TRUE;
1821 	    ClientSleep(client, (ClientSleepProcPtr)DoStartPage, (pointer) c);
1822 	    c->pContext->clientSlept = client;
1823 	}
1824 	return TRUE;
1825     }
1826 
1827     if(!(pContext->state & DOC_COOKED_STARTED))
1828     {
1829 	/* Implied StartDoc if it was omitted */
1830         if(pContext->funcs.StartDoc != (int (*)())NULL)
1831             result = pContext->funcs.StartDoc(pContext, XPDocNormal);
1832         else
1833 	{
1834 	    SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0,
1835 			      BadImplementation);
1836 	    return TRUE;
1837 	}
1838 
1839 	if(result != Success)
1840 	{
1841 	    SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0, result);
1842 	    return TRUE;
1843 	}
1844 
1845         pContext->state |= DOC_COOKED_STARTED;
1846         SendXpNotify(pContext, XPStartDocNotify, (int)FALSE);
1847     }
1848 
1849     /* ensure the window's not already being used as a page */
1850     if((pPage = (XpPagePtr)LookupIDByType(c->pWin->drawable.id, RTpage)) !=
1851        (XpPagePtr)NULL)
1852     {
1853         if(pPage->context != (XpContextPtr)NULL)
1854 	{
1855 	    SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0,
1856 			      BadWindow);
1857 	    return TRUE;
1858 	}
1859     }
1860     else
1861     {
1862         if((pPage = (XpPagePtr)xalloc(sizeof(XpPageRec))) == (XpPagePtr)NULL)
1863 	{
1864 	    SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0,
1865 			      BadAlloc);
1866 	    return TRUE;
1867 	}
1868         if(AddResource(c->pWin->drawable.id, RTpage, pPage) == FALSE)
1869         {
1870 	    xfree(pPage);
1871 	    SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0,
1872 			      BadAlloc);
1873 	    return TRUE;
1874         }
1875     }
1876 
1877     pPage->context = pContext;
1878     pContext->pageWin = c->pWin->drawable.id;
1879 
1880     pPrintScreen = XpScreens[pContext->screenNum];
1881 
1882 
1883     if(pContext->funcs.StartPage != (int (*)())NULL)
1884         result = pContext->funcs.StartPage(pContext, pWin);
1885     else
1886     {
1887 	SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0,
1888 			  BadImplementation);
1889 	return TRUE;
1890     }
1891 
1892     pContext->state |= PAGE_STARTED;
1893 
1894     (void)MapWindow(pWin, client);
1895 
1896     SendXpNotify(pContext, XPStartPageNotify, (int)FALSE);
1897 
1898     return TRUE;
1899 }
1900 
1901 static int
ProcXpStartPage(client)1902 ProcXpStartPage(client)
1903     ClientPtr client;
1904 {
1905     REQUEST(xPrintStartPageReq);
1906     XpScreenPtr pPrintScreen;
1907     WindowPtr pWin;
1908     int result = Success;
1909     XpContextPtr pContext;
1910     XpPagePtr pPage;
1911     XpStPagePtr c;
1912 
1913     REQUEST_SIZE_MATCH(xPrintStartPageReq);
1914 
1915     if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr)
1916        == (XpContextPtr)NULL)
1917         return XpErrorBase+XPBadSequence;
1918 
1919     if(!(pContext->state & JOB_STARTED))
1920 	return XpErrorBase+XPBadSequence;
1921 
1922     /* can't have pages in a raw documented */
1923     if(pContext->state & DOC_RAW_STARTED)
1924 	return XpErrorBase+XPBadSequence;
1925 
1926     if(pContext->state & PAGE_STARTED)
1927 	return XpErrorBase+XPBadSequence;
1928 
1929     pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
1930 					   SecurityWriteAccess);
1931     if (!pWin || pWin->drawable.pScreen->myNum != pContext->screenNum)
1932 	return BadWindow;
1933 
1934     if((c = (XpStPagePtr)xalloc(sizeof(XpStPageRec))) == (XpStPagePtr)NULL)
1935 	return BadAlloc;
1936     c->pContext = pContext;
1937     c->slept = FALSE;
1938     c->pWin = pWin;
1939 
1940     (void)DoStartPage(client, c);
1941 
1942     if (client->noClientException != Success)
1943         return client->noClientException;
1944     else
1945         return result;
1946 }
1947 
1948 static int
ProcXpEndPage(client)1949 ProcXpEndPage(client)
1950     ClientPtr client;
1951 {
1952     REQUEST(xPrintEndPageReq);
1953     XpScreenPtr pPrintScreen;
1954     int result = Success;
1955     XpContextPtr pContext;
1956     XpPagePtr page;
1957     WindowPtr pWin;
1958 
1959     REQUEST_SIZE_MATCH(xPrintEndPageReq);
1960 
1961     if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr)
1962        == (XpContextPtr)NULL)
1963         return XpErrorBase+XPBadSequence;
1964 
1965     if(!(pContext->state & PAGE_STARTED))
1966 	return XpErrorBase+XPBadSequence;
1967 
1968     pPrintScreen = XpScreens[pContext->screenNum];
1969     pWin = (WindowPtr )LookupIDByType(pContext->pageWin, RT_WINDOW);
1970 
1971     /* Call the ddx's EndPage proc. */
1972     if(pContext->funcs.EndPage != (int (*)())NULL)
1973         result = pContext->funcs.EndPage(pContext, pWin, stuff->cancel);
1974     else
1975 	return BadImplementation;
1976 
1977     if((page = (XpPagePtr)LookupIDByType(pContext->pageWin, RTpage)) !=
1978        (XpPagePtr)NULL)
1979 	page->context = (XpContextPtr)NULL;
1980 
1981     pContext->state &= ~PAGE_STARTED;
1982     pContext->pageWin = 0; /* None, NULL??? XXX */
1983 
1984     (void)UnmapWindow(pWin, FALSE);
1985 
1986     SendXpNotify(pContext, XPEndPageNotify, stuff->cancel);
1987 
1988     if (client->noClientException != Success)
1989         return client->noClientException;
1990     else
1991         return result;
1992 }
1993 
1994 /*******************************************************************************
1995  *
1996  * Document Data Functions: PutDocumentData, GetDocumentData
1997  *
1998  ******************************************************************************/
1999 
2000 static int
ProcXpPutDocumentData(client)2001 ProcXpPutDocumentData(client)
2002     ClientPtr client;
2003 {
2004     REQUEST(xPrintPutDocumentDataReq);
2005     XpContextPtr pContext;
2006     DrawablePtr pDraw;
2007     int result = Success;
2008     int len, totalSize;
2009     char *pData, *pDoc_fmt, *pOptions;
2010 
2011     REQUEST_AT_LEAST_SIZE(xPrintPutDocumentDataReq);
2012 
2013     if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr)
2014        == (XpContextPtr)NULL)
2015         return XpErrorBase+XPBadSequence;
2016 
2017     if(!(pContext->state & DOC_RAW_STARTED) &&
2018        !(pContext->state & DOC_COOKED_STARTED))
2019         return XpErrorBase+XPBadSequence;
2020 
2021     if (stuff->drawable) {
2022 	if (pContext->state & DOC_RAW_STARTED)
2023 	    return BadDrawable;
2024 	pDraw = (DrawablePtr)LookupDrawable(stuff->drawable, client);
2025 	if (!pDraw || pDraw->pScreen->myNum != pContext->screenNum)
2026 	    return BadDrawable;
2027     } else {
2028 	if (pContext->state & DOC_COOKED_STARTED)
2029 	    return BadDrawable;
2030 	pDraw = NULL;
2031     }
2032 
2033     pData = (char *)(&stuff[1]);
2034 
2035     totalSize = (stuff->len_data + 3) >> 2;
2036     pDoc_fmt = pData + (totalSize << 2);
2037 
2038     totalSize += (stuff->len_fmt + 3) >> 2;
2039     pOptions = pData + (totalSize << 2);
2040 
2041     totalSize += (stuff->len_options + 3) >> 2;
2042     if((totalSize + (sz_xPrintPutDocumentDataReq >> 2)) != client->req_len)
2043 	 return BadLength;
2044 
2045     if(pContext->funcs.PutDocumentData != (int (*)())NULL)
2046     {
2047         result = (*pContext->funcs.PutDocumentData)(pContext, pDraw,
2048 					  pData, stuff->len_data,
2049 				          pDoc_fmt, stuff->len_fmt,
2050 				          pOptions, stuff->len_options,
2051 					  client);
2052     }
2053     else
2054 	return BadImplementation;
2055 
2056     if (client->noClientException != Success)
2057         return client->noClientException;
2058     else
2059         return result;
2060 }
2061 
2062 static int
ProcXpGetDocumentData(client)2063 ProcXpGetDocumentData(client)
2064     ClientPtr client;
2065 {
2066     REQUEST(xPrintGetDocumentDataReq);
2067     xPrintGetDocumentDataReply rep;
2068     XpScreenPtr pPrintScreen;
2069     XpContextPtr pContext;
2070     int result = Success;
2071 
2072     REQUEST_SIZE_MATCH(xPrintGetDocumentDataReq);
2073 
2074     if((pContext = (XpContextPtr)SecurityLookupIDByType(client,
2075 							stuff->printContext,
2076 							RTcontext,
2077 							SecurityWriteAccess))
2078        == (XpContextPtr)NULL)
2079     {
2080         client->errorValue = stuff->printContext;
2081         return XpErrorBase+XPBadContext;
2082     }
2083 
2084     if(pContext->funcs.GetDocumentData == (int (*)())NULL)
2085 	return BadImplementation;
2086 
2087     if(!(pContext->state & JOB_GET_DATA) ||
2088        pContext->state & GET_DOC_DATA_STARTED)
2089 	return XpErrorBase+XPBadSequence;
2090 
2091     if(stuff->maxBufferSize <= 0)
2092     {
2093 	client->errorValue = stuff->maxBufferSize;
2094         return BadValue; /* gotta have a positive buffer size */
2095     }
2096 
2097     result = (*pContext->funcs.GetDocumentData)(pContext, client,
2098 						stuff->maxBufferSize);
2099     if(result != Success)
2100     {
2101 	rep.type = X_Reply;
2102 	rep.sequenceNumber = client->sequence;
2103 	rep.length = 0;
2104 	rep.dataLen = 0;
2105 	rep.statusCode = 1;
2106 	rep.finishedFlag = TRUE;
2107         if (client->swapped) {
2108             int n;
2109             long l;
2110 
2111             swaps(&rep.sequenceNumber, n);
2112             swapl(&rep.statusCode, l); /* XXX Why are these longs??? */
2113             swapl(&rep.finishedFlag, l); /* XXX Why are these longs??? */
2114         }
2115 	(void)WriteToClient(client,sz_xPrintGetDocumentDataReply,(char *)&rep);
2116     }
2117     else
2118         pContext->state |= GET_DOC_DATA_STARTED;
2119 
2120     if(pContext->clientSlept != (ClientPtr)NULL)
2121     {
2122 	ClientSignal(pContext->clientSlept);
2123 	ClientWakeup(pContext->clientSlept);
2124 	pContext->clientSlept = (ClientPtr)NULL;
2125     }
2126 
2127     return result;
2128 }
2129 
2130 /*******************************************************************************
2131  *
2132  * Attribute requests: GetAttributes, SetAttributes, GetOneAttribute
2133  *
2134  ******************************************************************************/
2135 
2136 static int
ProcXpGetAttributes(client)2137 ProcXpGetAttributes(client)
2138     ClientPtr client;
2139 {
2140     REQUEST(xPrintGetAttributesReq);
2141     XpContextPtr pContext;
2142     char *attrs;
2143     xPrintGetAttributesReply *pRep;
2144     int totalSize, n;
2145     unsigned long l;
2146 
2147     REQUEST_SIZE_MATCH(xPrintGetAttributesReq);
2148 
2149     if(stuff->type < XPJobAttr || stuff->type > XPServerAttr)
2150     {
2151 	client->errorValue = stuff->type;
2152 	return BadValue;
2153     }
2154 
2155     if(stuff->type != XPServerAttr)
2156     {
2157         if((pContext = (XpContextPtr)SecurityLookupIDByType(
2158 						client,
2159 						stuff->printContext,
2160 						RTcontext,
2161 						SecurityReadAccess))
2162 	   == (XpContextPtr)NULL)
2163         {
2164 	    client->errorValue = stuff->printContext;
2165             return XpErrorBase+XPBadContext;
2166         }
2167 
2168         if(pContext->funcs.GetAttributes == (char *(*)())NULL)
2169 	    return BadImplementation;
2170         if((attrs = (*pContext->funcs.GetAttributes)(pContext, stuff->type)) ==
2171            (char *)NULL)
2172 	    return BadAlloc;
2173     }
2174     else
2175     {
2176 	if((attrs = XpGetAttributes((XpContextPtr)NULL, XPServerAttr)) ==
2177 	   (char *)NULL)
2178 	    return BadAlloc;
2179     }
2180 
2181     totalSize = sz_xPrintGetAttributesReply + QUADPAD(strlen(attrs));
2182     if((pRep = (xPrintGetAttributesReply *)malloc(totalSize)) ==
2183        (xPrintGetAttributesReply *)NULL)
2184 	return BadAlloc;
2185 
2186     pRep->type = X_Reply;
2187     pRep->length = (totalSize - sz_xPrintGetAttributesReply) >> 2;
2188     pRep->sequenceNumber = client->sequence;
2189     pRep->stringLen = strlen(attrs);
2190 
2191     if (client->swapped) {
2192         swaps(&pRep->sequenceNumber, n);
2193         swapl(&pRep->length, l);
2194         swapl(&pRep->stringLen, l);
2195     }
2196 
2197     strncpy((char*)(pRep + 1), attrs, strlen(attrs));
2198     xfree(attrs);
2199 
2200     WriteToClient(client, totalSize, (char *)pRep);
2201 
2202     xfree(pRep);
2203 
2204     return client->noClientException;
2205 }
2206 
2207 static int
ProcXpSetAttributes(client)2208 ProcXpSetAttributes(client)
2209     ClientPtr client;
2210 {
2211     REQUEST(xPrintSetAttributesReq);
2212     int result = Success;
2213     XpContextPtr pContext;
2214     char *attr;
2215 
2216     REQUEST_AT_LEAST_SIZE(xPrintSetAttributesReq);
2217 
2218     if(stuff->type < XPJobAttr || stuff->type > XPServerAttr)
2219     {
2220 	client->errorValue = stuff->type;
2221 	return BadValue;
2222     }
2223 
2224     /*
2225      * Disallow changing of read-only attribute pools
2226      */
2227     if(stuff->type == XPPrinterAttr || stuff->type == XPServerAttr)
2228 	return BadMatch;
2229 
2230     if((pContext = (XpContextPtr)SecurityLookupIDByType(
2231 					client,
2232 					stuff->printContext,
2233 					RTcontext,
2234 					SecurityWriteAccess))
2235        == (XpContextPtr)NULL)
2236     {
2237         client->errorValue = stuff->printContext;
2238         return XpErrorBase+XPBadContext;
2239     }
2240 
2241     if(pContext->funcs.SetAttributes == (int (*)())NULL)
2242 	return BadImplementation;
2243 
2244     /*
2245      * Check for attributes being set after their relevant phase
2246      * has already begun (e.g. Job attributes set after StartJob).
2247      */
2248     if((pContext->state & JOB_STARTED) && stuff->type == XPJobAttr)
2249 	return XpErrorBase+XPBadSequence;
2250     if(((pContext->state & DOC_RAW_STARTED) ||
2251        (pContext->state & DOC_COOKED_STARTED)) && stuff->type == XPDocAttr)
2252 	return XpErrorBase+XPBadSequence;
2253     if((pContext->state & PAGE_STARTED) && stuff->type == XPPageAttr)
2254 	return XpErrorBase+XPBadSequence;
2255 
2256     if((attr = (char *)malloc(stuff->stringLen + 1)) == (char *)NULL)
2257 	return BadAlloc;
2258 
2259     strncpy(attr, (char *)(stuff + 1), stuff->stringLen);
2260     attr[stuff->stringLen] = (char)'\0';
2261 
2262     if(stuff->rule == XPAttrReplace)
2263         (*pContext->funcs.SetAttributes)(pContext, stuff->type, attr);
2264     else if(stuff->rule == XPAttrMerge)
2265         (*pContext->funcs.AugmentAttributes)(pContext, stuff->type, attr);
2266     else
2267     {
2268 	client->errorValue = stuff->rule;
2269 	result = BadValue;
2270     }
2271 
2272     xfree(attr);
2273 
2274     SendAttributeNotify(pContext, stuff->type);
2275 
2276     return result;
2277 }
2278 
2279 static int
ProcXpGetOneAttribute(client)2280 ProcXpGetOneAttribute(client)
2281     ClientPtr client;
2282 {
2283     REQUEST(xPrintGetOneAttributeReq);
2284     XpContextPtr pContext;
2285     char *value, *attrName;
2286     xPrintGetOneAttributeReply *pRep;
2287     int totalSize, n;
2288     unsigned long l;
2289 
2290     REQUEST_AT_LEAST_SIZE(xPrintGetOneAttributeReq);
2291 
2292     totalSize = ((sz_xPrintGetOneAttributeReq) >> 2) +
2293                 ((stuff->nameLen + 3) >> 2);
2294     if(totalSize != client->req_len)
2295 	 return BadLength;
2296 
2297     if(stuff->type < XPJobAttr || stuff->type > XPServerAttr)
2298     {
2299 	client->errorValue = stuff->type;
2300 	return BadValue;
2301     }
2302 
2303     if((attrName = (char *)malloc(stuff->nameLen + 1)) == (char *)NULL)
2304 	return BadAlloc;
2305     strncpy(attrName, (char *)(stuff+1), stuff->nameLen);
2306     attrName[stuff->nameLen] = (char)'\0';
2307 
2308     if(stuff->type != XPServerAttr)
2309     {
2310         if((pContext = (XpContextPtr)SecurityLookupIDByType(
2311 						client,
2312 						stuff->printContext,
2313 						RTcontext,
2314 						SecurityReadAccess))
2315 	   == (XpContextPtr)NULL)
2316         {
2317 	    client->errorValue = stuff->printContext;
2318             return XpErrorBase+XPBadContext;
2319         }
2320 
2321         if(pContext->funcs.GetOneAttribute == (char *(*)())NULL)
2322 	    return BadImplementation;
2323         if((value = (*pContext->funcs.GetOneAttribute)(pContext, stuff->type,
2324            attrName)) == (char *)NULL)
2325 	    return BadAlloc;
2326     }
2327     else
2328     {
2329 	if((value = XpGetOneAttribute((XpContextPtr)NULL, XPServerAttr,
2330 	    attrName)) == (char *)NULL)
2331 	    return BadAlloc;
2332     }
2333 
2334     free(attrName);
2335 
2336     totalSize = sz_xPrintGetOneAttributeReply + QUADPAD(strlen(value));
2337     if((pRep = (xPrintGetOneAttributeReply *)malloc(totalSize)) ==
2338        (xPrintGetOneAttributeReply *)NULL)
2339 	return BadAlloc;
2340 
2341     pRep->type = X_Reply;
2342     pRep->length = (totalSize - sz_xPrintGetOneAttributeReply) >> 2;
2343     pRep->sequenceNumber = client->sequence;
2344     pRep->valueLen = strlen(value);
2345 
2346     if (client->swapped) {
2347         swaps(&pRep->sequenceNumber, n);
2348         swapl(&pRep->length, l);
2349         swapl(&pRep->valueLen, l);
2350     }
2351 
2352     strncpy((char*)(pRep + 1), value, strlen(value));
2353 
2354     WriteToClient(client, totalSize, (char *)pRep);
2355 
2356     xfree(pRep);
2357 
2358     return client->noClientException;
2359 }
2360 
2361 /*******************************************************************************
2362  *
2363  * Print Event requests: SelectInput InputSelected, SendXpNotify
2364  *
2365  ******************************************************************************/
2366 
2367 
2368 static int
ProcXpSelectInput(client)2369 ProcXpSelectInput(client)
2370     ClientPtr client;
2371 {
2372     REQUEST(xPrintSelectInputReq);
2373     int result = Success;
2374     XpContextPtr pContext;
2375     XpClientPtr pPrintClient;
2376 
2377     REQUEST_SIZE_MATCH(xPrintSelectInputReq);
2378 
2379     /*
2380      * Check to see that the supplied XID is really a valid print context
2381      * in this server.
2382      */
2383     if((pContext=(XpContextPtr)SecurityLookupIDByType(client,
2384 						      stuff->printContext,
2385 						      RTcontext,
2386 						      SecurityWriteAccess))
2387        == (XpContextPtr)NULL)
2388     {
2389 	client->errorValue = stuff->printContext;
2390         return XpErrorBase+XPBadContext;
2391     }
2392 
2393     if(stuff->eventMask & ~allEvents)
2394     {
2395 	client->errorValue = stuff->eventMask;
2396         return BadValue; /* bogus event mask bits */
2397     }
2398 
2399     if((pPrintClient = AcquireClient(pContext, client)) == (XpClientPtr)NULL)
2400 	return BadAlloc;
2401 
2402     pPrintClient->eventMask = stuff->eventMask;
2403 
2404     return result;
2405 }
2406 
2407 static int
ProcXpInputSelected(client)2408 ProcXpInputSelected(client)
2409     ClientPtr client;
2410 {
2411     REQUEST(xPrintInputSelectedReq);
2412     xPrintInputSelectedReply rep;
2413     register int n;
2414     long l, allMask;
2415     WindowPtr pWin;
2416     XpClientPtr pXpClient;
2417     XpContextPtr pContext;
2418 
2419     REQUEST_SIZE_MATCH(xPrintInputSelectedReq);
2420 
2421     if((pContext=(XpContextPtr)SecurityLookupIDByType(client,
2422 						      stuff->printContext,
2423 						      RTcontext,
2424 						      SecurityReadAccess))
2425        == (XpContextPtr)NULL)
2426     {
2427 	client->errorValue = stuff->printContext;
2428         return XpErrorBase+XPBadContext;
2429     }
2430 
2431     pXpClient = FindClient(pContext, client);
2432 
2433     rep.type = X_Reply;
2434     rep.length = 0;
2435     rep.sequenceNumber = client->sequence;
2436     rep.eventMask = (pXpClient != (XpClientPtr)NULL)? pXpClient->eventMask : 0;
2437     rep.allEventsMask = GetAllEventMasks(pContext);
2438 
2439     if (client->swapped) {
2440         swaps(&rep.sequenceNumber, n);
2441         swapl(&rep.length, l);
2442         swapl(&rep.eventMask, l);
2443         swapl(&rep.allEventsMask, l);
2444     }
2445 
2446     WriteToClient(client, sz_xPrintInputSelectedReply, (char *)&rep);
2447     return client->noClientException;
2448 }
2449 
2450 static void
SendAttributeNotify(pContext,which)2451 SendAttributeNotify(pContext, which)
2452     XpContextPtr pContext;
2453     int which;
2454 {
2455     XpClientPtr        pXpClient;
2456     xPrintAttributeEvent   ae;
2457     ClientPtr	client;
2458 
2459     pXpClient = pContext->clientHead;
2460     if(pXpClient == (XpClientPtr)NULL)
2461         return; /* Nobody's interested in the events (or this context). */
2462 
2463     for (pXpClient = pContext->clientHead;
2464          pXpClient != (XpClientPtr)NULL;
2465          pXpClient = pXpClient->pNext)
2466     {
2467         client = pXpClient->client;
2468         if (client == serverClient || client->clientGone ||
2469 	    !(pXpClient->eventMask & XPAttributeMask))
2470             continue;
2471         ae.type = XPAttributeNotify + XpEventBase;
2472         ae.detail = which;
2473         ae.printContext = pContext->contextID;
2474         ae.sequenceNumber = client->sequence;
2475         WriteEventsToClient (client, 1, (xEvent *) &ae);
2476     }
2477 }
2478 static void
SendXpNotify(pContext,which,val)2479 SendXpNotify(pContext, which, val)
2480     XpContextPtr pContext;
2481     int which;
2482     int val;
2483 {
2484     XpClientPtr        pXpClient;
2485     xPrintPrintEvent   pe;
2486     ClientPtr	client;
2487 
2488     pXpClient = pContext->clientHead;
2489     if(pXpClient == (XpClientPtr)NULL)
2490         return; /* Nobody's interested in the events (or this context). */
2491 
2492     for (pXpClient = pContext->clientHead;
2493          pXpClient != (XpClientPtr)NULL;
2494          pXpClient = pXpClient->pNext)
2495     {
2496         client = pXpClient->client;
2497         if (client == serverClient || client->clientGone ||
2498 	    !(pXpClient->eventMask & XPPrintMask))
2499             continue;
2500         pe.type = XPPrintNotify + XpEventBase;
2501         pe.detail = which;
2502         pe.printContext = pContext->contextID;
2503 	pe.cancel = (Bool)val;
2504         pe.sequenceNumber = client->sequence;
2505         WriteEventsToClient (client, 1, (xEvent *) &pe);
2506     }
2507 }
2508 
2509 static CARD32
GetAllEventMasks(pContext)2510 GetAllEventMasks(pContext)
2511     XpContextPtr pContext;
2512 {
2513     XpClientPtr pPrintClient;
2514     CARD32 totalMask = (CARD32)0;
2515 
2516     for (pPrintClient = pContext->clientHead;
2517          pPrintClient != (XpClientPtr)NULL;
2518          pPrintClient = pPrintClient->pNext)
2519     {
2520         totalMask |= pPrintClient->eventMask;
2521     }
2522     return totalMask;
2523 }
2524 
2525 /*
2526  * XpContextOfClient - returns the XpContextPtr to the context
2527  * associated with the specified client, or NULL if the client
2528  * does not currently have a context set.
2529  */
2530 XpContextPtr
XpContextOfClient(client)2531 XpContextOfClient(client)
2532     ClientPtr client;
2533 {
2534     XpContextPtr pContext;
2535 
2536     return (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr;
2537 }
2538 
2539 
2540 /*******************************************************************************
2541  *
2542  * Swap-request functions
2543  *
2544  ******************************************************************************/
2545 
2546 static int
SProcXpCreateContext(client)2547 SProcXpCreateContext(client)
2548     ClientPtr client;
2549 {
2550     int i;
2551     long n;
2552 
2553     REQUEST(xPrintCreateContextReq);
2554 
2555     swaps(&stuff->length, i);
2556     swapl(&stuff->contextID, n);
2557     swapl(&stuff->printerNameLen, n);
2558     swapl(&stuff->localeLen, n);
2559     return ProcXpCreateContext(client);
2560 }
2561 
2562 static int
SProcXpGetPrinterList(client)2563 SProcXpGetPrinterList(client)
2564     ClientPtr client;
2565 {
2566     int i;
2567     long n;
2568 
2569     REQUEST(xPrintGetPrinterListReq);
2570 
2571     swaps(&stuff->length, i);
2572     swapl(&stuff->printerNameLen, n);
2573     swapl(&stuff->localeLen, n);
2574     return ProcXpGetPrinterList(client);
2575 }
2576 
2577 static int
SProcXpRehashPrinterList(client)2578 SProcXpRehashPrinterList(client)
2579     ClientPtr client;
2580 {
2581     int i;
2582     long n;
2583 
2584     REQUEST(xPrintRehashPrinterListReq);
2585     swaps(&stuff->length, i);
2586     return ProcXpRehashPrinterList(client);
2587 }
2588 
2589 static int
SProcXpSetContext(client)2590 SProcXpSetContext(client)
2591     ClientPtr client;
2592 {
2593     int i;
2594     long n;
2595 
2596     REQUEST(xPrintSetContextReq);
2597     swaps(&stuff->length, i);
2598     swapl(&stuff->printContext, i);
2599     return ProcXpSetContext(client);
2600 }
2601 
2602 static int
SProcXpGetContext(client)2603 SProcXpGetContext(client)
2604     ClientPtr client;
2605 {
2606     int i;
2607 
2608     REQUEST(xPrintGetContextReq);
2609     swaps(&stuff->length, i);
2610     return ProcXpGetContext(client);
2611 }
2612 
2613 static int
SProcXpDestroyContext(client)2614 SProcXpDestroyContext(client)
2615     ClientPtr client;
2616 {
2617     int i;
2618     long n;
2619 
2620     REQUEST(xPrintDestroyContextReq);
2621     swaps(&stuff->length, i);
2622     swapl(&stuff->printContext, n);
2623     return ProcXpDestroyContext(client);
2624 }
2625 
2626 static int
SProcXpGetContextScreen(client)2627 SProcXpGetContextScreen(client)
2628     ClientPtr client;
2629 {
2630     int i;
2631     long n;
2632 
2633     REQUEST(xPrintGetContextScreenReq);
2634     swaps(&stuff->length, i);
2635     swapl(&stuff->printContext, n);
2636     return ProcXpGetContextScreen(client);
2637 }
2638 
2639 static int
SProcXpInputSelected(client)2640 SProcXpInputSelected(client)
2641     ClientPtr client;
2642 {
2643     int i;
2644     long n;
2645 
2646     REQUEST(xPrintInputSelectedReq);
2647     swaps(&stuff->length, i);
2648     swapl(&stuff->printContext, n);
2649     return ProcXpInputSelected(client);
2650 }
2651 
2652 static int
SProcXpStartJob(client)2653 SProcXpStartJob(client)
2654     ClientPtr client;
2655 {
2656     int i;
2657 
2658     REQUEST(xPrintStartJobReq);
2659     swaps(&stuff->length, i);
2660     return ProcXpStartJob(client);
2661 }
2662 
2663 static int
SProcXpEndJob(client)2664 SProcXpEndJob(client)
2665     ClientPtr client;
2666 {
2667     int i;
2668 
2669     REQUEST(xPrintEndJobReq);
2670     swaps(&stuff->length, i);
2671     return ProcXpEndJob(client);
2672 }
2673 
2674 static int
SProcXpStartDoc(client)2675 SProcXpStartDoc(client)
2676     ClientPtr client;
2677 {
2678     int i;
2679 
2680     REQUEST(xPrintStartDocReq);
2681     swaps(&stuff->length, i);
2682     return ProcXpStartDoc(client);
2683 }
2684 
2685 static int
SProcXpEndDoc(client)2686 SProcXpEndDoc(client)
2687     ClientPtr client;
2688 {
2689     int i;
2690 
2691     REQUEST(xPrintEndDocReq);
2692     swaps(&stuff->length, i);
2693     return ProcXpEndDoc(client);
2694 }
2695 
2696 static int
SProcXpStartPage(client)2697 SProcXpStartPage(client)
2698     ClientPtr client;
2699 {
2700     int i;
2701     long n;
2702 
2703     REQUEST(xPrintStartPageReq);
2704     swaps(&stuff->length, i);
2705     swapl(&stuff->window, n);
2706     return ProcXpStartPage(client);
2707 }
2708 
2709 static int
SProcXpEndPage(client)2710 SProcXpEndPage(client)
2711     ClientPtr client;
2712 {
2713     int i;
2714 
2715     REQUEST(xPrintEndPageReq);
2716     swaps(&stuff->length, i);
2717     return ProcXpEndPage(client);
2718 }
2719 
2720 static int
SProcXpPutDocumentData(client)2721 SProcXpPutDocumentData(client)
2722     ClientPtr client;
2723 {
2724     long n;
2725     int i;
2726 
2727     REQUEST(xPrintPutDocumentDataReq);
2728     swaps(&stuff->length, i);
2729     swapl(&stuff->drawable, n);
2730     swapl(&stuff->len_data, n);
2731     swaps(&stuff->len_fmt, i);
2732     swaps(&stuff->len_options, i);
2733     return ProcXpPutDocumentData(client);
2734 }
2735 
2736 static int
SProcXpGetDocumentData(client)2737 SProcXpGetDocumentData(client)
2738     ClientPtr client;
2739 {
2740     long n;
2741     int i;
2742 
2743     REQUEST(xPrintGetDocumentDataReq);
2744     swaps(&stuff->length, i);
2745     swapl(&stuff->printContext, n);
2746     swapl(&stuff->maxBufferSize, n);
2747     return ProcXpGetDocumentData(client);
2748 }
2749 
2750 static int
SProcXpGetAttributes(client)2751 SProcXpGetAttributes(client)
2752     ClientPtr client;
2753 {
2754     long n;
2755     int i;
2756 
2757     REQUEST(xPrintGetAttributesReq);
2758     swaps(&stuff->length, i);
2759     swapl(&stuff->printContext, n);
2760     return ProcXpGetAttributes(client);
2761 }
2762 
2763 static int
SProcXpSetAttributes(client)2764 SProcXpSetAttributes(client)
2765     ClientPtr client;
2766 {
2767     long n;
2768     int i;
2769 
2770     REQUEST(xPrintSetAttributesReq);
2771     swaps(&stuff->length, i);
2772     swapl(&stuff->printContext, n);
2773     swapl(&stuff->stringLen, n);
2774     return ProcXpSetAttributes(client);
2775 }
2776 
2777 static int
SProcXpGetOneAttribute(client)2778 SProcXpGetOneAttribute(client)
2779     ClientPtr client;
2780 {
2781     long n;
2782     int i;
2783 
2784     REQUEST(xPrintGetOneAttributeReq);
2785     swaps(&stuff->length, i);
2786     swapl(&stuff->printContext, n);
2787     swapl(&stuff->nameLen, n);
2788     return ProcXpGetOneAttribute(client);
2789 }
2790 
2791 static int
SProcXpSelectInput(client)2792 SProcXpSelectInput(client)
2793     ClientPtr client;
2794 {
2795     long n;
2796     int i;
2797 
2798     REQUEST(xPrintSelectInputReq);
2799     swaps(&stuff->length, i);
2800     swapl(&stuff->eventMask, n);
2801     swapl(&stuff->printContext, n);
2802     return ProcXpSelectInput(client);
2803 }
2804 static int
SProcXpGetPageDimensions(client)2805 SProcXpGetPageDimensions(client)
2806     ClientPtr client;
2807 {
2808     long n;
2809     int i;
2810 
2811     REQUEST(xPrintGetPageDimensionsReq);
2812     swaps(&stuff->length, i);
2813     swapl(&stuff->printContext, n);
2814     return ProcXpGetPageDimensions(client);
2815 }
2816 static int
SProcXpSetImageResolution(client)2817 SProcXpSetImageResolution(client)
2818     ClientPtr client;
2819 {
2820     long n;
2821     int i;
2822 
2823     REQUEST(xPrintSetImageResolutionReq);
2824     swaps(&stuff->length, i);
2825     swapl(&stuff->printContext, n);
2826     swaps(&stuff->imageRes, i);
2827     return ProcXpSetImageResolution(client);
2828 }
2829 static int
SProcXpGetImageResolution(client)2830 SProcXpGetImageResolution(client)
2831     ClientPtr client;
2832 {
2833     long n;
2834     int i;
2835 
2836     REQUEST(xPrintGetImageResolutionReq);
2837     swaps(&stuff->length, i);
2838     swapl(&stuff->printContext, n);
2839     return ProcXpGetImageResolution(client);
2840 }
2841 
2842 static void
SwapXpNotifyEvent(src,dst)2843 SwapXpNotifyEvent(src, dst)
2844     xPrintPrintEvent *src, *dst;
2845 {
2846     /*
2847      * Swap the sequence number and context fields.
2848      */
2849     cpswaps(src->sequenceNumber, dst->sequenceNumber);
2850     cpswapl(src->printContext, dst->printContext);
2851 
2852     /*
2853      * Copy the byte-long fields.
2854      */
2855     dst->type = src->type;
2856     dst->detail = src->detail;
2857     dst->cancel = src->cancel;
2858 }
2859 
2860 static void
SwapXpAttributeEvent(src,dst)2861 SwapXpAttributeEvent(src, dst)
2862     xPrintAttributeEvent *src, *dst;
2863 {
2864     /*
2865      * Swap the sequence number and context fields.
2866      */
2867     cpswaps(src->sequenceNumber, dst->sequenceNumber);
2868     cpswapl(src->printContext, dst->printContext);
2869 
2870     /*
2871      * Copy the byte-long fields.
2872      */
2873     dst->type = src->type;
2874     dst->detail = src->detail;
2875 }
2876