dispatch.c revision b1d344b3
1/************************************************************
2
3Copyright 1987, 1989, 1998  The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25
26Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
27
28                        All Rights Reserved
29
30Permission to use, copy, modify, and distribute this software and its
31documentation for any purpose and without fee is hereby granted,
32provided that the above copyright notice appear in all copies and that
33both that copyright notice and this permission notice appear in
34supporting documentation, and that the name of Digital not be
35used in advertising or publicity pertaining to distribution of the
36software without specific, written prior permission.
37
38DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
40DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
41ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
43ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
44SOFTWARE.
45
46********************************************************/
47
48/* The panoramix components contained the following notice */
49/*****************************************************************
50
51Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
52
53Permission is hereby granted, free of charge, to any person obtaining a copy
54of this software and associated documentation files (the "Software"), to deal
55in the Software without restriction, including without limitation the rights
56to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
57copies of the Software.
58
59The above copyright notice and this permission notice shall be included in
60all copies or substantial portions of the Software.
61
62THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
63IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
64FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
65DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
66BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
67WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
68IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
69
70Except as contained in this notice, the name of Digital Equipment Corporation
71shall not be used in advertising or otherwise to promote the sale, use or other
72dealings in this Software without prior written authorization from Digital
73Equipment Corporation.
74
75******************************************************************/
76
77/* XSERVER_DTRACE additions:
78 * Copyright 2005-2006 Sun Microsystems, Inc.  All rights reserved.
79 *
80 * Permission is hereby granted, free of charge, to any person obtaining a
81 * copy of this software and associated documentation files (the
82 * "Software"), to deal in the Software without restriction, including
83 * without limitation the rights to use, copy, modify, merge, publish,
84 * distribute, and/or sell copies of the Software, and to permit persons
85 * to whom the Software is furnished to do so, provided that the above
86 * copyright notice(s) and this permission notice appear in all copies of
87 * the Software and that both the above copyright notice(s) and this
88 * permission notice appear in supporting documentation.
89 *
90 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
91 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
92 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
93 * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
94 * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
95 * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
96 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
97 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
98 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
99 *
100 * Except as contained in this notice, the name of a copyright holder
101 * shall not be used in advertising or otherwise to promote the sale, use
102 * or other dealings in this Software without prior written authorization
103 * of the copyright holder.
104 */
105
106
107
108#ifdef HAVE_DIX_CONFIG_H
109#include <dix-config.h>
110#endif
111
112#ifdef PANORAMIX_DEBUG
113#include <stdio.h>
114int ProcInitialConnection();
115#endif
116
117#include "windowstr.h"
118#include <X11/fonts/fontstruct.h>
119#include "dixfontstr.h"
120#include "gcstruct.h"
121#include "selection.h"
122#include "colormapst.h"
123#include "cursorstr.h"
124#include "scrnintstr.h"
125#include "opaque.h"
126#include "input.h"
127#include "servermd.h"
128#include "extnsionst.h"
129#include "dixfont.h"
130#include "dispatch.h"
131#include "swaprep.h"
132#include "swapreq.h"
133#ifdef PANORAMIX
134#include "panoramiX.h"
135#include "panoramiXsrv.h"
136#endif
137#include "privates.h"
138#include "xace.h"
139#ifdef XKB
140#ifndef XKB_IN_SERVER
141#define XKB_IN_SERVER
142#endif
143#include "inputstr.h"
144#include <xkbsrv.h>
145#endif
146
147#ifdef XSERVER_DTRACE
148#include "registry.h"
149#include <sys/types.h>
150typedef const char *string;
151#include "Xserver-dtrace.h"
152#endif
153
154#define mskcnt ((MAXCLIENTS + 31) / 32)
155#define BITMASK(i) (1U << ((i) & 31))
156#define MASKIDX(i) ((i) >> 5)
157#define MASKWORD(buf, i) buf[MASKIDX(i)]
158#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i)
159#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i)
160#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i))
161
162extern xConnSetupPrefix connSetupPrefix;
163
164static ClientPtr grabClient;
165#define GrabNone 0
166#define GrabActive 1
167#define GrabKickout 2
168static int grabState = GrabNone;
169static long grabWaiters[mskcnt];
170_X_EXPORT CallbackListPtr ServerGrabCallback = NULL;
171HWEventQueuePtr checkForInput[2];
172extern int connBlockScreenStart;
173
174static void KillAllClients(void);
175
176static int nextFreeClientID; /* always MIN free client ID */
177
178static int	nClients;	/* number of authorized clients */
179
180_X_EXPORT CallbackListPtr ClientStateCallback;
181
182/* dispatchException & isItTimeToYield must be declared volatile since they
183 * are modified by signal handlers - otherwise optimizer may assume it doesn't
184 * need to actually check value in memory when used and may miss changes from
185 * signal handlers.
186 */
187_X_EXPORT volatile char dispatchException = 0;
188_X_EXPORT volatile char isItTimeToYield;
189
190/* Various of the DIX function interfaces were not designed to allow
191 * the client->errorValue to be set on BadValue and other errors.
192 * Rather than changing interfaces and breaking untold code we introduce
193 * a new global that dispatch can use.
194 */
195XID clientErrorValue;   /* XXX this is a kludge */
196
197#define SAME_SCREENS(a, b) (\
198    (a.pScreen == b.pScreen))
199
200void
201SetInputCheck(HWEventQueuePtr c0, HWEventQueuePtr c1)
202{
203    checkForInput[0] = c0;
204    checkForInput[1] = c1;
205}
206
207_X_EXPORT void
208UpdateCurrentTime(void)
209{
210    TimeStamp systime;
211
212    /* To avoid time running backwards, we must call GetTimeInMillis before
213     * calling ProcessInputEvents.
214     */
215    systime.months = currentTime.months;
216    systime.milliseconds = GetTimeInMillis();
217    if (systime.milliseconds < currentTime.milliseconds)
218	systime.months++;
219    if (*checkForInput[0] != *checkForInput[1])
220	ProcessInputEvents();
221    if (CompareTimeStamps(systime, currentTime) == LATER)
222	currentTime = systime;
223}
224
225/* Like UpdateCurrentTime, but can't call ProcessInputEvents */
226_X_EXPORT void
227UpdateCurrentTimeIf(void)
228{
229    TimeStamp systime;
230
231    systime.months = currentTime.months;
232    systime.milliseconds = GetTimeInMillis();
233    if (systime.milliseconds < currentTime.milliseconds)
234	systime.months++;
235    if (*checkForInput[0] == *checkForInput[1])
236	currentTime = systime;
237}
238
239
240#undef SMART_DEBUG
241
242#define SMART_SCHEDULE_DEFAULT_INTERVAL	20	    /* ms */
243#define SMART_SCHEDULE_MAX_SLICE	200	    /* ms */
244
245Bool	    SmartScheduleDisable = FALSE;
246long	    SmartScheduleSlice = SMART_SCHEDULE_DEFAULT_INTERVAL;
247long	    SmartScheduleInterval = SMART_SCHEDULE_DEFAULT_INTERVAL;
248long	    SmartScheduleMaxSlice = SMART_SCHEDULE_MAX_SLICE;
249long	    SmartScheduleTime;
250int	    SmartScheduleLatencyLimited = 0;
251static ClientPtr   SmartLastClient;
252static int	   SmartLastIndex[SMART_MAX_PRIORITY-SMART_MIN_PRIORITY+1];
253
254#ifdef SMART_DEBUG
255long	    SmartLastPrint;
256#endif
257
258void        Dispatch(void);
259void        InitProcVectors(void);
260
261static int
262SmartScheduleClient (int *clientReady, int nready)
263{
264    ClientPtr	pClient;
265    int		i;
266    int		client;
267    int		bestPrio, best = 0;
268    int		bestRobin, robin;
269    long	now = SmartScheduleTime;
270    long	idle;
271
272    bestPrio = -0x7fffffff;
273    bestRobin = 0;
274    idle = 2 * SmartScheduleSlice;
275    for (i = 0; i < nready; i++)
276    {
277	client = clientReady[i];
278	pClient = clients[client];
279	/* Praise clients which are idle */
280	if ((now - pClient->smart_check_tick) >= idle)
281	{
282	    if (pClient->smart_priority < 0)
283		pClient->smart_priority++;
284	}
285	pClient->smart_check_tick = now;
286
287	/* check priority to select best client */
288	robin = (pClient->index - SmartLastIndex[pClient->smart_priority-SMART_MIN_PRIORITY]) & 0xff;
289	if (pClient->smart_priority > bestPrio ||
290	    (pClient->smart_priority == bestPrio && robin > bestRobin))
291	{
292	    bestPrio = pClient->smart_priority;
293	    bestRobin = robin;
294	    best = client;
295	}
296#ifdef SMART_DEBUG
297	if ((now - SmartLastPrint) >= 5000)
298	    fprintf (stderr, " %2d: %3d", client, pClient->smart_priority);
299#endif
300    }
301#ifdef SMART_DEBUG
302    if ((now - SmartLastPrint) >= 5000)
303    {
304	fprintf (stderr, " use %2d\n", best);
305	SmartLastPrint = now;
306    }
307#endif
308    pClient = clients[best];
309    SmartLastIndex[bestPrio-SMART_MIN_PRIORITY] = pClient->index;
310    /*
311     * Set current client pointer
312     */
313    if (SmartLastClient != pClient)
314    {
315	pClient->smart_start_tick = now;
316	SmartLastClient = pClient;
317    }
318    /*
319     * Adjust slice
320     */
321    if (nready == 1 && SmartScheduleLatencyLimited == 0)
322    {
323	/*
324	 * If it's been a long time since another client
325	 * has run, bump the slice up to get maximal
326	 * performance from a single client
327	 */
328	if ((now - pClient->smart_start_tick) > 1000 &&
329	    SmartScheduleSlice < SmartScheduleMaxSlice)
330	{
331	    SmartScheduleSlice += SmartScheduleInterval;
332	}
333    }
334    else
335    {
336	SmartScheduleSlice = SmartScheduleInterval;
337    }
338    return best;
339}
340
341void
342EnableLimitedSchedulingLatency(void)
343{
344    ++SmartScheduleLatencyLimited;
345    SmartScheduleSlice = SmartScheduleInterval;
346}
347
348void
349DisableLimitedSchedulingLatency(void)
350{
351    --SmartScheduleLatencyLimited;
352
353    /* protect against bugs */
354    if (SmartScheduleLatencyLimited < 0)
355	SmartScheduleLatencyLimited = 0;
356}
357
358#define MAJOROP ((xReq *)client->requestBuffer)->reqType
359
360void
361Dispatch(void)
362{
363    int        *clientReady;     /* array of request ready clients */
364    int	result;
365    ClientPtr	client;
366    int	nready;
367    HWEventQueuePtr* icheck = checkForInput;
368    long			start_tick;
369
370    nextFreeClientID = 1;
371    nClients = 0;
372
373    clientReady = (int *) xalloc(sizeof(int) * MaxClients);
374    if (!clientReady)
375	return;
376
377    SmartScheduleSlice = SmartScheduleInterval;
378    while (!dispatchException)
379    {
380        if (*icheck[0] != *icheck[1])
381	{
382	    ProcessInputEvents();
383	    FlushIfCriticalOutputPending();
384	}
385
386	nready = WaitForSomething(clientReady);
387
388	if (nready && !SmartScheduleDisable)
389	{
390	    clientReady[0] = SmartScheduleClient (clientReady, nready);
391	    nready = 1;
392	}
393       /*****************
394	*  Handle events in round robin fashion, doing input between
395	*  each round
396	*****************/
397
398	while (!dispatchException && (--nready >= 0))
399	{
400	    client = clients[clientReady[nready]];
401	    if (! client)
402	    {
403		/* KillClient can cause this to happen */
404		continue;
405	    }
406	    /* GrabServer activation can cause this to be true */
407	    if (grabState == GrabKickout)
408	    {
409		grabState = GrabActive;
410		break;
411	    }
412	    isItTimeToYield = FALSE;
413
414	    start_tick = SmartScheduleTime;
415	    while (!isItTimeToYield)
416	    {
417	        if (*icheck[0] != *icheck[1])
418		    ProcessInputEvents();
419
420		FlushIfCriticalOutputPending();
421		if (!SmartScheduleDisable &&
422		    (SmartScheduleTime - start_tick) >= SmartScheduleSlice)
423		{
424		    /* Penalize clients which consume ticks */
425		    if (client->smart_priority > SMART_MIN_PRIORITY)
426			client->smart_priority--;
427		    break;
428		}
429		/* now, finally, deal with client requests */
430
431	        result = ReadRequestFromClient(client);
432	        if (result <= 0)
433	        {
434		    if (result < 0)
435			CloseDownClient(client);
436		    break;
437	        }
438
439		client->sequence++;
440#ifdef DEBUG
441		if (client->requestLogIndex == MAX_REQUEST_LOG)
442		    client->requestLogIndex = 0;
443		client->requestLog[client->requestLogIndex] = MAJOROP;
444		client->requestLogIndex++;
445#endif
446#ifdef XSERVER_DTRACE
447		XSERVER_REQUEST_START(LookupMajorName(MAJOROP), MAJOROP,
448			      ((xReq *)client->requestBuffer)->length,
449			      client->index, client->requestBuffer);
450#endif
451		if (result > (maxBigRequestSize << 2))
452		    result = BadLength;
453		else {
454		    result = XaceHookDispatch(client, MAJOROP);
455		    if (result == Success)
456			result = (* client->requestVector[MAJOROP])(client);
457		    XaceHookAuditEnd(client, result);
458		}
459#ifdef XSERVER_DTRACE
460		XSERVER_REQUEST_DONE(LookupMajorName(MAJOROP), MAJOROP,
461			      client->sequence, client->index, result);
462#endif
463
464		if (result != Success)
465		{
466		    if (client->noClientException != Success)
467                        CloseDownClient(client);
468                    else
469		        SendErrorToClient(client, MAJOROP,
470					  MinorOpcodeOfRequest(client),
471					  client->errorValue, result);
472		    break;
473	        }
474	    }
475	    FlushAllOutput();
476	    client = clients[clientReady[nready]];
477	    if (client)
478		client->smart_stop_tick = SmartScheduleTime;
479	}
480	dispatchException &= ~DE_PRIORITYCHANGE;
481    }
482#if defined(DDXBEFORERESET)
483    ddxBeforeReset ();
484#endif
485    KillAllClients();
486    xfree(clientReady);
487    dispatchException &= ~DE_RESET;
488    SmartScheduleLatencyLimited = 0;
489}
490
491#undef MAJOROP
492
493_X_EXPORT int
494ProcBadRequest(ClientPtr client)
495{
496    return (BadRequest);
497}
498
499int
500ProcCreateWindow(ClientPtr client)
501{
502    WindowPtr pParent, pWin;
503    REQUEST(xCreateWindowReq);
504    int len, rc;
505
506    REQUEST_AT_LEAST_SIZE(xCreateWindowReq);
507
508    LEGAL_NEW_RESOURCE(stuff->wid, client);
509    rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess);
510    if (rc != Success)
511        return rc;
512    len = client->req_len - (sizeof(xCreateWindowReq) >> 2);
513    if (Ones(stuff->mask) != len)
514        return BadLength;
515    if (!stuff->width || !stuff->height)
516    {
517	client->errorValue = 0;
518        return BadValue;
519    }
520    pWin = CreateWindow(stuff->wid, pParent, stuff->x,
521			      stuff->y, stuff->width, stuff->height,
522			      stuff->borderWidth, stuff->class,
523			      stuff->mask, (XID *) &stuff[1],
524			      (int)stuff->depth,
525			      client, stuff->visual, &rc);
526    if (pWin)
527    {
528	Mask mask = pWin->eventMask;
529
530	pWin->eventMask = 0; /* subterfuge in case AddResource fails */
531	if (!AddResource(stuff->wid, RT_WINDOW, (pointer)pWin))
532	    return BadAlloc;
533	pWin->eventMask = mask;
534    }
535    if (client->noClientException != Success)
536        return(client->noClientException);
537    else
538        return rc;
539}
540
541int
542ProcChangeWindowAttributes(ClientPtr client)
543{
544    WindowPtr pWin;
545    REQUEST(xChangeWindowAttributesReq);
546    int result, len, rc;
547    Mask access_mode = 0;
548
549    REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq);
550    access_mode |= (stuff->valueMask & CWEventMask) ? DixReceiveAccess : 0;
551    access_mode |= (stuff->valueMask & ~CWEventMask) ? DixSetAttrAccess : 0;
552    rc = dixLookupWindow(&pWin, stuff->window, client, access_mode);
553    if (rc != Success)
554        return rc;
555    len = client->req_len - (sizeof(xChangeWindowAttributesReq) >> 2);
556    if (len != Ones(stuff->valueMask))
557        return BadLength;
558    result =  ChangeWindowAttributes(pWin,
559				  stuff->valueMask,
560				  (XID *) &stuff[1],
561				  client);
562    if (client->noClientException != Success)
563        return(client->noClientException);
564    else
565        return(result);
566}
567
568int
569ProcGetWindowAttributes(ClientPtr client)
570{
571    WindowPtr pWin;
572    REQUEST(xResourceReq);
573    xGetWindowAttributesReply wa;
574    int rc;
575
576    REQUEST_SIZE_MATCH(xResourceReq);
577    rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
578    if (rc != Success)
579	return rc;
580    GetWindowAttributes(pWin, client, &wa);
581    WriteReplyToClient(client, sizeof(xGetWindowAttributesReply), &wa);
582    return(client->noClientException);
583}
584
585int
586ProcDestroyWindow(ClientPtr client)
587{
588    WindowPtr pWin;
589    REQUEST(xResourceReq);
590    int rc;
591
592    REQUEST_SIZE_MATCH(xResourceReq);
593    rc = dixLookupWindow(&pWin, stuff->id, client, DixDestroyAccess);
594    if (rc != Success)
595	return rc;
596    if (pWin->parent) {
597	rc = dixLookupWindow(&pWin, pWin->parent->drawable.id, client,
598			     DixRemoveAccess);
599	if (rc != Success)
600	    return rc;
601	FreeResource(stuff->id, RT_NONE);
602    }
603    return(client->noClientException);
604}
605
606int
607ProcDestroySubwindows(ClientPtr client)
608{
609    WindowPtr pWin;
610    REQUEST(xResourceReq);
611    int rc;
612
613    REQUEST_SIZE_MATCH(xResourceReq);
614    rc = dixLookupWindow(&pWin, stuff->id, client, DixRemoveAccess);
615    if (rc != Success)
616	return rc;
617    DestroySubwindows(pWin, client);
618    return(client->noClientException);
619}
620
621int
622ProcChangeSaveSet(ClientPtr client)
623{
624    WindowPtr pWin;
625    REQUEST(xChangeSaveSetReq);
626    int result, rc;
627
628    REQUEST_SIZE_MATCH(xChangeSaveSetReq);
629    rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
630    if (rc != Success)
631        return rc;
632    if (client->clientAsMask == (CLIENT_BITS(pWin->drawable.id)))
633        return BadMatch;
634    if ((stuff->mode == SetModeInsert) || (stuff->mode == SetModeDelete))
635    {
636        result = AlterSaveSetForClient(client, pWin, stuff->mode, FALSE, TRUE);
637	if (client->noClientException != Success)
638	    return(client->noClientException);
639	else
640            return(result);
641    }
642    else
643    {
644	client->errorValue = stuff->mode;
645	return( BadValue );
646    }
647}
648
649int
650ProcReparentWindow(ClientPtr client)
651{
652    WindowPtr pWin, pParent;
653    REQUEST(xReparentWindowReq);
654    int result, rc;
655
656    REQUEST_SIZE_MATCH(xReparentWindowReq);
657    rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
658    if (rc != Success)
659        return rc;
660    rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess);
661    if (rc != Success)
662        return rc;
663    if (SAME_SCREENS(pWin->drawable, pParent->drawable))
664    {
665        if ((pWin->backgroundState == ParentRelative) &&
666            (pParent->drawable.depth != pWin->drawable.depth))
667            return BadMatch;
668	if ((pWin->drawable.class != InputOnly) &&
669	    (pParent->drawable.class == InputOnly))
670	    return BadMatch;
671        result =  ReparentWindow(pWin, pParent,
672			 (short)stuff->x, (short)stuff->y, client);
673	if (client->noClientException != Success)
674            return(client->noClientException);
675	else
676            return(result);
677    }
678    else
679        return (BadMatch);
680}
681
682int
683ProcMapWindow(ClientPtr client)
684{
685    WindowPtr pWin;
686    REQUEST(xResourceReq);
687    int rc;
688
689    REQUEST_SIZE_MATCH(xResourceReq);
690    rc = dixLookupWindow(&pWin, stuff->id, client, DixShowAccess);
691    if (rc != Success)
692        return rc;
693    MapWindow(pWin, client);
694           /* update cache to say it is mapped */
695    return(client->noClientException);
696}
697
698int
699ProcMapSubwindows(ClientPtr client)
700{
701    WindowPtr pWin;
702    REQUEST(xResourceReq);
703    int rc;
704
705    REQUEST_SIZE_MATCH(xResourceReq);
706    rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
707    if (rc != Success)
708        return rc;
709    MapSubwindows(pWin, client);
710           /* update cache to say it is mapped */
711    return(client->noClientException);
712}
713
714int
715ProcUnmapWindow(ClientPtr client)
716{
717    WindowPtr pWin;
718    REQUEST(xResourceReq);
719    int rc;
720
721    REQUEST_SIZE_MATCH(xResourceReq);
722    rc = dixLookupWindow(&pWin, stuff->id, client, DixHideAccess);
723    if (rc != Success)
724        return rc;
725    UnmapWindow(pWin, FALSE);
726           /* update cache to say it is mapped */
727    return(client->noClientException);
728}
729
730int
731ProcUnmapSubwindows(ClientPtr client)
732{
733    WindowPtr pWin;
734    REQUEST(xResourceReq);
735    int rc;
736
737    REQUEST_SIZE_MATCH(xResourceReq);
738    rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
739    if (rc != Success)
740        return rc;
741    UnmapSubwindows(pWin);
742    return(client->noClientException);
743}
744
745int
746ProcConfigureWindow(ClientPtr client)
747{
748    WindowPtr pWin;
749    REQUEST(xConfigureWindowReq);
750    int result;
751    int len, rc;
752
753    REQUEST_AT_LEAST_SIZE(xConfigureWindowReq);
754    rc = dixLookupWindow(&pWin, stuff->window, client,
755			 DixManageAccess|DixSetAttrAccess);
756    if (rc != Success)
757        return rc;
758    len = client->req_len - (sizeof(xConfigureWindowReq) >> 2);
759    if (Ones((Mask)stuff->mask) != len)
760        return BadLength;
761    result =  ConfigureWindow(pWin, (Mask)stuff->mask, (XID *) &stuff[1],
762			      client);
763    if (client->noClientException != Success)
764        return(client->noClientException);
765    else
766        return(result);
767}
768
769int
770ProcCirculateWindow(ClientPtr client)
771{
772    WindowPtr pWin;
773    REQUEST(xCirculateWindowReq);
774    int rc;
775
776    REQUEST_SIZE_MATCH(xCirculateWindowReq);
777    if ((stuff->direction != RaiseLowest) &&
778	(stuff->direction != LowerHighest))
779    {
780	client->errorValue = stuff->direction;
781        return BadValue;
782    }
783    rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
784    if (rc != Success)
785        return rc;
786    CirculateWindow(pWin, (int)stuff->direction, client);
787    return(client->noClientException);
788}
789
790static int
791GetGeometry(ClientPtr client, xGetGeometryReply *rep)
792{
793    DrawablePtr pDraw;
794    int rc;
795    REQUEST(xResourceReq);
796    REQUEST_SIZE_MATCH(xResourceReq);
797
798    rc = dixLookupDrawable(&pDraw, stuff->id, client, M_ANY, DixGetAttrAccess);
799    if (rc != Success)
800	return rc;
801
802    rep->type = X_Reply;
803    rep->length = 0;
804    rep->sequenceNumber = client->sequence;
805    rep->root = WindowTable[pDraw->pScreen->myNum]->drawable.id;
806    rep->depth = pDraw->depth;
807    rep->width = pDraw->width;
808    rep->height = pDraw->height;
809
810    /* XXX - Because the pixmap-implementation of the multibuffer extension
811     *       may have the buffer-id's drawable resource value be a pointer
812     *       to the buffer's window instead of the buffer itself
813     *       (this happens if the buffer is the displayed buffer),
814     *       we also have to check that the id matches before we can
815     *       truly say that it is a DRAWABLE_WINDOW.
816     */
817
818    if ((pDraw->type == UNDRAWABLE_WINDOW) ||
819        ((pDraw->type == DRAWABLE_WINDOW) && (stuff->id == pDraw->id)))
820    {
821        WindowPtr pWin = (WindowPtr)pDraw;
822	rep->x = pWin->origin.x - wBorderWidth (pWin);
823	rep->y = pWin->origin.y - wBorderWidth (pWin);
824	rep->borderWidth = pWin->borderWidth;
825    }
826    else /* DRAWABLE_PIXMAP or DRAWABLE_BUFFER */
827    {
828	rep->x = rep->y = rep->borderWidth = 0;
829    }
830
831    return Success;
832}
833
834
835int
836ProcGetGeometry(ClientPtr client)
837{
838    xGetGeometryReply rep;
839    int status;
840
841    if ((status = GetGeometry(client, &rep)) != Success)
842	return status;
843
844    WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep);
845    return(client->noClientException);
846}
847
848
849int
850ProcQueryTree(ClientPtr client)
851{
852    xQueryTreeReply reply;
853    int rc, numChildren = 0;
854    WindowPtr pChild, pWin, pHead;
855    Window  *childIDs = (Window *)NULL;
856    REQUEST(xResourceReq);
857
858    REQUEST_SIZE_MATCH(xResourceReq);
859    rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
860    if (rc != Success)
861        return rc;
862    reply.type = X_Reply;
863    reply.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
864    reply.sequenceNumber = client->sequence;
865    if (pWin->parent)
866	reply.parent = pWin->parent->drawable.id;
867    else
868        reply.parent = (Window)None;
869    pHead = RealChildHead(pWin);
870    for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib)
871	numChildren++;
872    if (numChildren)
873    {
874	int curChild = 0;
875
876	childIDs = (Window *) xalloc(numChildren * sizeof(Window));
877	if (!childIDs)
878	    return BadAlloc;
879	for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib)
880	    childIDs[curChild++] = pChild->drawable.id;
881    }
882
883    reply.nChildren = numChildren;
884    reply.length = (numChildren * sizeof(Window)) >> 2;
885
886    WriteReplyToClient(client, sizeof(xQueryTreeReply), &reply);
887    if (numChildren)
888    {
889    	client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
890	WriteSwappedDataToClient(client, numChildren * sizeof(Window), childIDs);
891	xfree(childIDs);
892    }
893
894    return(client->noClientException);
895}
896
897int
898ProcInternAtom(ClientPtr client)
899{
900    Atom atom;
901    char *tchar;
902    REQUEST(xInternAtomReq);
903
904    REQUEST_FIXED_SIZE(xInternAtomReq, stuff->nbytes);
905    if ((stuff->onlyIfExists != xTrue) && (stuff->onlyIfExists != xFalse))
906    {
907	client->errorValue = stuff->onlyIfExists;
908        return(BadValue);
909    }
910    tchar = (char *) &stuff[1];
911    atom = MakeAtom(tchar, stuff->nbytes, !stuff->onlyIfExists);
912    if (atom != BAD_RESOURCE)
913    {
914	xInternAtomReply reply;
915	reply.type = X_Reply;
916	reply.length = 0;
917	reply.sequenceNumber = client->sequence;
918	reply.atom = atom;
919	WriteReplyToClient(client, sizeof(xInternAtomReply), &reply);
920	return(client->noClientException);
921    }
922    else
923	return (BadAlloc);
924}
925
926int
927ProcGetAtomName(ClientPtr client)
928{
929    char *str;
930    xGetAtomNameReply reply;
931    int len;
932    REQUEST(xResourceReq);
933
934    REQUEST_SIZE_MATCH(xResourceReq);
935    if ( (str = NameForAtom(stuff->id)) )
936    {
937	len = strlen(str);
938	reply.type = X_Reply;
939	reply.length = (len + 3) >> 2;
940	reply.sequenceNumber = client->sequence;
941	reply.nameLength = len;
942	WriteReplyToClient(client, sizeof(xGetAtomNameReply), &reply);
943	(void)WriteToClient(client, len, str);
944	return(client->noClientException);
945    }
946    else
947    {
948	client->errorValue = stuff->id;
949	return (BadAtom);
950    }
951}
952
953int
954ProcGrabServer(ClientPtr client)
955{
956    int rc;
957    REQUEST_SIZE_MATCH(xReq);
958    if (grabState != GrabNone && client != grabClient)
959    {
960	ResetCurrentRequest(client);
961	client->sequence--;
962	BITSET(grabWaiters, client->index);
963	IgnoreClient(client);
964	return(client->noClientException);
965    }
966    rc = OnlyListenToOneClient(client);
967    if (rc != Success)
968	return rc;
969    grabState = GrabKickout;
970    grabClient = client;
971
972    if (ServerGrabCallback)
973    {
974	ServerGrabInfoRec grabinfo;
975	grabinfo.client = client;
976	grabinfo.grabstate  = SERVER_GRABBED;
977	CallCallbacks(&ServerGrabCallback, (pointer)&grabinfo);
978    }
979
980    return(client->noClientException);
981}
982
983static void
984UngrabServer(ClientPtr client)
985{
986    int i;
987
988    grabState = GrabNone;
989    ListenToAllClients();
990    for (i = mskcnt; --i >= 0 && !grabWaiters[i]; )
991	;
992    if (i >= 0)
993    {
994	i <<= 5;
995	while (!GETBIT(grabWaiters, i))
996	    i++;
997	BITCLEAR(grabWaiters, i);
998	AttendClient(clients[i]);
999    }
1000
1001    if (ServerGrabCallback)
1002    {
1003	ServerGrabInfoRec grabinfo;
1004	grabinfo.client = client;
1005	grabinfo.grabstate  = SERVER_UNGRABBED;
1006	CallCallbacks(&ServerGrabCallback, (pointer)&grabinfo);
1007    }
1008}
1009
1010int
1011ProcUngrabServer(ClientPtr client)
1012{
1013    REQUEST_SIZE_MATCH(xReq);
1014    UngrabServer(client);
1015    return(client->noClientException);
1016}
1017
1018int
1019ProcTranslateCoords(ClientPtr client)
1020{
1021    REQUEST(xTranslateCoordsReq);
1022
1023    WindowPtr pWin, pDst;
1024    xTranslateCoordsReply rep;
1025    int rc;
1026
1027    REQUEST_SIZE_MATCH(xTranslateCoordsReq);
1028    rc = dixLookupWindow(&pWin, stuff->srcWid, client, DixGetAttrAccess);
1029    if (rc != Success)
1030        return rc;
1031    rc = dixLookupWindow(&pDst, stuff->dstWid, client, DixGetAttrAccess);
1032    if (rc != Success)
1033        return rc;
1034    rep.type = X_Reply;
1035    rep.length = 0;
1036    rep.sequenceNumber = client->sequence;
1037    if (!SAME_SCREENS(pWin->drawable, pDst->drawable))
1038    {
1039	rep.sameScreen = xFalse;
1040        rep.child = None;
1041	rep.dstX = rep.dstY = 0;
1042    }
1043    else
1044    {
1045	INT16 x, y;
1046	rep.sameScreen = xTrue;
1047	rep.child = None;
1048	/* computing absolute coordinates -- adjust to destination later */
1049	x = pWin->drawable.x + stuff->srcX;
1050	y = pWin->drawable.y + stuff->srcY;
1051	pWin = pDst->firstChild;
1052	while (pWin)
1053	{
1054	    BoxRec  box;
1055	    if ((pWin->mapped) &&
1056		(x >= pWin->drawable.x - wBorderWidth (pWin)) &&
1057		(x < pWin->drawable.x + (int)pWin->drawable.width +
1058		 wBorderWidth (pWin)) &&
1059		(y >= pWin->drawable.y - wBorderWidth (pWin)) &&
1060		(y < pWin->drawable.y + (int)pWin->drawable.height +
1061		 wBorderWidth (pWin))
1062		/* When a window is shaped, a further check
1063		 * is made to see if the point is inside
1064		 * borderSize
1065		 */
1066		&& (!wBoundingShape(pWin) ||
1067		    POINT_IN_REGION(pWin->drawable.pScreen,
1068					&pWin->borderSize, x, y, &box))
1069
1070		&& (!wInputShape(pWin) ||
1071		    POINT_IN_REGION(pWin->drawable.pScreen,
1072				    wInputShape(pWin),
1073				    x - pWin->drawable.x,
1074				    y - pWin->drawable.y, &box))
1075		)
1076            {
1077		rep.child = pWin->drawable.id;
1078		pWin = (WindowPtr) NULL;
1079	    }
1080	    else
1081		pWin = pWin->nextSib;
1082	}
1083	/* adjust to destination coordinates */
1084	rep.dstX = x - pDst->drawable.x;
1085	rep.dstY = y - pDst->drawable.y;
1086    }
1087    WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep);
1088    return(client->noClientException);
1089}
1090
1091int
1092ProcOpenFont(ClientPtr client)
1093{
1094    int	err;
1095    REQUEST(xOpenFontReq);
1096
1097    REQUEST_FIXED_SIZE(xOpenFontReq, stuff->nbytes);
1098    client->errorValue = stuff->fid;
1099    LEGAL_NEW_RESOURCE(stuff->fid, client);
1100    err = OpenFont(client, stuff->fid, (Mask) 0,
1101		stuff->nbytes, (char *)&stuff[1]);
1102    if (err == Success)
1103    {
1104	return(client->noClientException);
1105    }
1106    else
1107	return err;
1108}
1109
1110int
1111ProcCloseFont(ClientPtr client)
1112{
1113    FontPtr pFont;
1114    REQUEST(xResourceReq);
1115
1116    REQUEST_SIZE_MATCH(xResourceReq);
1117    pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT,
1118					    DixDestroyAccess);
1119    if ( pFont != (FontPtr)NULL)	/* id was valid */
1120    {
1121        FreeResource(stuff->id, RT_NONE);
1122	return(client->noClientException);
1123    }
1124    else
1125    {
1126	client->errorValue = stuff->id;
1127        return (BadFont);
1128    }
1129}
1130
1131int
1132ProcQueryFont(ClientPtr client)
1133{
1134    xQueryFontReply	*reply;
1135    FontPtr pFont;
1136    GC *pGC;
1137    int rc;
1138    REQUEST(xResourceReq);
1139    REQUEST_SIZE_MATCH(xResourceReq);
1140
1141    client->errorValue = stuff->id;		/* EITHER font or gc */
1142    rc = dixLookupResourceByType((pointer *)&pFont, stuff->id, RT_FONT, client,
1143				 DixGetAttrAccess);
1144    if (rc == BadValue) {
1145	rc = dixLookupResourceByType((pointer *)&pGC, stuff->id, RT_GC, client,
1146				     DixGetAttrAccess);
1147	if (rc == Success)
1148	    pFont = pGC->font;
1149    }
1150    if (rc != Success)
1151	return (rc == BadValue) ? BadFont: rc;
1152
1153    {
1154	xCharInfo	*pmax = FONTINKMAX(pFont);
1155	xCharInfo	*pmin = FONTINKMIN(pFont);
1156	int		nprotoxcistructs;
1157	int		rlength;
1158
1159	nprotoxcistructs = (
1160	   pmax->rightSideBearing == pmin->rightSideBearing &&
1161	   pmax->leftSideBearing == pmin->leftSideBearing &&
1162	   pmax->descent == pmin->descent &&
1163	   pmax->ascent == pmin->ascent &&
1164	   pmax->characterWidth == pmin->characterWidth) ?
1165		0 : N2dChars(pFont);
1166
1167	rlength = sizeof(xQueryFontReply) +
1168	             FONTINFONPROPS(FONTCHARSET(pFont)) * sizeof(xFontProp)  +
1169		     nprotoxcistructs * sizeof(xCharInfo);
1170	reply = (xQueryFontReply *)xalloc(rlength);
1171	if(!reply)
1172	{
1173	    return(BadAlloc);
1174	}
1175
1176	reply->type = X_Reply;
1177	reply->length = (rlength - sizeof(xGenericReply)) >> 2;
1178	reply->sequenceNumber = client->sequence;
1179	QueryFont( pFont, reply, nprotoxcistructs);
1180
1181        WriteReplyToClient(client, rlength, reply);
1182	xfree(reply);
1183	return(client->noClientException);
1184    }
1185}
1186
1187int
1188ProcQueryTextExtents(ClientPtr client)
1189{
1190    xQueryTextExtentsReply reply;
1191    FontPtr pFont;
1192    GC *pGC;
1193    ExtentInfoRec info;
1194    unsigned long length;
1195    int rc;
1196    REQUEST(xQueryTextExtentsReq);
1197    REQUEST_AT_LEAST_SIZE(xQueryTextExtentsReq);
1198
1199    client->errorValue = stuff->fid;		/* EITHER font or gc */
1200    rc = dixLookupResourceByType((pointer *)&pFont, stuff->fid, RT_FONT, client,
1201				 DixGetAttrAccess);
1202    if (rc == BadValue) {
1203	rc = dixLookupResourceByType((pointer *)&pGC, stuff->fid, RT_GC, client,
1204			       DixGetAttrAccess);
1205	if (rc == Success)
1206	    pFont = pGC->font;
1207    }
1208    if (rc != Success)
1209	return (rc == BadValue) ? BadFont: rc;
1210
1211    length = client->req_len - (sizeof(xQueryTextExtentsReq) >> 2);
1212    length = length << 1;
1213    if (stuff->oddLength)
1214    {
1215	if (length == 0)
1216	    return(BadLength);
1217        length--;
1218    }
1219    if (!QueryTextExtents(pFont, length, (unsigned char *)&stuff[1], &info))
1220	return(BadAlloc);
1221    reply.type = X_Reply;
1222    reply.length = 0;
1223    reply.sequenceNumber = client->sequence;
1224    reply.drawDirection = info.drawDirection;
1225    reply.fontAscent = info.fontAscent;
1226    reply.fontDescent = info.fontDescent;
1227    reply.overallAscent = info.overallAscent;
1228    reply.overallDescent = info.overallDescent;
1229    reply.overallWidth = info.overallWidth;
1230    reply.overallLeft = info.overallLeft;
1231    reply.overallRight = info.overallRight;
1232    WriteReplyToClient(client, sizeof(xQueryTextExtentsReply), &reply);
1233    return(client->noClientException);
1234}
1235
1236int
1237ProcListFonts(ClientPtr client)
1238{
1239    REQUEST(xListFontsReq);
1240
1241    REQUEST_FIXED_SIZE(xListFontsReq, stuff->nbytes);
1242
1243    return ListFonts(client, (unsigned char *) &stuff[1], stuff->nbytes,
1244	stuff->maxNames);
1245}
1246
1247int
1248ProcListFontsWithInfo(ClientPtr client)
1249{
1250    REQUEST(xListFontsWithInfoReq);
1251
1252    REQUEST_FIXED_SIZE(xListFontsWithInfoReq, stuff->nbytes);
1253
1254    return StartListFontsWithInfo(client, stuff->nbytes,
1255				  (unsigned char *) &stuff[1], stuff->maxNames);
1256}
1257
1258/**
1259 *
1260 *  \param value must conform to DeleteType
1261 */
1262int
1263dixDestroyPixmap(pointer value, XID pid)
1264{
1265    PixmapPtr pPixmap = (PixmapPtr)value;
1266    return (*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap);
1267}
1268
1269int
1270ProcCreatePixmap(ClientPtr client)
1271{
1272    PixmapPtr pMap;
1273    DrawablePtr pDraw;
1274    REQUEST(xCreatePixmapReq);
1275    DepthPtr pDepth;
1276    int i, rc;
1277
1278    REQUEST_SIZE_MATCH(xCreatePixmapReq);
1279    client->errorValue = stuff->pid;
1280    LEGAL_NEW_RESOURCE(stuff->pid, client);
1281
1282    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
1283			   DixGetAttrAccess);
1284    if (rc != Success)
1285	return rc;
1286
1287    if (!stuff->width || !stuff->height)
1288    {
1289	client->errorValue = 0;
1290        return BadValue;
1291    }
1292    if (stuff->width > 32767 || stuff->height > 32767)
1293    {
1294	/* It is allowed to try and allocate a pixmap which is larger than
1295	 * 32767 in either dimension. However, all of the framebuffer code
1296	 * is buggy and does not reliably draw to such big pixmaps, basically
1297	 * because the Region data structure operates with signed shorts
1298	 * for the rectangles in it.
1299	 *
1300	 * Furthermore, several places in the X server computes the
1301	 * size in bytes of the pixmap and tries to store it in an
1302	 * integer. This integer can overflow and cause the allocated size
1303	 * to be much smaller.
1304	 *
1305	 * So, such big pixmaps are rejected here with a BadAlloc
1306	 */
1307	return BadAlloc;
1308    }
1309    if (stuff->depth != 1)
1310    {
1311        pDepth = pDraw->pScreen->allowedDepths;
1312        for (i=0; i<pDraw->pScreen->numDepths; i++, pDepth++)
1313	   if (pDepth->depth == stuff->depth)
1314               goto CreatePmap;
1315	client->errorValue = stuff->depth;
1316        return BadValue;
1317    }
1318CreatePmap:
1319    pMap = (PixmapPtr)(*pDraw->pScreen->CreatePixmap)
1320		(pDraw->pScreen, stuff->width,
1321		 stuff->height, stuff->depth, 0);
1322    if (pMap)
1323    {
1324	pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
1325	pMap->drawable.id = stuff->pid;
1326	/* security creation/labeling check */
1327	rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, RT_PIXMAP,
1328		      pMap, RT_NONE, NULL, DixCreateAccess);
1329	if (rc != Success) {
1330	    (*pDraw->pScreen->DestroyPixmap)(pMap);
1331	    return rc;
1332	}
1333	if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap))
1334	    return(client->noClientException);
1335	(*pDraw->pScreen->DestroyPixmap)(pMap);
1336    }
1337    return (BadAlloc);
1338}
1339
1340int
1341ProcFreePixmap(ClientPtr client)
1342{
1343    PixmapPtr pMap;
1344    int rc;
1345    REQUEST(xResourceReq);
1346    REQUEST_SIZE_MATCH(xResourceReq);
1347
1348    rc = dixLookupResourceByType((pointer *)&pMap, stuff->id, RT_PIXMAP, client,
1349			   DixDestroyAccess);
1350    if (rc == Success)
1351    {
1352	FreeResource(stuff->id, RT_NONE);
1353	return(client->noClientException);
1354    }
1355    else
1356    {
1357	client->errorValue = stuff->id;
1358	return (rc == BadValue) ? BadPixmap : rc;
1359    }
1360}
1361
1362int
1363ProcCreateGC(ClientPtr client)
1364{
1365    int error, rc;
1366    GC *pGC;
1367    DrawablePtr pDraw;
1368    unsigned len;
1369    REQUEST(xCreateGCReq);
1370
1371    REQUEST_AT_LEAST_SIZE(xCreateGCReq);
1372    client->errorValue = stuff->gc;
1373    LEGAL_NEW_RESOURCE(stuff->gc, client);
1374    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
1375			   DixGetAttrAccess);
1376    if (rc != Success)
1377	return rc;
1378
1379    len = client->req_len -  (sizeof(xCreateGCReq) >> 2);
1380    if (len != Ones(stuff->mask))
1381        return BadLength;
1382    pGC = (GC *)CreateGC(pDraw, stuff->mask, (XID *) &stuff[1], &error,
1383			 stuff->gc, client);
1384    if (error != Success)
1385        return error;
1386    if (!AddResource(stuff->gc, RT_GC, (pointer)pGC))
1387	return (BadAlloc);
1388    return(client->noClientException);
1389}
1390
1391int
1392ProcChangeGC(ClientPtr client)
1393{
1394    GC *pGC;
1395    int result;
1396    unsigned len;
1397    REQUEST(xChangeGCReq);
1398    REQUEST_AT_LEAST_SIZE(xChangeGCReq);
1399
1400    result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess);
1401    if (result != Success)
1402	return result;
1403
1404    len = client->req_len -  (sizeof(xChangeGCReq) >> 2);
1405    if (len != Ones(stuff->mask))
1406        return BadLength;
1407
1408    result = dixChangeGC(client, pGC, stuff->mask, (CARD32 *) &stuff[1], 0);
1409    if (client->noClientException != Success)
1410        return(client->noClientException);
1411    else
1412    {
1413	client->errorValue = clientErrorValue;
1414        return(result);
1415    }
1416}
1417
1418int
1419ProcCopyGC(ClientPtr client)
1420{
1421    GC *dstGC;
1422    GC *pGC;
1423    int result;
1424    REQUEST(xCopyGCReq);
1425    REQUEST_SIZE_MATCH(xCopyGCReq);
1426
1427    result = dixLookupGC(&pGC, stuff->srcGC, client, DixGetAttrAccess);
1428    if (result != Success)
1429	return result;
1430    result = dixLookupGC(&dstGC, stuff->dstGC, client, DixSetAttrAccess);
1431    if (result != Success)
1432	return result;
1433    if ((dstGC->pScreen != pGC->pScreen) || (dstGC->depth != pGC->depth))
1434        return (BadMatch);
1435    result = CopyGC(pGC, dstGC, stuff->mask);
1436    if (client->noClientException != Success)
1437        return(client->noClientException);
1438    else
1439    {
1440	client->errorValue = clientErrorValue;
1441        return(result);
1442    }
1443}
1444
1445int
1446ProcSetDashes(ClientPtr client)
1447{
1448    GC *pGC;
1449    int result;
1450    REQUEST(xSetDashesReq);
1451
1452    REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes);
1453    if (stuff->nDashes == 0)
1454    {
1455	 client->errorValue = 0;
1456         return BadValue;
1457    }
1458
1459    result = dixLookupGC(&pGC,stuff->gc, client, DixSetAttrAccess);
1460    if (result != Success)
1461	return result;
1462
1463    result = SetDashes(pGC, stuff->dashOffset, stuff->nDashes,
1464		       (unsigned char *)&stuff[1]);
1465    if (client->noClientException != Success)
1466        return(client->noClientException);
1467    else
1468    {
1469	client->errorValue = clientErrorValue;
1470        return(result);
1471    }
1472}
1473
1474int
1475ProcSetClipRectangles(ClientPtr client)
1476{
1477    int	nr, result;
1478    GC *pGC;
1479    REQUEST(xSetClipRectanglesReq);
1480
1481    REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq);
1482    if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) &&
1483	(stuff->ordering != YXSorted) && (stuff->ordering != YXBanded))
1484    {
1485	client->errorValue = stuff->ordering;
1486        return BadValue;
1487    }
1488    result = dixLookupGC(&pGC,stuff->gc, client, DixSetAttrAccess);
1489    if (result != Success)
1490	return result;
1491
1492    nr = (client->req_len << 2) - sizeof(xSetClipRectanglesReq);
1493    if (nr & 4)
1494	return(BadLength);
1495    nr >>= 3;
1496    result = SetClipRects(pGC, stuff->xOrigin, stuff->yOrigin,
1497			  nr, (xRectangle *)&stuff[1], (int)stuff->ordering);
1498    if (client->noClientException != Success)
1499        return(client->noClientException);
1500    else
1501        return(result);
1502}
1503
1504int
1505ProcFreeGC(ClientPtr client)
1506{
1507    GC *pGC;
1508    int rc;
1509    REQUEST(xResourceReq);
1510    REQUEST_SIZE_MATCH(xResourceReq);
1511
1512    rc = dixLookupGC(&pGC, stuff->id, client, DixDestroyAccess);
1513    if (rc != Success)
1514	return rc;
1515
1516    FreeResource(stuff->id, RT_NONE);
1517    return(client->noClientException);
1518}
1519
1520int
1521ProcClearToBackground(ClientPtr client)
1522{
1523    REQUEST(xClearAreaReq);
1524    WindowPtr pWin;
1525    int rc;
1526
1527    REQUEST_SIZE_MATCH(xClearAreaReq);
1528    rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess);
1529    if (rc != Success)
1530        return rc;
1531    if (pWin->drawable.class == InputOnly)
1532    {
1533	client->errorValue = stuff->window;
1534	return (BadMatch);
1535    }
1536    if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse))
1537    {
1538	client->errorValue = stuff->exposures;
1539        return(BadValue);
1540    }
1541    (*pWin->drawable.pScreen->ClearToBackground)(pWin, stuff->x, stuff->y,
1542			       stuff->width, stuff->height,
1543			       (Bool)stuff->exposures);
1544    return(client->noClientException);
1545}
1546
1547int
1548ProcCopyArea(ClientPtr client)
1549{
1550    DrawablePtr pDst;
1551    DrawablePtr pSrc;
1552    GC *pGC;
1553    REQUEST(xCopyAreaReq);
1554    RegionPtr pRgn;
1555    int rc;
1556
1557    REQUEST_SIZE_MATCH(xCopyAreaReq);
1558
1559    VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, DixWriteAccess);
1560    if (stuff->dstDrawable != stuff->srcDrawable)
1561    {
1562	rc = dixLookupDrawable(&pSrc, stuff->srcDrawable, client, 0,
1563				 DixReadAccess);
1564	if (rc != Success)
1565	    return rc;
1566	if ((pDst->pScreen != pSrc->pScreen) || (pDst->depth != pSrc->depth))
1567	{
1568	    client->errorValue = stuff->dstDrawable;
1569	    return (BadMatch);
1570	}
1571    }
1572    else
1573        pSrc = pDst;
1574
1575    pRgn = (*pGC->ops->CopyArea)(pSrc, pDst, pGC, stuff->srcX, stuff->srcY,
1576				 stuff->width, stuff->height,
1577				 stuff->dstX, stuff->dstY);
1578    if (pGC->graphicsExposures)
1579    {
1580	(*pDst->pScreen->SendGraphicsExpose)
1581 		(client, pRgn, stuff->dstDrawable, X_CopyArea, 0);
1582	if (pRgn)
1583	    REGION_DESTROY(pDst->pScreen, pRgn);
1584    }
1585
1586    return(client->noClientException);
1587}
1588
1589int
1590ProcCopyPlane(ClientPtr client)
1591{
1592    DrawablePtr psrcDraw, pdstDraw;
1593    GC *pGC;
1594    REQUEST(xCopyPlaneReq);
1595    RegionPtr pRgn;
1596    int rc;
1597
1598    REQUEST_SIZE_MATCH(xCopyPlaneReq);
1599
1600    VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pdstDraw, DixWriteAccess);
1601    if (stuff->dstDrawable != stuff->srcDrawable)
1602    {
1603	rc = dixLookupDrawable(&psrcDraw, stuff->srcDrawable, client, 0,
1604			       DixReadAccess);
1605	if (rc != Success)
1606	    return rc;
1607
1608	if (pdstDraw->pScreen != psrcDraw->pScreen)
1609	{
1610	    client->errorValue = stuff->dstDrawable;
1611	    return (BadMatch);
1612	}
1613    }
1614    else
1615        psrcDraw = pdstDraw;
1616
1617    /* Check to see if stuff->bitPlane has exactly ONE good bit set */
1618    if(stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) ||
1619       (stuff->bitPlane > (1L << (psrcDraw->depth - 1))))
1620    {
1621       client->errorValue = stuff->bitPlane;
1622       return(BadValue);
1623    }
1624
1625    pRgn = (*pGC->ops->CopyPlane)(psrcDraw, pdstDraw, pGC, stuff->srcX, stuff->srcY,
1626				 stuff->width, stuff->height,
1627				 stuff->dstX, stuff->dstY, stuff->bitPlane);
1628    if (pGC->graphicsExposures)
1629    {
1630	(*pdstDraw->pScreen->SendGraphicsExpose)
1631 		(client, pRgn, stuff->dstDrawable, X_CopyPlane, 0);
1632	if (pRgn)
1633	    REGION_DESTROY(pdstDraw->pScreen, pRgn);
1634    }
1635    return(client->noClientException);
1636}
1637
1638int
1639ProcPolyPoint(ClientPtr client)
1640{
1641    int npoint;
1642    GC *pGC;
1643    DrawablePtr pDraw;
1644    REQUEST(xPolyPointReq);
1645
1646    REQUEST_AT_LEAST_SIZE(xPolyPointReq);
1647    if ((stuff->coordMode != CoordModeOrigin) &&
1648	(stuff->coordMode != CoordModePrevious))
1649    {
1650	client->errorValue = stuff->coordMode;
1651        return BadValue;
1652    }
1653    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
1654    npoint = ((client->req_len << 2) - sizeof(xPolyPointReq)) >> 2;
1655    if (npoint)
1656        (*pGC->ops->PolyPoint)(pDraw, pGC, stuff->coordMode, npoint,
1657			  (xPoint *) &stuff[1]);
1658    return (client->noClientException);
1659}
1660
1661int
1662ProcPolyLine(ClientPtr client)
1663{
1664    int npoint;
1665    GC *pGC;
1666    DrawablePtr pDraw;
1667    REQUEST(xPolyLineReq);
1668
1669    REQUEST_AT_LEAST_SIZE(xPolyLineReq);
1670    if ((stuff->coordMode != CoordModeOrigin) &&
1671	(stuff->coordMode != CoordModePrevious))
1672    {
1673	client->errorValue = stuff->coordMode;
1674        return BadValue;
1675    }
1676    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
1677    npoint = ((client->req_len << 2) - sizeof(xPolyLineReq)) >> 2;
1678    if (npoint > 1)
1679	(*pGC->ops->Polylines)(pDraw, pGC, stuff->coordMode, npoint,
1680			      (DDXPointPtr) &stuff[1]);
1681    return(client->noClientException);
1682}
1683
1684int
1685ProcPolySegment(ClientPtr client)
1686{
1687    int nsegs;
1688    GC *pGC;
1689    DrawablePtr pDraw;
1690    REQUEST(xPolySegmentReq);
1691
1692    REQUEST_AT_LEAST_SIZE(xPolySegmentReq);
1693    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
1694    nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq);
1695    if (nsegs & 4)
1696	return(BadLength);
1697    nsegs >>= 3;
1698    if (nsegs)
1699        (*pGC->ops->PolySegment)(pDraw, pGC, nsegs, (xSegment *) &stuff[1]);
1700    return (client->noClientException);
1701}
1702
1703int
1704ProcPolyRectangle (ClientPtr client)
1705{
1706    int nrects;
1707    GC *pGC;
1708    DrawablePtr pDraw;
1709    REQUEST(xPolyRectangleReq);
1710
1711    REQUEST_AT_LEAST_SIZE(xPolyRectangleReq);
1712    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
1713    nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq);
1714    if (nrects & 4)
1715	return(BadLength);
1716    nrects >>= 3;
1717    if (nrects)
1718        (*pGC->ops->PolyRectangle)(pDraw, pGC,
1719		    nrects, (xRectangle *) &stuff[1]);
1720    return(client->noClientException);
1721}
1722
1723int
1724ProcPolyArc(ClientPtr client)
1725{
1726    int		narcs;
1727    GC *pGC;
1728    DrawablePtr pDraw;
1729    REQUEST(xPolyArcReq);
1730
1731    REQUEST_AT_LEAST_SIZE(xPolyArcReq);
1732    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
1733    narcs = (client->req_len << 2) - sizeof(xPolyArcReq);
1734    if (narcs % sizeof(xArc))
1735	return(BadLength);
1736    narcs /= sizeof(xArc);
1737    if (narcs)
1738        (*pGC->ops->PolyArc)(pDraw, pGC, narcs, (xArc *) &stuff[1]);
1739    return (client->noClientException);
1740}
1741
1742int
1743ProcFillPoly(ClientPtr client)
1744{
1745    int          things;
1746    GC *pGC;
1747    DrawablePtr pDraw;
1748    REQUEST(xFillPolyReq);
1749
1750    REQUEST_AT_LEAST_SIZE(xFillPolyReq);
1751    if ((stuff->shape != Complex) && (stuff->shape != Nonconvex) &&
1752	(stuff->shape != Convex))
1753    {
1754	client->errorValue = stuff->shape;
1755        return BadValue;
1756    }
1757    if ((stuff->coordMode != CoordModeOrigin) &&
1758	(stuff->coordMode != CoordModePrevious))
1759    {
1760	client->errorValue = stuff->coordMode;
1761        return BadValue;
1762    }
1763
1764    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
1765    things = ((client->req_len << 2) - sizeof(xFillPolyReq)) >> 2;
1766    if (things)
1767        (*pGC->ops->FillPolygon) (pDraw, pGC, stuff->shape,
1768			 stuff->coordMode, things,
1769			 (DDXPointPtr) &stuff[1]);
1770    return(client->noClientException);
1771}
1772
1773int
1774ProcPolyFillRectangle(ClientPtr client)
1775{
1776    int             things;
1777    GC *pGC;
1778    DrawablePtr pDraw;
1779    REQUEST(xPolyFillRectangleReq);
1780
1781    REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq);
1782    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
1783    things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq);
1784    if (things & 4)
1785	return(BadLength);
1786    things >>= 3;
1787
1788    if (things)
1789        (*pGC->ops->PolyFillRect) (pDraw, pGC, things,
1790		      (xRectangle *) &stuff[1]);
1791    return (client->noClientException);
1792}
1793
1794int
1795ProcPolyFillArc(ClientPtr client)
1796{
1797    int		narcs;
1798    GC *pGC;
1799    DrawablePtr pDraw;
1800    REQUEST(xPolyFillArcReq);
1801
1802    REQUEST_AT_LEAST_SIZE(xPolyFillArcReq);
1803    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
1804    narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq);
1805    if (narcs % sizeof(xArc))
1806	return(BadLength);
1807    narcs /= sizeof(xArc);
1808    if (narcs)
1809        (*pGC->ops->PolyFillArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]);
1810    return (client->noClientException);
1811}
1812
1813#ifdef MATCH_CLIENT_ENDIAN
1814
1815int
1816ServerOrder (void)
1817{
1818    int	    whichbyte = 1;
1819
1820    if (*((char *) &whichbyte))
1821	return LSBFirst;
1822    return MSBFirst;
1823}
1824
1825#define ClientOrder(client) ((client)->swapped ? !ServerOrder() : ServerOrder())
1826
1827void
1828ReformatImage (char *base, int nbytes, int bpp, int order)
1829{
1830    switch (bpp) {
1831    case 1:	/* yuck */
1832	if (BITMAP_BIT_ORDER != order)
1833	    BitOrderInvert ((unsigned char *) base, nbytes);
1834#if IMAGE_BYTE_ORDER != BITMAP_BIT_ORDER && BITMAP_SCANLINE_UNIT != 8
1835	ReformatImage (base, nbytes, BITMAP_SCANLINE_UNIT, order);
1836#endif
1837	break;
1838    case 4:
1839	break;  /* yuck */
1840    case 8:
1841	break;
1842    case 16:
1843	if (IMAGE_BYTE_ORDER != order)
1844	    TwoByteSwap ((unsigned char *) base, nbytes);
1845	break;
1846    case 32:
1847	if (IMAGE_BYTE_ORDER != order)
1848	    FourByteSwap ((unsigned char *) base, nbytes);
1849	break;
1850    }
1851}
1852#else
1853#define ReformatImage(b,n,bpp,o)
1854#endif
1855
1856/* 64-bit server notes: the protocol restricts padding of images to
1857 * 8-, 16-, or 32-bits. We would like to have 64-bits for the server
1858 * to use internally. Removes need for internal alignment checking.
1859 * All of the PutImage functions could be changed individually, but
1860 * as currently written, they call other routines which require things
1861 * to be 64-bit padded on scanlines, so we changed things here.
1862 * If an image would be padded differently for 64- versus 32-, then
1863 * copy each scanline to a 64-bit padded scanline.
1864 * Also, we need to make sure that the image is aligned on a 64-bit
1865 * boundary, even if the scanlines are padded to our satisfaction.
1866 */
1867int
1868ProcPutImage(ClientPtr client)
1869{
1870    GC *pGC;
1871    DrawablePtr pDraw;
1872    long	length; 	/* length of scanline server padded */
1873    long 	lengthProto; 	/* length of scanline protocol padded */
1874    char	*tmpImage;
1875    REQUEST(xPutImageReq);
1876
1877    REQUEST_AT_LEAST_SIZE(xPutImageReq);
1878    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
1879    if (stuff->format == XYBitmap)
1880    {
1881        if ((stuff->depth != 1) ||
1882	    (stuff->leftPad >= (unsigned int)screenInfo.bitmapScanlinePad))
1883            return BadMatch;
1884        length 	    = BitmapBytePad(stuff->width + stuff->leftPad);
1885    }
1886    else if (stuff->format == XYPixmap)
1887    {
1888        if ((pDraw->depth != stuff->depth) ||
1889	    (stuff->leftPad >= (unsigned int)screenInfo.bitmapScanlinePad))
1890            return BadMatch;
1891        length      = BitmapBytePad(stuff->width + stuff->leftPad);
1892	length      *= stuff->depth;
1893    }
1894    else if (stuff->format == ZPixmap)
1895    {
1896        if ((pDraw->depth != stuff->depth) || (stuff->leftPad != 0))
1897            return BadMatch;
1898        length      = PixmapBytePad(stuff->width, stuff->depth);
1899    }
1900    else
1901    {
1902	client->errorValue = stuff->format;
1903        return BadValue;
1904    }
1905
1906    tmpImage = (char *)&stuff[1];
1907    lengthProto = length;
1908
1909    if (((((lengthProto * stuff->height) + (unsigned)3) >> 2) +
1910	(sizeof(xPutImageReq) >> 2)) != client->req_len)
1911	return BadLength;
1912
1913    ReformatImage (tmpImage, lengthProto * stuff->height,
1914		   stuff->format == ZPixmap ? BitsPerPixel (stuff->depth) : 1,
1915		   ClientOrder(client));
1916
1917    (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, stuff->dstX, stuff->dstY,
1918		  stuff->width, stuff->height,
1919		  stuff->leftPad, stuff->format, tmpImage);
1920
1921     return (client->noClientException);
1922}
1923
1924static int
1925DoGetImage(ClientPtr client, int format, Drawable drawable,
1926           int x, int y, int width, int height,
1927           Mask planemask, xGetImageReply **im_return)
1928{
1929    DrawablePtr		pDraw;
1930    int			nlines, linesPerBuf, rc;
1931    int	linesDone;
1932    long		widthBytesLine, length;
1933    Mask		plane = 0;
1934    char		*pBuf;
1935    xGetImageReply	xgi;
1936    RegionPtr pVisibleRegion = NULL;
1937
1938    if ((format != XYPixmap) && (format != ZPixmap))
1939    {
1940	client->errorValue = format;
1941        return(BadValue);
1942    }
1943    rc = dixLookupDrawable(&pDraw, drawable, client, 0, DixReadAccess);
1944    if (rc != Success)
1945	return rc;
1946
1947    if(pDraw->type == DRAWABLE_WINDOW)
1948    {
1949      if( /* check for being viewable */
1950	 !((WindowPtr) pDraw)->realized ||
1951	  /* check for being on screen */
1952         pDraw->x + x < 0 ||
1953 	 pDraw->x + x + width > pDraw->pScreen->width ||
1954         pDraw->y + y < 0 ||
1955         pDraw->y + y + height > pDraw->pScreen->height ||
1956          /* check for being inside of border */
1957         x < - wBorderWidth((WindowPtr)pDraw) ||
1958         x + width > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width ||
1959         y < -wBorderWidth((WindowPtr)pDraw) ||
1960         y + height > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height
1961        )
1962	    return(BadMatch);
1963	xgi.visual = wVisual (((WindowPtr) pDraw));
1964    }
1965    else
1966    {
1967      if(x < 0 ||
1968         x+width > (int)pDraw->width ||
1969         y < 0 ||
1970         y+height > (int)pDraw->height
1971        )
1972	    return(BadMatch);
1973	xgi.visual = None;
1974    }
1975
1976    xgi.type = X_Reply;
1977    xgi.sequenceNumber = client->sequence;
1978    xgi.depth = pDraw->depth;
1979    if(format == ZPixmap)
1980    {
1981	widthBytesLine = PixmapBytePad(width, pDraw->depth);
1982	length = widthBytesLine * height;
1983
1984    }
1985    else
1986    {
1987	widthBytesLine = BitmapBytePad(width);
1988	plane = ((Mask)1) << (pDraw->depth - 1);
1989	/* only planes asked for */
1990	length = widthBytesLine * height *
1991		 Ones(planemask & (plane | (plane - 1)));
1992
1993    }
1994
1995    xgi.length = length;
1996
1997    if (im_return) {
1998	pBuf = (char *)xalloc(sz_xGetImageReply + length);
1999	if (!pBuf)
2000	    return (BadAlloc);
2001	if (widthBytesLine == 0)
2002	    linesPerBuf = 0;
2003	else
2004	    linesPerBuf = height;
2005	*im_return = (xGetImageReply *)pBuf;
2006	*(xGetImageReply *)pBuf = xgi;
2007	pBuf += sz_xGetImageReply;
2008    } else {
2009	xgi.length = (xgi.length + 3) >> 2;
2010	if (widthBytesLine == 0 || height == 0)
2011	    linesPerBuf = 0;
2012	else if (widthBytesLine >= IMAGE_BUFSIZE)
2013	    linesPerBuf = 1;
2014	else
2015	{
2016	    linesPerBuf = IMAGE_BUFSIZE / widthBytesLine;
2017	    if (linesPerBuf > height)
2018		linesPerBuf = height;
2019	}
2020	length = linesPerBuf * widthBytesLine;
2021	if (linesPerBuf < height)
2022	{
2023	    /* we have to make sure intermediate buffers don't need padding */
2024	    while ((linesPerBuf > 1) &&
2025		   (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD)-1)))
2026	    {
2027		linesPerBuf--;
2028		length -= widthBytesLine;
2029	    }
2030	    while (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD)-1))
2031	    {
2032		linesPerBuf++;
2033		length += widthBytesLine;
2034	    }
2035	}
2036	if(!(pBuf = (char *) xalloc(length)))
2037	    return (BadAlloc);
2038	WriteReplyToClient(client, sizeof (xGetImageReply), &xgi);
2039    }
2040
2041    if (pDraw->type == DRAWABLE_WINDOW)
2042    {
2043	pVisibleRegion = NotClippedByChildren((WindowPtr)pDraw);
2044	if (pVisibleRegion)
2045	{
2046	    REGION_TRANSLATE(pDraw->pScreen, pVisibleRegion,
2047			     -pDraw->x, -pDraw->y);
2048	}
2049    }
2050
2051    if (linesPerBuf == 0)
2052    {
2053	/* nothing to do */
2054    }
2055    else if (format == ZPixmap)
2056    {
2057        linesDone = 0;
2058        while (height - linesDone > 0)
2059        {
2060	    nlines = min(linesPerBuf, height - linesDone);
2061	    (*pDraw->pScreen->GetImage) (pDraw,
2062	                                 x,
2063				         y + linesDone,
2064				         width,
2065				         nlines,
2066				         format,
2067				         planemask,
2068				         (pointer) pBuf);
2069	    if (pVisibleRegion)
2070		XaceCensorImage(client, pVisibleRegion, widthBytesLine,
2071			pDraw, x, y + linesDone, width,
2072			nlines, format, pBuf);
2073
2074	    /* Note that this is NOT a call to WriteSwappedDataToClient,
2075               as we do NOT byte swap */
2076	    if (!im_return)
2077	    {
2078		ReformatImage (pBuf, (int)(nlines * widthBytesLine),
2079			       BitsPerPixel (pDraw->depth),
2080			       ClientOrder(client));
2081
2082/* Don't split me, gcc pukes when you do */
2083		(void)WriteToClient(client,
2084				    (int)(nlines * widthBytesLine),
2085				    pBuf);
2086	    }
2087	    linesDone += nlines;
2088        }
2089    }
2090    else /* XYPixmap */
2091    {
2092        for (; plane; plane >>= 1)
2093	{
2094	    if (planemask & plane)
2095	    {
2096	        linesDone = 0;
2097	        while (height - linesDone > 0)
2098	        {
2099		    nlines = min(linesPerBuf, height - linesDone);
2100	            (*pDraw->pScreen->GetImage) (pDraw,
2101	                                         x,
2102				                 y + linesDone,
2103				                 width,
2104				                 nlines,
2105				                 format,
2106				                 plane,
2107				                 (pointer)pBuf);
2108		    if (pVisibleRegion)
2109			XaceCensorImage(client, pVisibleRegion,
2110				widthBytesLine,
2111				pDraw, x, y + linesDone, width,
2112				nlines, format, pBuf);
2113
2114		    /* Note: NOT a call to WriteSwappedDataToClient,
2115		       as we do NOT byte swap */
2116		    if (im_return) {
2117			pBuf += nlines * widthBytesLine;
2118		    } else {
2119			ReformatImage (pBuf,
2120				       (int)(nlines * widthBytesLine),
2121				       1,
2122				       ClientOrder (client));
2123
2124/* Don't split me, gcc pukes when you do */
2125			(void)WriteToClient(client,
2126					(int)(nlines * widthBytesLine),
2127					pBuf);
2128		    }
2129		    linesDone += nlines;
2130		}
2131            }
2132	}
2133    }
2134    if (pVisibleRegion)
2135	REGION_DESTROY(pDraw->pScreen, pVisibleRegion);
2136    if (!im_return)
2137	xfree(pBuf);
2138    return (client->noClientException);
2139}
2140
2141int
2142ProcGetImage(ClientPtr client)
2143{
2144    REQUEST(xGetImageReq);
2145
2146    REQUEST_SIZE_MATCH(xGetImageReq);
2147
2148    return DoGetImage(client, stuff->format, stuff->drawable,
2149		      stuff->x, stuff->y,
2150		      (int)stuff->width, (int)stuff->height,
2151		      stuff->planeMask, (xGetImageReply **)NULL);
2152}
2153
2154int
2155ProcPolyText(ClientPtr client)
2156{
2157    int	err;
2158    REQUEST(xPolyTextReq);
2159    DrawablePtr pDraw;
2160    GC *pGC;
2161
2162    REQUEST_AT_LEAST_SIZE(xPolyTextReq);
2163    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
2164
2165    err = PolyText(client,
2166		   pDraw,
2167		   pGC,
2168		   (unsigned char *)&stuff[1],
2169		   ((unsigned char *) stuff) + (client->req_len << 2),
2170		   stuff->x,
2171		   stuff->y,
2172		   stuff->reqType,
2173		   stuff->drawable);
2174
2175    if (err == Success)
2176    {
2177	return(client->noClientException);
2178    }
2179    else
2180	return err;
2181}
2182
2183int
2184ProcImageText8(ClientPtr client)
2185{
2186    int	err;
2187    DrawablePtr pDraw;
2188    GC *pGC;
2189
2190    REQUEST(xImageTextReq);
2191
2192    REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars);
2193    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
2194
2195    err = ImageText(client,
2196		    pDraw,
2197		    pGC,
2198		    stuff->nChars,
2199		    (unsigned char *)&stuff[1],
2200		    stuff->x,
2201		    stuff->y,
2202		    stuff->reqType,
2203		    stuff->drawable);
2204
2205    if (err == Success)
2206    {
2207	return(client->noClientException);
2208    }
2209    else
2210	return err;
2211}
2212
2213int
2214ProcImageText16(ClientPtr client)
2215{
2216    int	err;
2217    DrawablePtr pDraw;
2218    GC *pGC;
2219
2220    REQUEST(xImageTextReq);
2221
2222    REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars << 1);
2223    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
2224
2225    err = ImageText(client,
2226		    pDraw,
2227		    pGC,
2228		    stuff->nChars,
2229		    (unsigned char *)&stuff[1],
2230		    stuff->x,
2231		    stuff->y,
2232		    stuff->reqType,
2233		    stuff->drawable);
2234
2235    if (err == Success)
2236    {
2237	return(client->noClientException);
2238    }
2239    else
2240	return err;
2241}
2242
2243
2244int
2245ProcCreateColormap(ClientPtr client)
2246{
2247    VisualPtr	pVisual;
2248    ColormapPtr	pmap;
2249    Colormap	mid;
2250    WindowPtr   pWin;
2251    ScreenPtr pScreen;
2252    REQUEST(xCreateColormapReq);
2253    int i, result;
2254
2255    REQUEST_SIZE_MATCH(xCreateColormapReq);
2256
2257    if ((stuff->alloc != AllocNone) && (stuff->alloc != AllocAll))
2258    {
2259	client->errorValue = stuff->alloc;
2260        return(BadValue);
2261    }
2262    mid = stuff->mid;
2263    LEGAL_NEW_RESOURCE(mid, client);
2264    result = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
2265    if (result != Success)
2266        return result;
2267
2268    pScreen = pWin->drawable.pScreen;
2269    for (i = 0, pVisual = pScreen->visuals;
2270	 i < pScreen->numVisuals;
2271	 i++, pVisual++)
2272    {
2273	if (pVisual->vid != stuff->visual)
2274	    continue;
2275	result =  CreateColormap(mid, pScreen, pVisual, &pmap,
2276				 (int)stuff->alloc, client->index);
2277	if (client->noClientException != Success)
2278	    return(client->noClientException);
2279	else
2280	    return(result);
2281    }
2282    client->errorValue = stuff->visual;
2283    return(BadMatch);
2284}
2285
2286int
2287ProcFreeColormap(ClientPtr client)
2288{
2289    ColormapPtr pmap;
2290    int rc;
2291    REQUEST(xResourceReq);
2292
2293    REQUEST_SIZE_MATCH(xResourceReq);
2294    rc = dixLookupResourceByType((pointer *)&pmap, stuff->id, RT_COLORMAP, client,
2295			   DixDestroyAccess);
2296    if (rc == Success)
2297    {
2298	/* Freeing a default colormap is a no-op */
2299	if (!(pmap->flags & IsDefault))
2300	    FreeResource(stuff->id, RT_NONE);
2301	return (client->noClientException);
2302    }
2303    else
2304    {
2305	client->errorValue = stuff->id;
2306	return (rc == BadValue) ? BadColor : rc;
2307    }
2308}
2309
2310
2311int
2312ProcCopyColormapAndFree(ClientPtr client)
2313{
2314    Colormap	mid;
2315    ColormapPtr	pSrcMap;
2316    REQUEST(xCopyColormapAndFreeReq);
2317    int rc;
2318
2319    REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq);
2320    mid = stuff->mid;
2321    LEGAL_NEW_RESOURCE(mid, client);
2322    rc = dixLookupResourceByType((pointer *)&pSrcMap, stuff->srcCmap, RT_COLORMAP,
2323			   client, DixReadAccess|DixRemoveAccess);
2324    if (rc == Success)
2325    {
2326	rc = CopyColormapAndFree(mid, pSrcMap, client->index);
2327	if (client->noClientException != Success)
2328            return(client->noClientException);
2329	else
2330            return rc;
2331    }
2332    else
2333    {
2334	client->errorValue = stuff->srcCmap;
2335	return (rc == BadValue) ? BadColor : rc;
2336    }
2337}
2338
2339int
2340ProcInstallColormap(ClientPtr client)
2341{
2342    ColormapPtr pcmp;
2343    int rc;
2344    REQUEST(xResourceReq);
2345    REQUEST_SIZE_MATCH(xResourceReq);
2346
2347    rc = dixLookupResourceByType((pointer *)&pcmp, stuff->id, RT_COLORMAP, client,
2348			   DixInstallAccess);
2349    if (rc != Success)
2350	goto out;
2351
2352    rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess);
2353    if (rc != Success)
2354	goto out;
2355
2356    (*(pcmp->pScreen->InstallColormap)) (pcmp);
2357
2358    rc = client->noClientException;
2359out:
2360    client->errorValue = stuff->id;
2361    return (rc == BadValue) ? BadColor : rc;
2362}
2363
2364int
2365ProcUninstallColormap(ClientPtr client)
2366{
2367    ColormapPtr pcmp;
2368    int rc;
2369    REQUEST(xResourceReq);
2370    REQUEST_SIZE_MATCH(xResourceReq);
2371
2372    rc = dixLookupResourceByType((pointer *)&pcmp, stuff->id, RT_COLORMAP, client,
2373			   DixUninstallAccess);
2374    if (rc != Success)
2375	goto out;
2376
2377    rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess);
2378    if (rc != Success)
2379	goto out;
2380
2381    if(pcmp->mid != pcmp->pScreen->defColormap)
2382	(*(pcmp->pScreen->UninstallColormap)) (pcmp);
2383
2384    rc = client->noClientException;
2385out:
2386    client->errorValue = stuff->id;
2387    return (rc == BadValue) ? BadColor : rc;
2388}
2389
2390int
2391ProcListInstalledColormaps(ClientPtr client)
2392{
2393    xListInstalledColormapsReply *preply;
2394    int nummaps, rc;
2395    WindowPtr pWin;
2396    REQUEST(xResourceReq);
2397    REQUEST_SIZE_MATCH(xResourceReq);
2398
2399    rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
2400    if (rc != Success)
2401	goto out;
2402
2403    rc = XaceHook(XACE_SCREEN_ACCESS, client, pWin->drawable.pScreen,
2404		  DixGetAttrAccess);
2405    if (rc != Success)
2406	goto out;
2407
2408    preply = (xListInstalledColormapsReply *)
2409		xalloc(sizeof(xListInstalledColormapsReply) +
2410		     pWin->drawable.pScreen->maxInstalledCmaps *
2411		     sizeof(Colormap));
2412    if(!preply)
2413        return(BadAlloc);
2414
2415    preply->type = X_Reply;
2416    preply->sequenceNumber = client->sequence;
2417    nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps)
2418        (pWin->drawable.pScreen, (Colormap *)&preply[1]);
2419    preply->nColormaps = nummaps;
2420    preply->length = nummaps;
2421    WriteReplyToClient(client, sizeof (xListInstalledColormapsReply), preply);
2422    client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
2423    WriteSwappedDataToClient(client, nummaps * sizeof(Colormap), &preply[1]);
2424    xfree(preply);
2425    rc = client->noClientException;
2426out:
2427    return rc;
2428}
2429
2430int
2431ProcAllocColor (ClientPtr client)
2432{
2433    ColormapPtr pmap;
2434    int rc;
2435    xAllocColorReply acr;
2436    REQUEST(xAllocColorReq);
2437
2438    REQUEST_SIZE_MATCH(xAllocColorReq);
2439    rc = dixLookupResourceByType((pointer *)&pmap, stuff->cmap, RT_COLORMAP, client,
2440			   DixAddAccess);
2441    if (rc == Success)
2442    {
2443	acr.type = X_Reply;
2444	acr.length = 0;
2445	acr.sequenceNumber = client->sequence;
2446	acr.red = stuff->red;
2447	acr.green = stuff->green;
2448	acr.blue = stuff->blue;
2449	acr.pixel = 0;
2450	if( (rc = AllocColor(pmap, &acr.red, &acr.green, &acr.blue,
2451	                       &acr.pixel, client->index)) )
2452	{
2453            if (client->noClientException != Success)
2454                return(client->noClientException);
2455	    else
2456	        return rc;
2457	}
2458#ifdef PANORAMIX
2459	if (noPanoramiXExtension || !pmap->pScreen->myNum)
2460#endif
2461        WriteReplyToClient(client, sizeof(xAllocColorReply), &acr);
2462	return (client->noClientException);
2463
2464    }
2465    else
2466    {
2467        client->errorValue = stuff->cmap;
2468        return (rc == BadValue) ? BadColor : rc;
2469    }
2470}
2471
2472int
2473ProcAllocNamedColor (ClientPtr client)
2474{
2475    ColormapPtr pcmp;
2476    int rc;
2477    REQUEST(xAllocNamedColorReq);
2478
2479    REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes);
2480    rc = dixLookupResourceByType((pointer *)&pcmp, stuff->cmap, RT_COLORMAP, client,
2481			   DixAddAccess);
2482    if (rc == Success)
2483    {
2484	xAllocNamedColorReply ancr;
2485
2486	ancr.type = X_Reply;
2487	ancr.length = 0;
2488	ancr.sequenceNumber = client->sequence;
2489
2490	if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], stuff->nbytes,
2491	                 &ancr.exactRed, &ancr.exactGreen, &ancr.exactBlue))
2492	{
2493	    ancr.screenRed = ancr.exactRed;
2494	    ancr.screenGreen = ancr.exactGreen;
2495	    ancr.screenBlue = ancr.exactBlue;
2496	    ancr.pixel = 0;
2497	    if( (rc = AllocColor(pcmp,
2498	                 &ancr.screenRed, &ancr.screenGreen, &ancr.screenBlue,
2499			 &ancr.pixel, client->index)) )
2500	    {
2501                if (client->noClientException != Success)
2502                    return(client->noClientException);
2503                else
2504		    return rc;
2505	    }
2506#ifdef PANORAMIX
2507	    if (noPanoramiXExtension || !pcmp->pScreen->myNum)
2508#endif
2509            WriteReplyToClient(client, sizeof (xAllocNamedColorReply), &ancr);
2510	    return (client->noClientException);
2511	}
2512	else
2513	    return(BadName);
2514
2515    }
2516    else
2517    {
2518        client->errorValue = stuff->cmap;
2519        return (rc == BadValue) ? BadColor : rc;
2520    }
2521}
2522
2523int
2524ProcAllocColorCells (ClientPtr client)
2525{
2526    ColormapPtr pcmp;
2527    int rc;
2528    REQUEST(xAllocColorCellsReq);
2529
2530    REQUEST_SIZE_MATCH(xAllocColorCellsReq);
2531    rc = dixLookupResourceByType((pointer *)&pcmp, stuff->cmap, RT_COLORMAP, client,
2532			   DixAddAccess);
2533    if (rc == Success)
2534    {
2535	xAllocColorCellsReply	accr;
2536	int			npixels, nmasks;
2537	long			length;
2538	Pixel			*ppixels, *pmasks;
2539
2540	npixels = stuff->colors;
2541	if (!npixels)
2542	{
2543	    client->errorValue = npixels;
2544	    return (BadValue);
2545	}
2546	if (stuff->contiguous != xTrue && stuff->contiguous != xFalse)
2547	{
2548	    client->errorValue = stuff->contiguous;
2549	    return (BadValue);
2550	}
2551	nmasks = stuff->planes;
2552	length = ((long)npixels + (long)nmasks) * sizeof(Pixel);
2553	ppixels = (Pixel *)xalloc(length);
2554	if(!ppixels)
2555            return(BadAlloc);
2556	pmasks = ppixels + npixels;
2557
2558	if( (rc = AllocColorCells(client->index, pcmp, npixels, nmasks,
2559				    (Bool)stuff->contiguous, ppixels, pmasks)) )
2560	{
2561	    xfree(ppixels);
2562            if (client->noClientException != Success)
2563                return(client->noClientException);
2564	    else
2565	        return rc;
2566	}
2567#ifdef PANORAMIX
2568	if (noPanoramiXExtension || !pcmp->pScreen->myNum)
2569#endif
2570	{
2571	    accr.type = X_Reply;
2572	    accr.length = length >> 2;
2573	    accr.sequenceNumber = client->sequence;
2574	    accr.nPixels = npixels;
2575	    accr.nMasks = nmasks;
2576	    WriteReplyToClient(client, sizeof (xAllocColorCellsReply), &accr);
2577	    client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
2578	    WriteSwappedDataToClient(client, length, ppixels);
2579	}
2580	xfree(ppixels);
2581        return (client->noClientException);
2582    }
2583    else
2584    {
2585        client->errorValue = stuff->cmap;
2586        return (rc == BadValue) ? BadColor : rc;
2587    }
2588}
2589
2590int
2591ProcAllocColorPlanes(ClientPtr client)
2592{
2593    ColormapPtr pcmp;
2594    int rc;
2595    REQUEST(xAllocColorPlanesReq);
2596
2597    REQUEST_SIZE_MATCH(xAllocColorPlanesReq);
2598    rc = dixLookupResourceByType((pointer *)&pcmp, stuff->cmap, RT_COLORMAP, client,
2599			   DixAddAccess);
2600    if (rc == Success)
2601    {
2602	xAllocColorPlanesReply	acpr;
2603	int			npixels;
2604	long			length;
2605	Pixel			*ppixels;
2606
2607	npixels = stuff->colors;
2608	if (!npixels)
2609	{
2610	    client->errorValue = npixels;
2611	    return (BadValue);
2612	}
2613	if (stuff->contiguous != xTrue && stuff->contiguous != xFalse)
2614	{
2615	    client->errorValue = stuff->contiguous;
2616	    return (BadValue);
2617	}
2618	acpr.type = X_Reply;
2619	acpr.sequenceNumber = client->sequence;
2620	acpr.nPixels = npixels;
2621	length = (long)npixels * sizeof(Pixel);
2622	ppixels = (Pixel *)xalloc(length);
2623	if(!ppixels)
2624            return(BadAlloc);
2625	if( (rc = AllocColorPlanes(client->index, pcmp, npixels,
2626	    (int)stuff->red, (int)stuff->green, (int)stuff->blue,
2627	    (Bool)stuff->contiguous, ppixels,
2628	    &acpr.redMask, &acpr.greenMask, &acpr.blueMask)) )
2629	{
2630            xfree(ppixels);
2631            if (client->noClientException != Success)
2632                return(client->noClientException);
2633	    else
2634	        return rc;
2635	}
2636	acpr.length = length >> 2;
2637#ifdef PANORAMIX
2638	if (noPanoramiXExtension || !pcmp->pScreen->myNum)
2639#endif
2640	{
2641	    WriteReplyToClient(client, sizeof(xAllocColorPlanesReply), &acpr);
2642	    client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
2643	    WriteSwappedDataToClient(client, length, ppixels);
2644	}
2645	xfree(ppixels);
2646        return (client->noClientException);
2647    }
2648    else
2649    {
2650        client->errorValue = stuff->cmap;
2651        return (rc == BadValue) ? BadColor : rc;
2652    }
2653}
2654
2655int
2656ProcFreeColors(ClientPtr client)
2657{
2658    ColormapPtr pcmp;
2659    int rc;
2660    REQUEST(xFreeColorsReq);
2661
2662    REQUEST_AT_LEAST_SIZE(xFreeColorsReq);
2663    rc = dixLookupResourceByType((pointer *)&pcmp, stuff->cmap, RT_COLORMAP, client,
2664			   DixRemoveAccess);
2665    if (rc == Success)
2666    {
2667	int	count;
2668
2669	if(pcmp->flags & AllAllocated)
2670	    return(BadAccess);
2671	count = ((client->req_len << 2)- sizeof(xFreeColorsReq)) >> 2;
2672	rc = FreeColors(pcmp, client->index, count,
2673	    (Pixel *)&stuff[1], (Pixel)stuff->planeMask);
2674        if (client->noClientException != Success)
2675            return(client->noClientException);
2676        else
2677	{
2678	    client->errorValue = clientErrorValue;
2679            return rc;
2680	}
2681
2682    }
2683    else
2684    {
2685        client->errorValue = stuff->cmap;
2686        return (rc == BadValue) ? BadColor : rc;
2687    }
2688}
2689
2690int
2691ProcStoreColors (ClientPtr client)
2692{
2693    ColormapPtr pcmp;
2694    int rc;
2695    REQUEST(xStoreColorsReq);
2696
2697    REQUEST_AT_LEAST_SIZE(xStoreColorsReq);
2698    rc = dixLookupResourceByType((pointer *)&pcmp, stuff->cmap, RT_COLORMAP, client,
2699			   DixWriteAccess);
2700    if (rc == Success)
2701    {
2702	int	count;
2703
2704        count = (client->req_len << 2) - sizeof(xStoreColorsReq);
2705	if (count % sizeof(xColorItem))
2706	    return(BadLength);
2707	count /= sizeof(xColorItem);
2708	rc = StoreColors(pcmp, count, (xColorItem *)&stuff[1]);
2709        if (client->noClientException != Success)
2710            return(client->noClientException);
2711        else
2712	{
2713	    client->errorValue = clientErrorValue;
2714            return rc;
2715	}
2716    }
2717    else
2718    {
2719        client->errorValue = stuff->cmap;
2720        return (rc == BadValue) ? BadColor : rc;
2721    }
2722}
2723
2724int
2725ProcStoreNamedColor (ClientPtr client)
2726{
2727    ColormapPtr pcmp;
2728    int rc;
2729    REQUEST(xStoreNamedColorReq);
2730
2731    REQUEST_FIXED_SIZE(xStoreNamedColorReq, stuff->nbytes);
2732    rc = dixLookupResourceByType((pointer *)&pcmp, stuff->cmap, RT_COLORMAP, client,
2733			   DixWriteAccess);
2734    if (rc == Success)
2735    {
2736	xColorItem	def;
2737
2738	if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1],
2739	                 stuff->nbytes, &def.red, &def.green, &def.blue))
2740	{
2741	    def.flags = stuff->flags;
2742	    def.pixel = stuff->pixel;
2743	    rc = StoreColors(pcmp, 1, &def);
2744            if (client->noClientException != Success)
2745                return(client->noClientException);
2746	    else
2747		return rc;
2748	}
2749        return (BadName);
2750    }
2751    else
2752    {
2753        client->errorValue = stuff->cmap;
2754        return (rc == BadValue) ? BadColor : rc;
2755    }
2756}
2757
2758int
2759ProcQueryColors(ClientPtr client)
2760{
2761    ColormapPtr pcmp;
2762    int rc;
2763    REQUEST(xQueryColorsReq);
2764
2765    REQUEST_AT_LEAST_SIZE(xQueryColorsReq);
2766    rc = dixLookupResourceByType((pointer *)&pcmp, stuff->cmap, RT_COLORMAP, client,
2767			   DixReadAccess);
2768    if (rc == Success)
2769    {
2770	int			count;
2771	xrgb 			*prgbs;
2772	xQueryColorsReply	qcr;
2773
2774	count = ((client->req_len << 2) - sizeof(xQueryColorsReq)) >> 2;
2775	prgbs = (xrgb *)xalloc(count * sizeof(xrgb));
2776	if(!prgbs && count)
2777            return(BadAlloc);
2778	if( (rc = QueryColors(pcmp, count, (Pixel *)&stuff[1], prgbs)) )
2779	{
2780   	    if (prgbs) xfree(prgbs);
2781	    if (client->noClientException != Success)
2782                return(client->noClientException);
2783	    else
2784	    {
2785		client->errorValue = clientErrorValue;
2786	        return rc;
2787	    }
2788	}
2789	qcr.type = X_Reply;
2790	qcr.length = (count * sizeof(xrgb)) >> 2;
2791	qcr.sequenceNumber = client->sequence;
2792	qcr.nColors = count;
2793	WriteReplyToClient(client, sizeof(xQueryColorsReply), &qcr);
2794	if (count)
2795	{
2796	    client->pSwapReplyFunc = (ReplySwapPtr) SQColorsExtend;
2797	    WriteSwappedDataToClient(client, count * sizeof(xrgb), prgbs);
2798	}
2799	if (prgbs) xfree(prgbs);
2800	return(client->noClientException);
2801
2802    }
2803    else
2804    {
2805        client->errorValue = stuff->cmap;
2806        return (rc == BadValue) ? BadColor : rc;
2807    }
2808}
2809
2810int
2811ProcLookupColor(ClientPtr client)
2812{
2813    ColormapPtr pcmp;
2814    int rc;
2815    REQUEST(xLookupColorReq);
2816
2817    REQUEST_FIXED_SIZE(xLookupColorReq, stuff->nbytes);
2818    rc = dixLookupResourceByType((pointer *)&pcmp, stuff->cmap, RT_COLORMAP, client,
2819			   DixReadAccess);
2820    if (rc == Success)
2821    {
2822	xLookupColorReply lcr;
2823
2824	if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], stuff->nbytes,
2825	                 &lcr.exactRed, &lcr.exactGreen, &lcr.exactBlue))
2826	{
2827	    lcr.type = X_Reply;
2828	    lcr.length = 0;
2829	    lcr.sequenceNumber = client->sequence;
2830	    lcr.screenRed = lcr.exactRed;
2831	    lcr.screenGreen = lcr.exactGreen;
2832	    lcr.screenBlue = lcr.exactBlue;
2833	    (*pcmp->pScreen->ResolveColor)(&lcr.screenRed,
2834	                                   &lcr.screenGreen,
2835					   &lcr.screenBlue,
2836					   pcmp->pVisual);
2837	    WriteReplyToClient(client, sizeof(xLookupColorReply), &lcr);
2838	    return(client->noClientException);
2839	}
2840        return (BadName);
2841    }
2842    else
2843    {
2844        client->errorValue = stuff->cmap;
2845        return (rc == BadValue) ? BadColor : rc;
2846    }
2847}
2848
2849int
2850ProcCreateCursor (ClientPtr client)
2851{
2852    CursorPtr		pCursor;
2853    PixmapPtr 		src;
2854    PixmapPtr 		msk;
2855    unsigned char *	srcbits;
2856    unsigned char *	mskbits;
2857    unsigned short	width, height;
2858    long		n;
2859    CursorMetricRec 	cm;
2860    int rc;
2861
2862    REQUEST(xCreateCursorReq);
2863
2864    REQUEST_SIZE_MATCH(xCreateCursorReq);
2865    LEGAL_NEW_RESOURCE(stuff->cid, client);
2866
2867    rc = dixLookupResourceByType((pointer *)&src, stuff->source, RT_PIXMAP, client,
2868			   DixReadAccess);
2869    if (rc != Success) {
2870	client->errorValue = stuff->source;
2871	return (rc == BadValue) ? BadPixmap : rc;
2872    }
2873
2874    rc = dixLookupResourceByType((pointer *)&msk, stuff->mask, RT_PIXMAP, client,
2875			   DixReadAccess);
2876    if (rc != Success)
2877    {
2878	if (stuff->mask != None)
2879	{
2880	    client->errorValue = stuff->mask;
2881	    return (rc == BadValue) ? BadPixmap : rc;
2882	}
2883    }
2884    else if (  src->drawable.width != msk->drawable.width
2885	    || src->drawable.height != msk->drawable.height
2886	    || src->drawable.depth != 1
2887	    || msk->drawable.depth != 1)
2888	return (BadMatch);
2889
2890    width = src->drawable.width;
2891    height = src->drawable.height;
2892
2893    if ( stuff->x > width
2894      || stuff->y > height )
2895	return (BadMatch);
2896
2897    n = BitmapBytePad(width)*height;
2898    srcbits = xcalloc(1, n);
2899    if (!srcbits)
2900	return (BadAlloc);
2901    mskbits = xalloc(n);
2902    if (!mskbits)
2903    {
2904	xfree(srcbits);
2905	return (BadAlloc);
2906    }
2907
2908    (* src->drawable.pScreen->GetImage)( (DrawablePtr)src, 0, 0, width, height,
2909					 XYPixmap, 1, (pointer)srcbits);
2910    if ( msk == (PixmapPtr)NULL)
2911    {
2912	unsigned char *bits = mskbits;
2913	while (--n >= 0)
2914	    *bits++ = ~0;
2915    }
2916    else
2917    {
2918	/* zeroing the (pad) bits helps some ddx cursor handling */
2919	bzero((char *)mskbits, n);
2920	(* msk->drawable.pScreen->GetImage)( (DrawablePtr)msk, 0, 0, width,
2921					height, XYPixmap, 1, (pointer)mskbits);
2922    }
2923    cm.width = width;
2924    cm.height = height;
2925    cm.xhot = stuff->x;
2926    cm.yhot = stuff->y;
2927    rc = AllocARGBCursor(srcbits, mskbits, NULL, &cm,
2928			 stuff->foreRed, stuff->foreGreen, stuff->foreBlue,
2929			 stuff->backRed, stuff->backGreen, stuff->backBlue,
2930			 &pCursor, client, stuff->cid);
2931
2932    if (rc != Success)
2933	return rc;
2934    if (!AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor))
2935	return BadAlloc;
2936
2937    return client->noClientException;
2938}
2939
2940int
2941ProcCreateGlyphCursor (ClientPtr client)
2942{
2943    CursorPtr pCursor;
2944    int res;
2945
2946    REQUEST(xCreateGlyphCursorReq);
2947
2948    REQUEST_SIZE_MATCH(xCreateGlyphCursorReq);
2949    LEGAL_NEW_RESOURCE(stuff->cid, client);
2950
2951    res = AllocGlyphCursor(stuff->source, stuff->sourceChar,
2952			   stuff->mask, stuff->maskChar,
2953			   stuff->foreRed, stuff->foreGreen, stuff->foreBlue,
2954			   stuff->backRed, stuff->backGreen, stuff->backBlue,
2955			   &pCursor, client, stuff->cid);
2956    if (res != Success)
2957	return res;
2958    if (AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor))
2959	return client->noClientException;
2960    return BadAlloc;
2961}
2962
2963
2964int
2965ProcFreeCursor (ClientPtr client)
2966{
2967    CursorPtr pCursor;
2968    int rc;
2969    REQUEST(xResourceReq);
2970
2971    REQUEST_SIZE_MATCH(xResourceReq);
2972    rc = dixLookupResourceByType((pointer *)&pCursor, stuff->id, RT_CURSOR, client,
2973			   DixDestroyAccess);
2974    if (rc == Success)
2975    {
2976	FreeResource(stuff->id, RT_NONE);
2977	return (client->noClientException);
2978    }
2979    else
2980    {
2981	client->errorValue = stuff->id;
2982	return (rc == BadValue) ? BadCursor : rc;
2983    }
2984}
2985
2986int
2987ProcQueryBestSize (ClientPtr client)
2988{
2989    xQueryBestSizeReply	reply;
2990    DrawablePtr pDraw;
2991    ScreenPtr pScreen;
2992    int rc;
2993    REQUEST(xQueryBestSizeReq);
2994    REQUEST_SIZE_MATCH(xQueryBestSizeReq);
2995
2996    if ((stuff->class != CursorShape) &&
2997	(stuff->class != TileShape) &&
2998	(stuff->class != StippleShape))
2999    {
3000	client->errorValue = stuff->class;
3001        return(BadValue);
3002    }
3003
3004    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
3005			   DixGetAttrAccess);
3006    if (rc != Success)
3007	return rc;
3008    if (stuff->class != CursorShape && pDraw->type == UNDRAWABLE_WINDOW)
3009	return (BadMatch);
3010    pScreen = pDraw->pScreen;
3011    rc = XaceHook(XACE_SCREEN_ACCESS, client, pScreen, DixGetAttrAccess);
3012    if (rc != Success)
3013	return rc;
3014    (* pScreen->QueryBestSize)(stuff->class, &stuff->width,
3015			       &stuff->height, pScreen);
3016    reply.type = X_Reply;
3017    reply.length = 0;
3018    reply.sequenceNumber = client->sequence;
3019    reply.width = stuff->width;
3020    reply.height = stuff->height;
3021    WriteReplyToClient(client, sizeof(xQueryBestSizeReply), &reply);
3022    return (client->noClientException);
3023}
3024
3025
3026int
3027ProcSetScreenSaver (ClientPtr client)
3028{
3029    int rc, i, blankingOption, exposureOption;
3030    REQUEST(xSetScreenSaverReq);
3031    REQUEST_SIZE_MATCH(xSetScreenSaverReq);
3032
3033    for (i = 0; i < screenInfo.numScreens; i++) {
3034	rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i],
3035		      DixSetAttrAccess);
3036	if (rc != Success)
3037	    return rc;
3038    }
3039
3040    blankingOption = stuff->preferBlank;
3041    if ((blankingOption != DontPreferBlanking) &&
3042        (blankingOption != PreferBlanking) &&
3043        (blankingOption != DefaultBlanking))
3044    {
3045	client->errorValue = blankingOption;
3046        return BadValue;
3047    }
3048    exposureOption = stuff->allowExpose;
3049    if ((exposureOption != DontAllowExposures) &&
3050        (exposureOption != AllowExposures) &&
3051        (exposureOption != DefaultExposures))
3052    {
3053	client->errorValue = exposureOption;
3054        return BadValue;
3055    }
3056    if (stuff->timeout < -1)
3057    {
3058	client->errorValue = stuff->timeout;
3059        return BadValue;
3060    }
3061    if (stuff->interval < -1)
3062    {
3063	client->errorValue = stuff->interval;
3064        return BadValue;
3065    }
3066
3067    if (blankingOption == DefaultBlanking)
3068	ScreenSaverBlanking = defaultScreenSaverBlanking;
3069    else
3070	ScreenSaverBlanking = blankingOption;
3071    if (exposureOption == DefaultExposures)
3072	ScreenSaverAllowExposures = defaultScreenSaverAllowExposures;
3073    else
3074	ScreenSaverAllowExposures = exposureOption;
3075
3076    if (stuff->timeout >= 0)
3077	ScreenSaverTime = stuff->timeout * MILLI_PER_SECOND;
3078    else
3079	ScreenSaverTime = defaultScreenSaverTime;
3080    if (stuff->interval >= 0)
3081	ScreenSaverInterval = stuff->interval * MILLI_PER_SECOND;
3082    else
3083	ScreenSaverInterval = defaultScreenSaverInterval;
3084
3085    SetScreenSaverTimer();
3086    return (client->noClientException);
3087}
3088
3089int
3090ProcGetScreenSaver(ClientPtr client)
3091{
3092    xGetScreenSaverReply rep;
3093    int rc, i;
3094    REQUEST_SIZE_MATCH(xReq);
3095
3096    for (i = 0; i < screenInfo.numScreens; i++) {
3097	rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i],
3098		      DixGetAttrAccess);
3099	if (rc != Success)
3100	    return rc;
3101    }
3102
3103    rep.type = X_Reply;
3104    rep.length = 0;
3105    rep.sequenceNumber = client->sequence;
3106    rep.timeout = ScreenSaverTime / MILLI_PER_SECOND;
3107    rep.interval = ScreenSaverInterval / MILLI_PER_SECOND;
3108    rep.preferBlanking = ScreenSaverBlanking;
3109    rep.allowExposures = ScreenSaverAllowExposures;
3110    WriteReplyToClient(client, sizeof(xGetScreenSaverReply), &rep);
3111    return (client->noClientException);
3112}
3113
3114int
3115ProcChangeHosts(ClientPtr client)
3116{
3117    REQUEST(xChangeHostsReq);
3118    int result;
3119
3120    REQUEST_FIXED_SIZE(xChangeHostsReq, stuff->hostLength);
3121
3122    if(stuff->mode == HostInsert)
3123	result = AddHost(client, (int)stuff->hostFamily,
3124			 stuff->hostLength, (pointer)&stuff[1]);
3125    else if (stuff->mode == HostDelete)
3126	result = RemoveHost(client, (int)stuff->hostFamily,
3127			    stuff->hostLength, (pointer)&stuff[1]);
3128    else
3129    {
3130	client->errorValue = stuff->mode;
3131        return BadValue;
3132    }
3133    if (!result)
3134	result = client->noClientException;
3135    return (result);
3136}
3137
3138int
3139ProcListHosts(ClientPtr client)
3140{
3141    xListHostsReply reply;
3142    int	len, nHosts, result;
3143    pointer	pdata;
3144    /* REQUEST(xListHostsReq); */
3145
3146    REQUEST_SIZE_MATCH(xListHostsReq);
3147
3148    /* untrusted clients can't list hosts */
3149    result = XaceHook(XACE_SERVER_ACCESS, client, DixReadAccess);
3150    if (result != Success)
3151	return result;
3152
3153    result = GetHosts(&pdata, &nHosts, &len, &reply.enabled);
3154    if (result != Success)
3155	return(result);
3156    reply.type = X_Reply;
3157    reply.sequenceNumber = client->sequence;
3158    reply.nHosts = nHosts;
3159    reply.length = len >> 2;
3160    WriteReplyToClient(client, sizeof(xListHostsReply), &reply);
3161    if (nHosts)
3162    {
3163	client->pSwapReplyFunc = (ReplySwapPtr) SLHostsExtend;
3164	WriteSwappedDataToClient(client, len, pdata);
3165    }
3166    xfree(pdata);
3167    return (client->noClientException);
3168}
3169
3170int
3171ProcChangeAccessControl(ClientPtr client)
3172{
3173    int result;
3174    REQUEST(xSetAccessControlReq);
3175
3176    REQUEST_SIZE_MATCH(xSetAccessControlReq);
3177    if ((stuff->mode != EnableAccess) && (stuff->mode != DisableAccess))
3178    {
3179	client->errorValue = stuff->mode;
3180        return BadValue;
3181    }
3182    result = ChangeAccessControl(client, stuff->mode == EnableAccess);
3183    if (!result)
3184	result = client->noClientException;
3185    return (result);
3186}
3187
3188/*********************
3189 * CloseDownRetainedResources
3190 *
3191 *    Find all clients that are gone and have terminated in RetainTemporary
3192 *    and destroy their resources.
3193 *********************/
3194
3195static void
3196CloseDownRetainedResources(void)
3197{
3198    int i;
3199    ClientPtr client;
3200
3201    for (i=1; i<currentMaxClients; i++)
3202    {
3203        client = clients[i];
3204        if (client && (client->closeDownMode == RetainTemporary)
3205	    && (client->clientGone))
3206	    CloseDownClient(client);
3207    }
3208}
3209
3210int
3211ProcKillClient(ClientPtr client)
3212{
3213    REQUEST(xResourceReq);
3214    ClientPtr killclient;
3215    int rc;
3216
3217    REQUEST_SIZE_MATCH(xResourceReq);
3218    if (stuff->id == AllTemporary)
3219    {
3220	CloseDownRetainedResources();
3221        return (client->noClientException);
3222    }
3223
3224    rc = dixLookupClient(&killclient, stuff->id, client, DixDestroyAccess);
3225    if (rc == Success) {
3226	CloseDownClient(killclient);
3227	/* if an LBX proxy gets killed, isItTimeToYield will be set */
3228	if (isItTimeToYield || (client == killclient))
3229	{
3230	    /* force yield and return Success, so that Dispatch()
3231	     * doesn't try to touch client
3232	     */
3233	    isItTimeToYield = TRUE;
3234	    return (Success);
3235	}
3236	return (client->noClientException);
3237    }
3238    else
3239	return rc;
3240}
3241
3242int
3243ProcSetFontPath(ClientPtr client)
3244{
3245    unsigned char *ptr;
3246    unsigned long nbytes, total;
3247    long nfonts;
3248    int n, result;
3249    int error;
3250    REQUEST(xSetFontPathReq);
3251
3252    REQUEST_AT_LEAST_SIZE(xSetFontPathReq);
3253
3254    nbytes = (client->req_len << 2) - sizeof(xSetFontPathReq);
3255    total = nbytes;
3256    ptr = (unsigned char *)&stuff[1];
3257    nfonts = stuff->nFonts;
3258    while (--nfonts >= 0)
3259    {
3260	if ((total == 0) || (total < (n = (*ptr + 1))))
3261	    return(BadLength);
3262	total -= n;
3263	ptr += n;
3264    }
3265    if (total >= 4)
3266	return(BadLength);
3267    result = SetFontPath(client, stuff->nFonts, (unsigned char *)&stuff[1],
3268			 &error);
3269    if (!result)
3270    {
3271	result = client->noClientException;
3272	client->errorValue = error;
3273    }
3274    return (result);
3275}
3276
3277int
3278ProcGetFontPath(ClientPtr client)
3279{
3280    xGetFontPathReply reply;
3281    int rc, stringLens, numpaths;
3282    unsigned char *bufferStart;
3283    /* REQUEST (xReq); */
3284
3285    REQUEST_SIZE_MATCH(xReq);
3286    rc = GetFontPath(client, &numpaths, &stringLens, &bufferStart);
3287    if (rc != Success)
3288	return rc;
3289
3290    reply.type = X_Reply;
3291    reply.sequenceNumber = client->sequence;
3292    reply.length = (stringLens + numpaths + 3) >> 2;
3293    reply.nPaths = numpaths;
3294
3295    WriteReplyToClient(client, sizeof(xGetFontPathReply), &reply);
3296    if (stringLens || numpaths)
3297	(void)WriteToClient(client, stringLens + numpaths, (char *)bufferStart);
3298    return(client->noClientException);
3299}
3300
3301int
3302ProcChangeCloseDownMode(ClientPtr client)
3303{
3304    int rc;
3305    REQUEST(xSetCloseDownModeReq);
3306    REQUEST_SIZE_MATCH(xSetCloseDownModeReq);
3307
3308    rc = XaceHook(XACE_CLIENT_ACCESS, client, client, DixManageAccess);
3309    if (rc != Success)
3310	return rc;
3311
3312    if ((stuff->mode == AllTemporary) ||
3313	(stuff->mode == RetainPermanent) ||
3314	(stuff->mode == RetainTemporary))
3315    {
3316	client->closeDownMode = stuff->mode;
3317	return (client->noClientException);
3318    }
3319    else
3320    {
3321	client->errorValue = stuff->mode;
3322	return (BadValue);
3323    }
3324}
3325
3326int ProcForceScreenSaver(ClientPtr client)
3327{
3328    int rc;
3329    REQUEST(xForceScreenSaverReq);
3330
3331    REQUEST_SIZE_MATCH(xForceScreenSaverReq);
3332
3333    if ((stuff->mode != ScreenSaverReset) &&
3334	(stuff->mode != ScreenSaverActive))
3335    {
3336	client->errorValue = stuff->mode;
3337        return BadValue;
3338    }
3339    rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, (int)stuff->mode);
3340    if (rc != Success)
3341	return rc;
3342    return client->noClientException;
3343}
3344
3345int ProcNoOperation(ClientPtr client)
3346{
3347    REQUEST_AT_LEAST_SIZE(xReq);
3348
3349    /* noop -- don't do anything */
3350    return(client->noClientException);
3351}
3352
3353void
3354InitProcVectors(void)
3355{
3356    int i;
3357    for (i = 0; i<256; i++)
3358    {
3359	if(!ProcVector[i])
3360	{
3361            ProcVector[i] = SwappedProcVector[i] = ProcBadRequest;
3362	    ReplySwapVector[i] = ReplyNotSwappd;
3363	}
3364    }
3365    for(i = LASTEvent; i < 128; i++)
3366    {
3367	EventSwapVector[i] = NotImplemented;
3368    }
3369
3370}
3371
3372/**********************
3373 * CloseDownClient
3374 *
3375 *  Client can either mark his resources destroy or retain.  If retained and
3376 *  then killed again, the client is really destroyed.
3377 *********************/
3378
3379char dispatchExceptionAtReset = DE_RESET;
3380
3381void
3382CloseDownClient(ClientPtr client)
3383{
3384    Bool really_close_down = client->clientGone ||
3385			     client->closeDownMode == DestroyAll;
3386
3387    if (!client->clientGone)
3388    {
3389	/* ungrab server if grabbing client dies */
3390	if (grabState != GrabNone && grabClient == client)
3391	{
3392	    UngrabServer(client);
3393	}
3394	BITCLEAR(grabWaiters, client->index);
3395	DeleteClientFromAnySelections(client);
3396	ReleaseActiveGrabs(client);
3397	DeleteClientFontStuff(client);
3398	if (!really_close_down)
3399	{
3400	    /*  This frees resources that should never be retained
3401	     *  no matter what the close down mode is.  Actually we
3402	     *  could do this unconditionally, but it's probably
3403	     *  better not to traverse all the client's resources
3404	     *  twice (once here, once a few lines down in
3405	     *  FreeClientResources) in the common case of
3406	     *  really_close_down == TRUE.
3407	     */
3408	    FreeClientNeverRetainResources(client);
3409	    client->clientState = ClientStateRetained;
3410  	    if (ClientStateCallback)
3411            {
3412		NewClientInfoRec clientinfo;
3413
3414		clientinfo.client = client;
3415		clientinfo.prefix = (xConnSetupPrefix *)NULL;
3416		clientinfo.setup = (xConnSetup *) NULL;
3417		CallCallbacks((&ClientStateCallback), (pointer)&clientinfo);
3418            }
3419	}
3420	client->clientGone = TRUE;  /* so events aren't sent to client */
3421	if (ClientIsAsleep(client))
3422	    ClientSignal (client);
3423	ProcessWorkQueueZombies();
3424	CloseDownConnection(client);
3425
3426	/* If the client made it to the Running stage, nClients has
3427	 * been incremented on its behalf, so we need to decrement it
3428	 * now.  If it hasn't gotten to Running, nClients has *not*
3429	 * been incremented, so *don't* decrement it.
3430	 */
3431	if (client->clientState != ClientStateInitial &&
3432	    client->clientState != ClientStateAuthenticating )
3433	{
3434	    --nClients;
3435	}
3436    }
3437
3438    if (really_close_down)
3439    {
3440	if (client->clientState == ClientStateRunning && nClients == 0)
3441	    dispatchException |= dispatchExceptionAtReset;
3442
3443	client->clientState = ClientStateGone;
3444	if (ClientStateCallback)
3445	{
3446	    NewClientInfoRec clientinfo;
3447
3448	    clientinfo.client = client;
3449	    clientinfo.prefix = (xConnSetupPrefix *)NULL;
3450	    clientinfo.setup = (xConnSetup *) NULL;
3451	    CallCallbacks((&ClientStateCallback), (pointer)&clientinfo);
3452	}
3453	FreeClientResources(client);
3454#ifdef XSERVER_DTRACE
3455	XSERVER_CLIENT_DISCONNECT(client->index);
3456#endif
3457	if (client->index < nextFreeClientID)
3458	    nextFreeClientID = client->index;
3459	clients[client->index] = NullClient;
3460	SmartLastClient = NullClient;
3461	dixFreePrivates(client->devPrivates);
3462	xfree(client);
3463
3464	while (!clients[currentMaxClients-1])
3465	    currentMaxClients--;
3466    }
3467}
3468
3469static void
3470KillAllClients(void)
3471{
3472    int i;
3473    for (i=1; i<currentMaxClients; i++)
3474        if (clients[i]) {
3475            /* Make sure Retained clients are released. */
3476            clients[i]->closeDownMode = DestroyAll;
3477            CloseDownClient(clients[i]);
3478        }
3479}
3480
3481void InitClient(ClientPtr client, int i, pointer ospriv)
3482{
3483    client->index = i;
3484    client->sequence = 0;
3485    client->clientAsMask = ((Mask)i) << CLIENTOFFSET;
3486    client->clientGone = FALSE;
3487    client->closeDownMode = i ? DestroyAll : RetainPermanent;
3488    client->numSaved = 0;
3489    client->saveSet = (SaveSetElt *)NULL;
3490    client->noClientException = Success;
3491#ifdef DEBUG
3492    client->requestLogIndex = 0;
3493#endif
3494    client->requestVector = InitialVector;
3495    client->osPrivate = ospriv;
3496    client->swapped = FALSE;
3497    client->big_requests = FALSE;
3498    client->priority = 0;
3499    client->clientState = ClientStateInitial;
3500    client->devPrivates = NULL;
3501#ifdef XKB
3502    if (!noXkbExtension) {
3503	client->xkbClientFlags = 0;
3504	client->mapNotifyMask = 0;
3505	client->newKeyboardNotifyMask = 0;
3506	client->vMinor = client->vMajor = 0;
3507	QueryMinMaxKeyCodes(&client->minKC,&client->maxKC);
3508    }
3509#endif
3510    client->replyBytesRemaining = 0;
3511    client->fontResFunc = NULL;
3512    client->smart_priority = 0;
3513    client->smart_start_tick = SmartScheduleTime;
3514    client->smart_stop_tick = SmartScheduleTime;
3515    client->smart_check_tick = SmartScheduleTime;
3516
3517    client->clientPtr = NULL;
3518}
3519
3520/************************
3521 * int NextAvailableClient(ospriv)
3522 *
3523 * OS dependent portion can't assign client id's because of CloseDownModes.
3524 * Returns NULL if there are no free clients.
3525 *************************/
3526
3527ClientPtr NextAvailableClient(pointer ospriv)
3528{
3529    int i;
3530    ClientPtr client;
3531    xReq data;
3532
3533    i = nextFreeClientID;
3534    if (i == MAXCLIENTS)
3535	return (ClientPtr)NULL;
3536    clients[i] = client = (ClientPtr)xalloc(sizeof(ClientRec));
3537    if (!client)
3538	return (ClientPtr)NULL;
3539    InitClient(client, i, ospriv);
3540    if (!InitClientResources(client))
3541    {
3542	xfree(client);
3543	return (ClientPtr)NULL;
3544    }
3545    data.reqType = 1;
3546    data.length = (sz_xReq + sz_xConnClientPrefix) >> 2;
3547    if (!InsertFakeRequest(client, (char *)&data, sz_xReq))
3548    {
3549	FreeClientResources(client);
3550	xfree(client);
3551	return (ClientPtr)NULL;
3552    }
3553    if (i == currentMaxClients)
3554	currentMaxClients++;
3555    while ((nextFreeClientID < MAXCLIENTS) && clients[nextFreeClientID])
3556	nextFreeClientID++;
3557    if (ClientStateCallback)
3558    {
3559	NewClientInfoRec clientinfo;
3560
3561        clientinfo.client = client;
3562        clientinfo.prefix = (xConnSetupPrefix *)NULL;
3563        clientinfo.setup = (xConnSetup *) NULL;
3564	CallCallbacks((&ClientStateCallback), (pointer)&clientinfo);
3565    }
3566    return(client);
3567}
3568
3569int
3570ProcInitialConnection(ClientPtr client)
3571{
3572    REQUEST(xReq);
3573    xConnClientPrefix *prefix;
3574    int whichbyte = 1;
3575
3576    prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq);
3577    if ((prefix->byteOrder != 'l') && (prefix->byteOrder != 'B'))
3578	return (client->noClientException = -1);
3579    if (((*(char *) &whichbyte) && (prefix->byteOrder == 'B')) ||
3580	(!(*(char *) &whichbyte) && (prefix->byteOrder == 'l')))
3581    {
3582	client->swapped = TRUE;
3583	SwapConnClientPrefix(prefix);
3584    }
3585    stuff->reqType = 2;
3586    stuff->length += ((prefix->nbytesAuthProto + (unsigned)3) >> 2) +
3587		     ((prefix->nbytesAuthString + (unsigned)3) >> 2);
3588    if (client->swapped)
3589    {
3590	swaps(&stuff->length, whichbyte);
3591    }
3592    ResetCurrentRequest(client);
3593    return (client->noClientException);
3594}
3595
3596static int
3597SendConnSetup(ClientPtr client, char *reason)
3598{
3599    xWindowRoot *root;
3600    int i;
3601    int numScreens;
3602    char* lConnectionInfo;
3603    xConnSetupPrefix* lconnSetupPrefix;
3604
3605    if (reason)
3606    {
3607	xConnSetupPrefix csp;
3608
3609	csp.success = xFalse;
3610	csp.lengthReason = strlen(reason);
3611	csp.length = (csp.lengthReason + (unsigned)3) >> 2;
3612	csp.majorVersion = X_PROTOCOL;
3613	csp.minorVersion = X_PROTOCOL_REVISION;
3614	if (client->swapped)
3615	    WriteSConnSetupPrefix(client, &csp);
3616	else
3617	    (void)WriteToClient(client, sz_xConnSetupPrefix, (char *) &csp);
3618        (void)WriteToClient(client, (int)csp.lengthReason, reason);
3619	return (client->noClientException = -1);
3620    }
3621
3622    numScreens = screenInfo.numScreens;
3623    lConnectionInfo = ConnectionInfo;
3624    lconnSetupPrefix = &connSetupPrefix;
3625
3626    /* We're about to start speaking X protocol back to the client by
3627     * sending the connection setup info.  This means the authorization
3628     * step is complete, and we can count the client as an
3629     * authorized one.
3630     */
3631    nClients++;
3632
3633    client->requestVector = client->swapped ? SwappedProcVector : ProcVector;
3634    client->sequence = 0;
3635    ((xConnSetup *)lConnectionInfo)->ridBase = client->clientAsMask;
3636    ((xConnSetup *)lConnectionInfo)->ridMask = RESOURCE_ID_MASK;
3637#ifdef MATCH_CLIENT_ENDIAN
3638    ((xConnSetup *)lConnectionInfo)->imageByteOrder = ClientOrder (client);
3639    ((xConnSetup *)lConnectionInfo)->bitmapBitOrder = ClientOrder (client);
3640#endif
3641    /* fill in the "currentInputMask" */
3642    root = (xWindowRoot *)(lConnectionInfo + connBlockScreenStart);
3643#ifdef PANORAMIX
3644    if (noPanoramiXExtension)
3645	numScreens = screenInfo.numScreens;
3646    else
3647        numScreens = ((xConnSetup *)ConnectionInfo)->numRoots;
3648#endif
3649
3650    for (i=0; i<numScreens; i++)
3651    {
3652	unsigned int j;
3653	xDepth *pDepth;
3654
3655        root->currentInputMask = WindowTable[i]->eventMask |
3656			         wOtherEventMasks (WindowTable[i]);
3657	pDepth = (xDepth *)(root + 1);
3658	for (j = 0; j < root->nDepths; j++)
3659	{
3660	    pDepth = (xDepth *)(((char *)(pDepth + 1)) +
3661				pDepth->nVisuals * sizeof(xVisualType));
3662	}
3663	root = (xWindowRoot *)pDepth;
3664    }
3665
3666    if (client->swapped)
3667    {
3668	WriteSConnSetupPrefix(client, lconnSetupPrefix);
3669	WriteSConnectionInfo(client,
3670			     (unsigned long)(lconnSetupPrefix->length << 2),
3671			     lConnectionInfo);
3672    }
3673    else
3674    {
3675	(void)WriteToClient(client, sizeof(xConnSetupPrefix),
3676			    (char *) lconnSetupPrefix);
3677	(void)WriteToClient(client, (int)(lconnSetupPrefix->length << 2),
3678			    lConnectionInfo);
3679    }
3680    client->clientState = ClientStateRunning;
3681    if (ClientStateCallback)
3682    {
3683	NewClientInfoRec clientinfo;
3684
3685        clientinfo.client = client;
3686        clientinfo.prefix = lconnSetupPrefix;
3687        clientinfo.setup = (xConnSetup *)lConnectionInfo;
3688	CallCallbacks((&ClientStateCallback), (pointer)&clientinfo);
3689    }
3690    return (client->noClientException);
3691}
3692
3693int
3694ProcEstablishConnection(ClientPtr client)
3695{
3696    char *reason, *auth_proto, *auth_string;
3697    xConnClientPrefix *prefix;
3698    REQUEST(xReq);
3699
3700    prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq);
3701    auth_proto = (char *)prefix + sz_xConnClientPrefix;
3702    auth_string = auth_proto + ((prefix->nbytesAuthProto + 3) & ~3);
3703    if ((prefix->majorVersion != X_PROTOCOL) ||
3704	(prefix->minorVersion != X_PROTOCOL_REVISION))
3705	reason = "Protocol version mismatch";
3706    else
3707	reason = ClientAuthorized(client,
3708				  (unsigned short)prefix->nbytesAuthProto,
3709				  auth_proto,
3710				  (unsigned short)prefix->nbytesAuthString,
3711				  auth_string);
3712    /*
3713     * If Kerberos is being used for this client, the clientState
3714     * will be set to ClientStateAuthenticating at this point.
3715     * More messages need to be exchanged among the X server, Kerberos
3716     * server, and client to figure out if everyone is authorized.
3717     * So we don't want to send the connection setup info yet, since
3718     * the auth step isn't really done.
3719     */
3720    if (client->clientState == ClientStateCheckingSecurity)
3721	client->clientState = ClientStateCheckedSecurity;
3722    else if (client->clientState != ClientStateAuthenticating)
3723	return(SendConnSetup(client, reason));
3724    return(client->noClientException);
3725}
3726
3727_X_EXPORT void
3728SendErrorToClient(ClientPtr client, unsigned majorCode, unsigned minorCode,
3729                  XID resId, int errorCode)
3730{
3731    xError rep;
3732
3733    rep.type = X_Error;
3734    rep.sequenceNumber = client->sequence;
3735    rep.errorCode = errorCode;
3736    rep.majorCode = majorCode;
3737    rep.minorCode = minorCode;
3738    rep.resourceID = resId;
3739
3740    WriteEventsToClient (client, 1, (xEvent *)&rep);
3741}
3742
3743void
3744MarkClientException(ClientPtr client)
3745{
3746    client->noClientException = -1;
3747}
3748