dispatch.c revision f7df2e56
105b261ecSmrg/************************************************************
205b261ecSmrg
305b261ecSmrgCopyright 1987, 1989, 1998  The Open Group
405b261ecSmrg
505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its
605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that
705b261ecSmrgthe above copyright notice appear in all copies and that both that
805b261ecSmrgcopyright notice and this permission notice appear in supporting
905b261ecSmrgdocumentation.
1005b261ecSmrg
1105b261ecSmrgThe above copyright notice and this permission notice shall be included in
1205b261ecSmrgall copies or substantial portions of the Software.
1305b261ecSmrg
1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1505b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1605b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
1705b261ecSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1805b261ecSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1905b261ecSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2005b261ecSmrg
2105b261ecSmrgExcept as contained in this notice, the name of The Open Group shall not be
2205b261ecSmrgused in advertising or otherwise to promote the sale, use or other dealings
2305b261ecSmrgin this Software without prior written authorization from The Open Group.
2405b261ecSmrg
2505b261ecSmrgCopyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
2605b261ecSmrg
2705b261ecSmrg                        All Rights Reserved
2805b261ecSmrg
29f7df2e56SmrgPermission to use, copy, modify, and distribute this software and its
30f7df2e56Smrgdocumentation for any purpose and without fee is hereby granted,
3105b261ecSmrgprovided that the above copyright notice appear in all copies and that
32f7df2e56Smrgboth that copyright notice and this permission notice appear in
3305b261ecSmrgsupporting documentation, and that the name of Digital not be
3405b261ecSmrgused in advertising or publicity pertaining to distribution of the
35f7df2e56Smrgsoftware without specific, written prior permission.
3605b261ecSmrg
3705b261ecSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
3805b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
3905b261ecSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
4005b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
4105b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
4205b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
4305b261ecSmrgSOFTWARE.
4405b261ecSmrg
4505b261ecSmrg********************************************************/
4605b261ecSmrg
4705b261ecSmrg/* The panoramix components contained the following notice */
4805b261ecSmrg/*****************************************************************
4905b261ecSmrg
5005b261ecSmrgCopyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
5105b261ecSmrg
5205b261ecSmrgPermission is hereby granted, free of charge, to any person obtaining a copy
5305b261ecSmrgof this software and associated documentation files (the "Software"), to deal
5405b261ecSmrgin the Software without restriction, including without limitation the rights
5505b261ecSmrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell
5605b261ecSmrgcopies of the Software.
5705b261ecSmrg
5805b261ecSmrgThe above copyright notice and this permission notice shall be included in
5905b261ecSmrgall copies or substantial portions of the Software.
6005b261ecSmrg
6105b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6205b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6305b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
6405b261ecSmrgDIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
6505b261ecSmrgBUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
6605b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
6705b261ecSmrgIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
6805b261ecSmrg
6905b261ecSmrgExcept as contained in this notice, the name of Digital Equipment Corporation
7005b261ecSmrgshall not be used in advertising or otherwise to promote the sale, use or other
7105b261ecSmrgdealings in this Software without prior written authorization from Digital
7205b261ecSmrgEquipment Corporation.
7305b261ecSmrg
7405b261ecSmrg******************************************************************/
7505b261ecSmrg
7605b261ecSmrg/* XSERVER_DTRACE additions:
779ace9065Smrg * Copyright (c) 2005-2006, Oracle and/or its affiliates. All rights reserved.
7805b261ecSmrg *
7905b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a
806747b715Smrg * copy of this software and associated documentation files (the "Software"),
816747b715Smrg * to deal in the Software without restriction, including without limitation
826747b715Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
836747b715Smrg * and/or sell copies of the Software, and to permit persons to whom the
846747b715Smrg * Software is furnished to do so, subject to the following conditions:
856747b715Smrg *
866747b715Smrg * The above copyright notice and this permission notice (including the next
876747b715Smrg * paragraph) shall be included in all copies or substantial portions of the
886747b715Smrg * Software.
896747b715Smrg *
906747b715Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
916747b715Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
926747b715Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
936747b715Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
946747b715Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
956747b715Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
966747b715Smrg * DEALINGS IN THE SOFTWARE.
9705b261ecSmrg */
9805b261ecSmrg
9905b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
10005b261ecSmrg#include <dix-config.h>
1016747b715Smrg#include <version-config.h>
10205b261ecSmrg#endif
10305b261ecSmrg
10405b261ecSmrg#ifdef PANORAMIX_DEBUG
10505b261ecSmrg#include <stdio.h>
10605b261ecSmrgint ProcInitialConnection();
10705b261ecSmrg#endif
10805b261ecSmrg
10905b261ecSmrg#include "windowstr.h"
11005b261ecSmrg#include <X11/fonts/fontstruct.h>
111f7df2e56Smrg#include <X11/fonts/fontutil.h>
11205b261ecSmrg#include "dixfontstr.h"
11305b261ecSmrg#include "gcstruct.h"
11405b261ecSmrg#include "selection.h"
11505b261ecSmrg#include "colormapst.h"
11605b261ecSmrg#include "cursorstr.h"
11705b261ecSmrg#include "scrnintstr.h"
11805b261ecSmrg#include "opaque.h"
11905b261ecSmrg#include "input.h"
12005b261ecSmrg#include "servermd.h"
12105b261ecSmrg#include "extnsionst.h"
12205b261ecSmrg#include "dixfont.h"
12305b261ecSmrg#include "dispatch.h"
12405b261ecSmrg#include "swaprep.h"
12505b261ecSmrg#include "swapreq.h"
1264642e01fSmrg#include "privates.h"
12705b261ecSmrg#include "xace.h"
12805b261ecSmrg#include "inputstr.h"
1296747b715Smrg#include "xkbsrv.h"
1306747b715Smrg#include "site.h"
131f7df2e56Smrg#include "client.h"
13205b261ecSmrg
13305b261ecSmrg#ifdef XSERVER_DTRACE
1344642e01fSmrg#include "registry.h"
135f7df2e56Smrg#include "probes.h"
13605b261ecSmrg#endif
13705b261ecSmrg
13805b261ecSmrg#define mskcnt ((MAXCLIENTS + 31) / 32)
13905b261ecSmrg#define BITMASK(i) (1U << ((i) & 31))
14005b261ecSmrg#define MASKIDX(i) ((i) >> 5)
14105b261ecSmrg#define MASKWORD(buf, i) buf[MASKIDX(i)]
14205b261ecSmrg#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i)
14305b261ecSmrg#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i)
14405b261ecSmrg#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i))
14505b261ecSmrg
1466747b715SmrgxConnSetupPrefix connSetupPrefix;
1476747b715Smrg
1486747b715SmrgPaddingInfo PixmapWidthPaddingInfo[33];
14905b261ecSmrg
15005b261ecSmrgstatic ClientPtr grabClient;
151f7df2e56Smrg
15205b261ecSmrg#define GrabNone 0
15305b261ecSmrg#define GrabActive 1
15405b261ecSmrg#define GrabKickout 2
15505b261ecSmrgstatic int grabState = GrabNone;
15605b261ecSmrgstatic long grabWaiters[mskcnt];
1576747b715SmrgCallbackListPtr ServerGrabCallback = NULL;
15805b261ecSmrgHWEventQueuePtr checkForInput[2];
1596747b715Smrgint connBlockScreenStart;
16005b261ecSmrg
16105b261ecSmrgstatic void KillAllClients(void);
16205b261ecSmrg
163f7df2e56Smrgstatic int nextFreeClientID;    /* always MIN free client ID */
16405b261ecSmrg
165f7df2e56Smrgstatic int nClients;            /* number of authorized clients */
16605b261ecSmrg
1676747b715SmrgCallbackListPtr ClientStateCallback;
16805b261ecSmrg
16905b261ecSmrg/* dispatchException & isItTimeToYield must be declared volatile since they
17005b261ecSmrg * are modified by signal handlers - otherwise optimizer may assume it doesn't
17105b261ecSmrg * need to actually check value in memory when used and may miss changes from
17205b261ecSmrg * signal handlers.
17305b261ecSmrg */
1746747b715Smrgvolatile char dispatchException = 0;
1756747b715Smrgvolatile char isItTimeToYield;
17605b261ecSmrg
17705b261ecSmrg#define SAME_SCREENS(a, b) (\
17805b261ecSmrg    (a.pScreen == b.pScreen))
17905b261ecSmrg
1804642e01fSmrgvoid
18105b261ecSmrgSetInputCheck(HWEventQueuePtr c0, HWEventQueuePtr c1)
18205b261ecSmrg{
18305b261ecSmrg    checkForInput[0] = c0;
18405b261ecSmrg    checkForInput[1] = c1;
18505b261ecSmrg}
18605b261ecSmrg
1876747b715Smrgvoid
18805b261ecSmrgUpdateCurrentTime(void)
18905b261ecSmrg{
19005b261ecSmrg    TimeStamp systime;
19105b261ecSmrg
19205b261ecSmrg    /* To avoid time running backwards, we must call GetTimeInMillis before
19305b261ecSmrg     * calling ProcessInputEvents.
19405b261ecSmrg     */
19505b261ecSmrg    systime.months = currentTime.months;
19605b261ecSmrg    systime.milliseconds = GetTimeInMillis();
19705b261ecSmrg    if (systime.milliseconds < currentTime.milliseconds)
198f7df2e56Smrg        systime.months++;
19905b261ecSmrg    if (*checkForInput[0] != *checkForInput[1])
200f7df2e56Smrg        ProcessInputEvents();
20105b261ecSmrg    if (CompareTimeStamps(systime, currentTime) == LATER)
202f7df2e56Smrg        currentTime = systime;
20305b261ecSmrg}
20405b261ecSmrg
20505b261ecSmrg/* Like UpdateCurrentTime, but can't call ProcessInputEvents */
2066747b715Smrgvoid
20705b261ecSmrgUpdateCurrentTimeIf(void)
20805b261ecSmrg{
20905b261ecSmrg    TimeStamp systime;
21005b261ecSmrg
21105b261ecSmrg    systime.months = currentTime.months;
21205b261ecSmrg    systime.milliseconds = GetTimeInMillis();
21305b261ecSmrg    if (systime.milliseconds < currentTime.milliseconds)
214f7df2e56Smrg        systime.months++;
215f7df2e56Smrg    if (CompareTimeStamps(systime, currentTime) == LATER)
216f7df2e56Smrg        currentTime = systime;
21705b261ecSmrg}
21805b261ecSmrg
21905b261ecSmrg#undef SMART_DEBUG
22005b261ecSmrg
221f7df2e56Smrg/* in milliseconds */
222f7df2e56Smrg#define SMART_SCHEDULE_DEFAULT_INTERVAL	5
223f7df2e56Smrg#define SMART_SCHEDULE_MAX_SLICE	15
22405b261ecSmrg
225f7df2e56Smrg#if defined(WIN32) && !defined(__CYGWIN__)
226f7df2e56SmrgBool SmartScheduleDisable = TRUE;
227f7df2e56Smrg#else
2286747b715SmrgBool SmartScheduleDisable = FALSE;
229f7df2e56Smrg#endif
2306747b715Smrglong SmartScheduleSlice = SMART_SCHEDULE_DEFAULT_INTERVAL;
2316747b715Smrglong SmartScheduleInterval = SMART_SCHEDULE_DEFAULT_INTERVAL;
2326747b715Smrglong SmartScheduleMaxSlice = SMART_SCHEDULE_MAX_SLICE;
2336747b715Smrglong SmartScheduleTime;
2346747b715Smrgint SmartScheduleLatencyLimited = 0;
235f7df2e56Smrgstatic ClientPtr SmartLastClient;
236f7df2e56Smrgstatic int SmartLastIndex[SMART_MAX_PRIORITY - SMART_MIN_PRIORITY + 1];
23705b261ecSmrg
23805b261ecSmrg#ifdef SMART_DEBUG
239f7df2e56Smrglong SmartLastPrint;
24005b261ecSmrg#endif
24105b261ecSmrg
242f7df2e56Smrgvoid Dispatch(void);
24305b261ecSmrg
24405b261ecSmrgstatic int
245f7df2e56SmrgSmartScheduleClient(int *clientReady, int nready)
24605b261ecSmrg{
247f7df2e56Smrg    ClientPtr pClient;
248f7df2e56Smrg    int i;
249f7df2e56Smrg    int client;
250f7df2e56Smrg    int bestPrio, best = 0;
251f7df2e56Smrg    int bestRobin, robin;
252f7df2e56Smrg    long now = SmartScheduleTime;
253f7df2e56Smrg    long idle;
25405b261ecSmrg
25505b261ecSmrg    bestPrio = -0x7fffffff;
25605b261ecSmrg    bestRobin = 0;
25705b261ecSmrg    idle = 2 * SmartScheduleSlice;
258f7df2e56Smrg    for (i = 0; i < nready; i++) {
259f7df2e56Smrg        client = clientReady[i];
260f7df2e56Smrg        pClient = clients[client];
261f7df2e56Smrg        /* Praise clients which haven't run in a while */
262f7df2e56Smrg        if ((now - pClient->smart_stop_tick) >= idle) {
263f7df2e56Smrg            if (pClient->smart_priority < 0)
264f7df2e56Smrg                pClient->smart_priority++;
265f7df2e56Smrg        }
266f7df2e56Smrg
267f7df2e56Smrg        /* check priority to select best client */
268f7df2e56Smrg        robin =
269f7df2e56Smrg            (pClient->index -
270f7df2e56Smrg             SmartLastIndex[pClient->smart_priority -
271f7df2e56Smrg                            SMART_MIN_PRIORITY]) & 0xff;
272f7df2e56Smrg        if (pClient->smart_priority > bestPrio ||
273f7df2e56Smrg            (pClient->smart_priority == bestPrio && robin > bestRobin)) {
274f7df2e56Smrg            bestPrio = pClient->smart_priority;
275f7df2e56Smrg            bestRobin = robin;
276f7df2e56Smrg            best = client;
277f7df2e56Smrg        }
27805b261ecSmrg#ifdef SMART_DEBUG
279f7df2e56Smrg        if ((now - SmartLastPrint) >= 5000)
280f7df2e56Smrg            fprintf(stderr, " %2d: %3d", client, pClient->smart_priority);
28105b261ecSmrg#endif
28205b261ecSmrg    }
28305b261ecSmrg#ifdef SMART_DEBUG
284f7df2e56Smrg    if ((now - SmartLastPrint) >= 5000) {
285f7df2e56Smrg        fprintf(stderr, " use %2d\n", best);
286f7df2e56Smrg        SmartLastPrint = now;
28705b261ecSmrg    }
28805b261ecSmrg#endif
28905b261ecSmrg    pClient = clients[best];
290f7df2e56Smrg    SmartLastIndex[bestPrio - SMART_MIN_PRIORITY] = pClient->index;
29105b261ecSmrg    /*
29205b261ecSmrg     * Set current client pointer
29305b261ecSmrg     */
294f7df2e56Smrg    if (SmartLastClient != pClient) {
295f7df2e56Smrg        pClient->smart_start_tick = now;
296f7df2e56Smrg        SmartLastClient = pClient;
29705b261ecSmrg    }
29805b261ecSmrg    /*
29905b261ecSmrg     * Adjust slice
30005b261ecSmrg     */
301f7df2e56Smrg    if (nready == 1 && SmartScheduleLatencyLimited == 0) {
302f7df2e56Smrg        /*
303f7df2e56Smrg         * If it's been a long time since another client
304f7df2e56Smrg         * has run, bump the slice up to get maximal
305f7df2e56Smrg         * performance from a single client
306f7df2e56Smrg         */
307f7df2e56Smrg        if ((now - pClient->smart_start_tick) > 1000 &&
308f7df2e56Smrg            SmartScheduleSlice < SmartScheduleMaxSlice) {
309f7df2e56Smrg            SmartScheduleSlice += SmartScheduleInterval;
310f7df2e56Smrg        }
31105b261ecSmrg    }
312f7df2e56Smrg    else {
313f7df2e56Smrg        SmartScheduleSlice = SmartScheduleInterval;
31405b261ecSmrg    }
31505b261ecSmrg    return best;
31605b261ecSmrg}
31705b261ecSmrg
318b1d344b3Smrgvoid
319b1d344b3SmrgEnableLimitedSchedulingLatency(void)
320b1d344b3Smrg{
321b1d344b3Smrg    ++SmartScheduleLatencyLimited;
322b1d344b3Smrg    SmartScheduleSlice = SmartScheduleInterval;
323b1d344b3Smrg}
324b1d344b3Smrg
325b1d344b3Smrgvoid
326b1d344b3SmrgDisableLimitedSchedulingLatency(void)
327b1d344b3Smrg{
328b1d344b3Smrg    --SmartScheduleLatencyLimited;
329b1d344b3Smrg
330b1d344b3Smrg    /* protect against bugs */
331b1d344b3Smrg    if (SmartScheduleLatencyLimited < 0)
332f7df2e56Smrg        SmartScheduleLatencyLimited = 0;
333b1d344b3Smrg}
334b1d344b3Smrg
33505b261ecSmrgvoid
33605b261ecSmrgDispatch(void)
33705b261ecSmrg{
338f7df2e56Smrg    int *clientReady;           /* array of request ready clients */
339f7df2e56Smrg    int result;
340f7df2e56Smrg    ClientPtr client;
341f7df2e56Smrg    int nready;
342f7df2e56Smrg    HWEventQueuePtr *icheck = checkForInput;
343f7df2e56Smrg    long start_tick;
34405b261ecSmrg
34505b261ecSmrg    nextFreeClientID = 1;
34605b261ecSmrg    nClients = 0;
34705b261ecSmrg
348f7df2e56Smrg    clientReady = xallocarray(MaxClients, sizeof(int));
34905b261ecSmrg    if (!clientReady)
350f7df2e56Smrg        return;
35105b261ecSmrg
352b1d344b3Smrg    SmartScheduleSlice = SmartScheduleInterval;
353f7df2e56Smrg    while (!dispatchException) {
354f7df2e56Smrg        if (*icheck[0] != *icheck[1]) {
355f7df2e56Smrg            ProcessInputEvents();
356f7df2e56Smrg            FlushIfCriticalOutputPending();
357f7df2e56Smrg        }
358f7df2e56Smrg
359f7df2e56Smrg        nready = WaitForSomething(clientReady);
360f7df2e56Smrg
361f7df2e56Smrg        if (nready && !SmartScheduleDisable) {
362f7df2e56Smrg            clientReady[0] = SmartScheduleClient(clientReady, nready);
363f7df2e56Smrg            nready = 1;
364f7df2e56Smrg        }
365f7df2e56Smrg       /*****************
366f7df2e56Smrg	*  Handle events in round robin fashion, doing input between
367f7df2e56Smrg	*  each round
36805b261ecSmrg	*****************/
36905b261ecSmrg
370f7df2e56Smrg        while (!dispatchException && (--nready >= 0)) {
371f7df2e56Smrg            client = clients[clientReady[nready]];
372f7df2e56Smrg            if (!client) {
373f7df2e56Smrg                /* KillClient can cause this to happen */
374f7df2e56Smrg                continue;
375f7df2e56Smrg            }
376f7df2e56Smrg            /* GrabServer activation can cause this to be true */
377f7df2e56Smrg            if (grabState == GrabKickout) {
378f7df2e56Smrg                grabState = GrabActive;
379f7df2e56Smrg                break;
380f7df2e56Smrg            }
381f7df2e56Smrg            isItTimeToYield = FALSE;
382f7df2e56Smrg
383f7df2e56Smrg            start_tick = SmartScheduleTime;
384f7df2e56Smrg            while (!isItTimeToYield) {
385f7df2e56Smrg                if (*icheck[0] != *icheck[1])
386f7df2e56Smrg                    ProcessInputEvents();
387f7df2e56Smrg
388f7df2e56Smrg                FlushIfCriticalOutputPending();
389f7df2e56Smrg                if (!SmartScheduleDisable &&
390f7df2e56Smrg                    (SmartScheduleTime - start_tick) >= SmartScheduleSlice) {
391f7df2e56Smrg                    /* Penalize clients which consume ticks */
392f7df2e56Smrg                    if (client->smart_priority > SMART_MIN_PRIORITY)
393f7df2e56Smrg                        client->smart_priority--;
394f7df2e56Smrg                    break;
395f7df2e56Smrg                }
396f7df2e56Smrg                /* now, finally, deal with client requests */
397f7df2e56Smrg
398f7df2e56Smrg                /* Update currentTime so request time checks, such as for input
399f7df2e56Smrg                 * device grabs, are calculated correctly */
400f7df2e56Smrg                UpdateCurrentTimeIf();
401f7df2e56Smrg                result = ReadRequestFromClient(client);
402f7df2e56Smrg                if (result <= 0) {
403f7df2e56Smrg                    if (result < 0)
404f7df2e56Smrg                        CloseDownClient(client);
405f7df2e56Smrg                    break;
406f7df2e56Smrg                }
407f7df2e56Smrg
408f7df2e56Smrg                client->sequence++;
409f7df2e56Smrg                client->majorOp = ((xReq *) client->requestBuffer)->reqType;
410f7df2e56Smrg                client->minorOp = 0;
411f7df2e56Smrg                if (client->majorOp >= EXTENSION_BASE) {
412f7df2e56Smrg                    ExtensionEntry *ext = GetExtensionEntry(client->majorOp);
413f7df2e56Smrg
414f7df2e56Smrg                    if (ext)
415f7df2e56Smrg                        client->minorOp = ext->MinorOpcode(client);
416f7df2e56Smrg                }
41705b261ecSmrg#ifdef XSERVER_DTRACE
418f7df2e56Smrg                if (XSERVER_REQUEST_START_ENABLED())
419f7df2e56Smrg                    XSERVER_REQUEST_START(LookupMajorName(client->majorOp),
420f7df2e56Smrg                                          client->majorOp,
421f7df2e56Smrg                                          ((xReq *) client->requestBuffer)->length,
422f7df2e56Smrg                                          client->index,
423f7df2e56Smrg                                          client->requestBuffer);
42405b261ecSmrg#endif
425f7df2e56Smrg                if (result > (maxBigRequestSize << 2))
426f7df2e56Smrg                    result = BadLength;
427f7df2e56Smrg                else {
428f7df2e56Smrg                    result = XaceHookDispatch(client, client->majorOp);
429f7df2e56Smrg                    if (result == Success)
430f7df2e56Smrg                        result =
431f7df2e56Smrg                            (*client->requestVector[client->majorOp]) (client);
432f7df2e56Smrg                    XaceHookAuditEnd(client, result);
433f7df2e56Smrg                }
43405b261ecSmrg#ifdef XSERVER_DTRACE
435f7df2e56Smrg                if (XSERVER_REQUEST_DONE_ENABLED())
436f7df2e56Smrg                    XSERVER_REQUEST_DONE(LookupMajorName(client->majorOp),
437f7df2e56Smrg                                         client->majorOp, client->sequence,
438f7df2e56Smrg                                         client->index, result);
43905b261ecSmrg#endif
44005b261ecSmrg
441f7df2e56Smrg                if (client->noClientException != Success) {
442f7df2e56Smrg                    CloseDownClient(client);
443f7df2e56Smrg                    break;
444f7df2e56Smrg                }
445f7df2e56Smrg                else if (result != Success) {
446f7df2e56Smrg                    SendErrorToClient(client, client->majorOp,
447f7df2e56Smrg                                      client->minorOp,
448f7df2e56Smrg                                      client->errorValue, result);
449f7df2e56Smrg                    break;
450f7df2e56Smrg                }
451f7df2e56Smrg            }
452f7df2e56Smrg            FlushAllOutput();
453f7df2e56Smrg            client = clients[clientReady[nready]];
454f7df2e56Smrg            if (client)
455f7df2e56Smrg                client->smart_stop_tick = SmartScheduleTime;
456f7df2e56Smrg        }
457f7df2e56Smrg        dispatchException &= ~DE_PRIORITYCHANGE;
45805b261ecSmrg    }
45905b261ecSmrg#if defined(DDXBEFORERESET)
460f7df2e56Smrg    ddxBeforeReset();
46105b261ecSmrg#endif
46205b261ecSmrg    KillAllClients();
4636747b715Smrg    free(clientReady);
46405b261ecSmrg    dispatchException &= ~DE_RESET;
465b1d344b3Smrg    SmartScheduleLatencyLimited = 0;
466f7df2e56Smrg    ResetOsBuffers();
46705b261ecSmrg}
46805b261ecSmrg
469f7df2e56Smrgstatic int VendorRelease = VENDOR_RELEASE;
470f7df2e56Smrgstatic const char *VendorString = VENDOR_NAME;
4716747b715Smrg
4726747b715Smrgvoid
4736747b715SmrgSetVendorRelease(int release)
4746747b715Smrg{
4756747b715Smrg    VendorRelease = release;
4766747b715Smrg}
4776747b715Smrg
4786747b715Smrgvoid
479f7df2e56SmrgSetVendorString(const char *vendor)
4806747b715Smrg{
481f7df2e56Smrg    VendorString = vendor;
4826747b715Smrg}
4836747b715Smrg
4846747b715SmrgBool
4856747b715SmrgCreateConnectionBlock(void)
4866747b715Smrg{
4876747b715Smrg    xConnSetup setup;
4886747b715Smrg    xWindowRoot root;
489f7df2e56Smrg    xDepth depth;
4906747b715Smrg    xVisualType visual;
4916747b715Smrg    xPixmapFormat format;
4926747b715Smrg    unsigned long vid;
493f7df2e56Smrg    int i, j, k, lenofblock, sizesofar = 0;
4946747b715Smrg    char *pBuf;
4956747b715Smrg
4966747b715Smrg    memset(&setup, 0, sizeof(xConnSetup));
4976747b715Smrg    /* Leave off the ridBase and ridMask, these must be sent with
4986747b715Smrg       connection */
4996747b715Smrg
5006747b715Smrg    setup.release = VendorRelease;
5016747b715Smrg    /*
5026747b715Smrg     * per-server image and bitmap parameters are defined in Xmd.h
5036747b715Smrg     */
5046747b715Smrg    setup.imageByteOrder = screenInfo.imageByteOrder;
5056747b715Smrg
5066747b715Smrg    setup.bitmapScanlineUnit = screenInfo.bitmapScanlineUnit;
5076747b715Smrg    setup.bitmapScanlinePad = screenInfo.bitmapScanlinePad;
5086747b715Smrg
5096747b715Smrg    setup.bitmapBitOrder = screenInfo.bitmapBitOrder;
5106747b715Smrg    setup.motionBufferSize = NumMotionEvents();
5116747b715Smrg    setup.numRoots = screenInfo.numScreens;
5126747b715Smrg    setup.nbytesVendor = strlen(VendorString);
5136747b715Smrg    setup.numFormats = screenInfo.numPixmapFormats;
5146747b715Smrg    setup.maxRequestSize = MAX_REQUEST_SIZE;
5156747b715Smrg    QueryMinMaxKeyCodes(&setup.minKeyCode, &setup.maxKeyCode);
5166747b715Smrg
5176747b715Smrg    lenofblock = sizeof(xConnSetup) +
518f7df2e56Smrg        pad_to_int32(setup.nbytesVendor) +
519f7df2e56Smrg        (setup.numFormats * sizeof(xPixmapFormat)) +
520f7df2e56Smrg        (setup.numRoots * sizeof(xWindowRoot));
5216747b715Smrg    ConnectionInfo = malloc(lenofblock);
5226747b715Smrg    if (!ConnectionInfo)
523f7df2e56Smrg        return FALSE;
5246747b715Smrg
525f7df2e56Smrg    memmove(ConnectionInfo, (char *) &setup, sizeof(xConnSetup));
5266747b715Smrg    sizesofar = sizeof(xConnSetup);
5276747b715Smrg    pBuf = ConnectionInfo + sizeof(xConnSetup);
5286747b715Smrg
529f7df2e56Smrg    memmove(pBuf, VendorString, (int) setup.nbytesVendor);
5306747b715Smrg    sizesofar += setup.nbytesVendor;
5316747b715Smrg    pBuf += setup.nbytesVendor;
532f7df2e56Smrg    i = padding_for_int32(setup.nbytesVendor);
5336747b715Smrg    sizesofar += i;
5346747b715Smrg    while (--i >= 0)
535f7df2e56Smrg        *pBuf++ = 0;
5366747b715Smrg
5376747b715Smrg    memset(&format, 0, sizeof(xPixmapFormat));
538f7df2e56Smrg    for (i = 0; i < screenInfo.numPixmapFormats; i++) {
539f7df2e56Smrg        format.depth = screenInfo.formats[i].depth;
540f7df2e56Smrg        format.bitsPerPixel = screenInfo.formats[i].bitsPerPixel;
541f7df2e56Smrg        format.scanLinePad = screenInfo.formats[i].scanlinePad;
542f7df2e56Smrg        memmove(pBuf, (char *) &format, sizeof(xPixmapFormat));
543f7df2e56Smrg        pBuf += sizeof(xPixmapFormat);
544f7df2e56Smrg        sizesofar += sizeof(xPixmapFormat);
5456747b715Smrg    }
5466747b715Smrg
5476747b715Smrg    connBlockScreenStart = sizesofar;
5486747b715Smrg    memset(&depth, 0, sizeof(xDepth));
5496747b715Smrg    memset(&visual, 0, sizeof(xVisualType));
550f7df2e56Smrg    for (i = 0; i < screenInfo.numScreens; i++) {
551f7df2e56Smrg        ScreenPtr pScreen;
552f7df2e56Smrg        DepthPtr pDepth;
553f7df2e56Smrg        VisualPtr pVisual;
554f7df2e56Smrg
555f7df2e56Smrg        pScreen = screenInfo.screens[i];
556f7df2e56Smrg        root.windowId = pScreen->root->drawable.id;
557f7df2e56Smrg        root.defaultColormap = pScreen->defColormap;
558f7df2e56Smrg        root.whitePixel = pScreen->whitePixel;
559f7df2e56Smrg        root.blackPixel = pScreen->blackPixel;
560f7df2e56Smrg        root.currentInputMask = 0;      /* filled in when sent */
561f7df2e56Smrg        root.pixWidth = pScreen->width;
562f7df2e56Smrg        root.pixHeight = pScreen->height;
563f7df2e56Smrg        root.mmWidth = pScreen->mmWidth;
564f7df2e56Smrg        root.mmHeight = pScreen->mmHeight;
565f7df2e56Smrg        root.minInstalledMaps = pScreen->minInstalledCmaps;
566f7df2e56Smrg        root.maxInstalledMaps = pScreen->maxInstalledCmaps;
567f7df2e56Smrg        root.rootVisualID = pScreen->rootVisual;
568f7df2e56Smrg        root.backingStore = pScreen->backingStoreSupport;
569f7df2e56Smrg        root.saveUnders = FALSE;
570f7df2e56Smrg        root.rootDepth = pScreen->rootDepth;
571f7df2e56Smrg        root.nDepths = pScreen->numDepths;
572f7df2e56Smrg        memmove(pBuf, (char *) &root, sizeof(xWindowRoot));
573f7df2e56Smrg        sizesofar += sizeof(xWindowRoot);
574f7df2e56Smrg        pBuf += sizeof(xWindowRoot);
575f7df2e56Smrg
576f7df2e56Smrg        pDepth = pScreen->allowedDepths;
577f7df2e56Smrg        for (j = 0; j < pScreen->numDepths; j++, pDepth++) {
578f7df2e56Smrg            lenofblock += sizeof(xDepth) +
579f7df2e56Smrg                (pDepth->numVids * sizeof(xVisualType));
580f7df2e56Smrg            pBuf = (char *) realloc(ConnectionInfo, lenofblock);
581f7df2e56Smrg            if (!pBuf) {
582f7df2e56Smrg                free(ConnectionInfo);
583f7df2e56Smrg                return FALSE;
584f7df2e56Smrg            }
585f7df2e56Smrg            ConnectionInfo = pBuf;
586f7df2e56Smrg            pBuf += sizesofar;
587f7df2e56Smrg            depth.depth = pDepth->depth;
588f7df2e56Smrg            depth.nVisuals = pDepth->numVids;
589f7df2e56Smrg            memmove(pBuf, (char *) &depth, sizeof(xDepth));
590f7df2e56Smrg            pBuf += sizeof(xDepth);
591f7df2e56Smrg            sizesofar += sizeof(xDepth);
592f7df2e56Smrg            for (k = 0; k < pDepth->numVids; k++) {
593f7df2e56Smrg                vid = pDepth->vids[k];
594f7df2e56Smrg                for (pVisual = pScreen->visuals;
595f7df2e56Smrg                     pVisual->vid != vid; pVisual++);
596f7df2e56Smrg                visual.visualID = vid;
597f7df2e56Smrg                visual.class = pVisual->class;
598f7df2e56Smrg                visual.bitsPerRGB = pVisual->bitsPerRGBValue;
599f7df2e56Smrg                visual.colormapEntries = pVisual->ColormapEntries;
600f7df2e56Smrg                visual.redMask = pVisual->redMask;
601f7df2e56Smrg                visual.greenMask = pVisual->greenMask;
602f7df2e56Smrg                visual.blueMask = pVisual->blueMask;
603f7df2e56Smrg                memmove(pBuf, (char *) &visual, sizeof(xVisualType));
604f7df2e56Smrg                pBuf += sizeof(xVisualType);
605f7df2e56Smrg                sizesofar += sizeof(xVisualType);
606f7df2e56Smrg            }
607f7df2e56Smrg        }
6086747b715Smrg    }
6096747b715Smrg    connSetupPrefix.success = xTrue;
610f7df2e56Smrg    connSetupPrefix.length = lenofblock / 4;
6116747b715Smrg    connSetupPrefix.majorVersion = X_PROTOCOL;
6126747b715Smrg    connSetupPrefix.minorVersion = X_PROTOCOL_REVISION;
6136747b715Smrg    return TRUE;
6146747b715Smrg}
6156747b715Smrg
6166747b715Smrgint
61705b261ecSmrgProcBadRequest(ClientPtr client)
61805b261ecSmrg{
6196747b715Smrg    return BadRequest;
62005b261ecSmrg}
62105b261ecSmrg
62205b261ecSmrgint
62305b261ecSmrgProcCreateWindow(ClientPtr client)
62405b261ecSmrg{
62505b261ecSmrg    WindowPtr pParent, pWin;
626f7df2e56Smrg
62705b261ecSmrg    REQUEST(xCreateWindowReq);
6284642e01fSmrg    int len, rc;
62905b261ecSmrg
63005b261ecSmrg    REQUEST_AT_LEAST_SIZE(xCreateWindowReq);
631f7df2e56Smrg
63205b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->wid, client);
6334642e01fSmrg    rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess);
63405b261ecSmrg    if (rc != Success)
63505b261ecSmrg        return rc;
6366747b715Smrg    len = client->req_len - bytes_to_int32(sizeof(xCreateWindowReq));
63705b261ecSmrg    if (Ones(stuff->mask) != len)
63805b261ecSmrg        return BadLength;
639f7df2e56Smrg    if (!stuff->width || !stuff->height) {
640f7df2e56Smrg        client->errorValue = 0;
64105b261ecSmrg        return BadValue;
64205b261ecSmrg    }
64305b261ecSmrg    pWin = CreateWindow(stuff->wid, pParent, stuff->x,
644f7df2e56Smrg                        stuff->y, stuff->width, stuff->height,
645f7df2e56Smrg                        stuff->borderWidth, stuff->class,
646f7df2e56Smrg                        stuff->mask, (XID *) &stuff[1],
647f7df2e56Smrg                        (int) stuff->depth, client, stuff->visual, &rc);
648f7df2e56Smrg    if (pWin) {
649f7df2e56Smrg        Mask mask = pWin->eventMask;
650f7df2e56Smrg
651f7df2e56Smrg        pWin->eventMask = 0;    /* subterfuge in case AddResource fails */
652f7df2e56Smrg        if (!AddResource(stuff->wid, RT_WINDOW, (void *) pWin))
653f7df2e56Smrg            return BadAlloc;
654f7df2e56Smrg        pWin->eventMask = mask;
65505b261ecSmrg    }
6566747b715Smrg    return rc;
65705b261ecSmrg}
65805b261ecSmrg
65905b261ecSmrgint
66005b261ecSmrgProcChangeWindowAttributes(ClientPtr client)
66105b261ecSmrg{
66205b261ecSmrg    WindowPtr pWin;
663f7df2e56Smrg
66405b261ecSmrg    REQUEST(xChangeWindowAttributesReq);
6656747b715Smrg    int len, rc;
6664642e01fSmrg    Mask access_mode = 0;
66705b261ecSmrg
66805b261ecSmrg    REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq);
6694642e01fSmrg    access_mode |= (stuff->valueMask & CWEventMask) ? DixReceiveAccess : 0;
6704642e01fSmrg    access_mode |= (stuff->valueMask & ~CWEventMask) ? DixSetAttrAccess : 0;
6714642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, access_mode);
67205b261ecSmrg    if (rc != Success)
67305b261ecSmrg        return rc;
6746747b715Smrg    len = client->req_len - bytes_to_int32(sizeof(xChangeWindowAttributesReq));
67505b261ecSmrg    if (len != Ones(stuff->valueMask))
67605b261ecSmrg        return BadLength;
6776747b715Smrg    return ChangeWindowAttributes(pWin,
678f7df2e56Smrg                                  stuff->valueMask, (XID *) &stuff[1], client);
67905b261ecSmrg}
68005b261ecSmrg
68105b261ecSmrgint
68205b261ecSmrgProcGetWindowAttributes(ClientPtr client)
68305b261ecSmrg{
68405b261ecSmrg    WindowPtr pWin;
685f7df2e56Smrg
68605b261ecSmrg    REQUEST(xResourceReq);
68705b261ecSmrg    xGetWindowAttributesReply wa;
68805b261ecSmrg    int rc;
68905b261ecSmrg
69005b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
6914642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
69205b261ecSmrg    if (rc != Success)
693f7df2e56Smrg        return rc;
6946747b715Smrg    memset(&wa, 0, sizeof(xGetWindowAttributesReply));
69505b261ecSmrg    GetWindowAttributes(pWin, client, &wa);
69605b261ecSmrg    WriteReplyToClient(client, sizeof(xGetWindowAttributesReply), &wa);
6976747b715Smrg    return Success;
69805b261ecSmrg}
69905b261ecSmrg
70005b261ecSmrgint
70105b261ecSmrgProcDestroyWindow(ClientPtr client)
70205b261ecSmrg{
70305b261ecSmrg    WindowPtr pWin;
704f7df2e56Smrg
70505b261ecSmrg    REQUEST(xResourceReq);
70605b261ecSmrg    int rc;
70705b261ecSmrg
70805b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
70905b261ecSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixDestroyAccess);
71005b261ecSmrg    if (rc != Success)
711f7df2e56Smrg        return rc;
7124642e01fSmrg    if (pWin->parent) {
713f7df2e56Smrg        rc = dixLookupWindow(&pWin, pWin->parent->drawable.id, client,
714f7df2e56Smrg                             DixRemoveAccess);
715f7df2e56Smrg        if (rc != Success)
716f7df2e56Smrg            return rc;
717f7df2e56Smrg        FreeResource(stuff->id, RT_NONE);
7184642e01fSmrg    }
7196747b715Smrg    return Success;
72005b261ecSmrg}
72105b261ecSmrg
72205b261ecSmrgint
72305b261ecSmrgProcDestroySubwindows(ClientPtr client)
72405b261ecSmrg{
72505b261ecSmrg    WindowPtr pWin;
726f7df2e56Smrg
72705b261ecSmrg    REQUEST(xResourceReq);
72805b261ecSmrg    int rc;
72905b261ecSmrg
73005b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
7314642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixRemoveAccess);
73205b261ecSmrg    if (rc != Success)
733f7df2e56Smrg        return rc;
73405b261ecSmrg    DestroySubwindows(pWin, client);
7356747b715Smrg    return Success;
73605b261ecSmrg}
73705b261ecSmrg
73805b261ecSmrgint
73905b261ecSmrgProcChangeSaveSet(ClientPtr client)
74005b261ecSmrg{
74105b261ecSmrg    WindowPtr pWin;
742f7df2e56Smrg
74305b261ecSmrg    REQUEST(xChangeSaveSetReq);
7446747b715Smrg    int rc;
745f7df2e56Smrg
74605b261ecSmrg    REQUEST_SIZE_MATCH(xChangeSaveSetReq);
7474642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
74805b261ecSmrg    if (rc != Success)
74905b261ecSmrg        return rc;
75005b261ecSmrg    if (client->clientAsMask == (CLIENT_BITS(pWin->drawable.id)))
75105b261ecSmrg        return BadMatch;
75205b261ecSmrg    if ((stuff->mode == SetModeInsert) || (stuff->mode == SetModeDelete))
7536747b715Smrg        return AlterSaveSetForClient(client, pWin, stuff->mode, FALSE, TRUE);
7546747b715Smrg    client->errorValue = stuff->mode;
7556747b715Smrg    return BadValue;
75605b261ecSmrg}
75705b261ecSmrg
75805b261ecSmrgint
75905b261ecSmrgProcReparentWindow(ClientPtr client)
76005b261ecSmrg{
76105b261ecSmrg    WindowPtr pWin, pParent;
762f7df2e56Smrg
76305b261ecSmrg    REQUEST(xReparentWindowReq);
7646747b715Smrg    int rc;
76505b261ecSmrg
76605b261ecSmrg    REQUEST_SIZE_MATCH(xReparentWindowReq);
7674642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
76805b261ecSmrg    if (rc != Success)
76905b261ecSmrg        return rc;
7704642e01fSmrg    rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess);
77105b261ecSmrg    if (rc != Success)
77205b261ecSmrg        return rc;
7736747b715Smrg    if (!SAME_SCREENS(pWin->drawable, pParent->drawable))
774f7df2e56Smrg        return BadMatch;
7756747b715Smrg    if ((pWin->backgroundState == ParentRelative) &&
776f7df2e56Smrg        (pParent->drawable.depth != pWin->drawable.depth))
777f7df2e56Smrg        return BadMatch;
7786747b715Smrg    if ((pWin->drawable.class != InputOnly) &&
779f7df2e56Smrg        (pParent->drawable.class == InputOnly))
780f7df2e56Smrg        return BadMatch;
7816747b715Smrg    return ReparentWindow(pWin, pParent,
782f7df2e56Smrg                          (short) stuff->x, (short) stuff->y, client);
78305b261ecSmrg}
78405b261ecSmrg
78505b261ecSmrgint
78605b261ecSmrgProcMapWindow(ClientPtr client)
78705b261ecSmrg{
78805b261ecSmrg    WindowPtr pWin;
789f7df2e56Smrg
79005b261ecSmrg    REQUEST(xResourceReq);
79105b261ecSmrg    int rc;
79205b261ecSmrg
79305b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
7944642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixShowAccess);
79505b261ecSmrg    if (rc != Success)
79605b261ecSmrg        return rc;
79705b261ecSmrg    MapWindow(pWin, client);
798f7df2e56Smrg    /* update cache to say it is mapped */
7996747b715Smrg    return Success;
80005b261ecSmrg}
80105b261ecSmrg
80205b261ecSmrgint
80305b261ecSmrgProcMapSubwindows(ClientPtr client)
80405b261ecSmrg{
80505b261ecSmrg    WindowPtr pWin;
806f7df2e56Smrg
80705b261ecSmrg    REQUEST(xResourceReq);
80805b261ecSmrg    int rc;
80905b261ecSmrg
81005b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
8114642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
81205b261ecSmrg    if (rc != Success)
81305b261ecSmrg        return rc;
81405b261ecSmrg    MapSubwindows(pWin, client);
815f7df2e56Smrg    /* update cache to say it is mapped */
8166747b715Smrg    return Success;
81705b261ecSmrg}
81805b261ecSmrg
81905b261ecSmrgint
82005b261ecSmrgProcUnmapWindow(ClientPtr client)
82105b261ecSmrg{
82205b261ecSmrg    WindowPtr pWin;
823f7df2e56Smrg
82405b261ecSmrg    REQUEST(xResourceReq);
82505b261ecSmrg    int rc;
82605b261ecSmrg
82705b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
8284642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixHideAccess);
82905b261ecSmrg    if (rc != Success)
83005b261ecSmrg        return rc;
83105b261ecSmrg    UnmapWindow(pWin, FALSE);
832f7df2e56Smrg    /* update cache to say it is mapped */
8336747b715Smrg    return Success;
83405b261ecSmrg}
83505b261ecSmrg
83605b261ecSmrgint
83705b261ecSmrgProcUnmapSubwindows(ClientPtr client)
83805b261ecSmrg{
83905b261ecSmrg    WindowPtr pWin;
840f7df2e56Smrg
84105b261ecSmrg    REQUEST(xResourceReq);
84205b261ecSmrg    int rc;
84305b261ecSmrg
84405b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
8454642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
84605b261ecSmrg    if (rc != Success)
84705b261ecSmrg        return rc;
84805b261ecSmrg    UnmapSubwindows(pWin);
8496747b715Smrg    return Success;
85005b261ecSmrg}
85105b261ecSmrg
85205b261ecSmrgint
85305b261ecSmrgProcConfigureWindow(ClientPtr client)
85405b261ecSmrg{
85505b261ecSmrg    WindowPtr pWin;
856f7df2e56Smrg
85705b261ecSmrg    REQUEST(xConfigureWindowReq);
85805b261ecSmrg    int len, rc;
85905b261ecSmrg
86005b261ecSmrg    REQUEST_AT_LEAST_SIZE(xConfigureWindowReq);
8614642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client,
862f7df2e56Smrg                         DixManageAccess | DixSetAttrAccess);
86305b261ecSmrg    if (rc != Success)
86405b261ecSmrg        return rc;
8656747b715Smrg    len = client->req_len - bytes_to_int32(sizeof(xConfigureWindowReq));
866f7df2e56Smrg    if (Ones((Mask) stuff->mask) != len)
86705b261ecSmrg        return BadLength;
868f7df2e56Smrg    return ConfigureWindow(pWin, (Mask) stuff->mask, (XID *) &stuff[1], client);
86905b261ecSmrg}
87005b261ecSmrg
87105b261ecSmrgint
87205b261ecSmrgProcCirculateWindow(ClientPtr client)
87305b261ecSmrg{
87405b261ecSmrg    WindowPtr pWin;
875f7df2e56Smrg
87605b261ecSmrg    REQUEST(xCirculateWindowReq);
87705b261ecSmrg    int rc;
87805b261ecSmrg
87905b261ecSmrg    REQUEST_SIZE_MATCH(xCirculateWindowReq);
880f7df2e56Smrg    if ((stuff->direction != RaiseLowest) && (stuff->direction != LowerHighest)) {
881f7df2e56Smrg        client->errorValue = stuff->direction;
88205b261ecSmrg        return BadValue;
88305b261ecSmrg    }
8844642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
88505b261ecSmrg    if (rc != Success)
88605b261ecSmrg        return rc;
887f7df2e56Smrg    CirculateWindow(pWin, (int) stuff->direction, client);
8886747b715Smrg    return Success;
88905b261ecSmrg}
89005b261ecSmrg
89105b261ecSmrgstatic int
892f7df2e56SmrgGetGeometry(ClientPtr client, xGetGeometryReply * rep)
89305b261ecSmrg{
89405b261ecSmrg    DrawablePtr pDraw;
89505b261ecSmrg    int rc;
896f7df2e56Smrg
89705b261ecSmrg    REQUEST(xResourceReq);
89805b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
89905b261ecSmrg
9004642e01fSmrg    rc = dixLookupDrawable(&pDraw, stuff->id, client, M_ANY, DixGetAttrAccess);
90105b261ecSmrg    if (rc != Success)
902f7df2e56Smrg        return rc;
90305b261ecSmrg
90405b261ecSmrg    rep->type = X_Reply;
90505b261ecSmrg    rep->length = 0;
90605b261ecSmrg    rep->sequenceNumber = client->sequence;
9076747b715Smrg    rep->root = pDraw->pScreen->root->drawable.id;
90805b261ecSmrg    rep->depth = pDraw->depth;
90905b261ecSmrg    rep->width = pDraw->width;
91005b261ecSmrg    rep->height = pDraw->height;
91105b261ecSmrg
912f7df2e56Smrg    if (WindowDrawable(pDraw->type)) {
913f7df2e56Smrg        WindowPtr pWin = (WindowPtr) pDraw;
914f7df2e56Smrg
915f7df2e56Smrg        rep->x = pWin->origin.x - wBorderWidth(pWin);
916f7df2e56Smrg        rep->y = pWin->origin.y - wBorderWidth(pWin);
917f7df2e56Smrg        rep->borderWidth = pWin->borderWidth;
91805b261ecSmrg    }
919f7df2e56Smrg    else {                      /* DRAWABLE_PIXMAP */
920f7df2e56Smrg
921f7df2e56Smrg        rep->x = rep->y = rep->borderWidth = 0;
92205b261ecSmrg    }
92305b261ecSmrg
92405b261ecSmrg    return Success;
92505b261ecSmrg}
92605b261ecSmrg
92705b261ecSmrgint
92805b261ecSmrgProcGetGeometry(ClientPtr client)
92905b261ecSmrg{
930f7df2e56Smrg    xGetGeometryReply rep = { .type = X_Reply };
93105b261ecSmrg    int status;
93205b261ecSmrg
93305b261ecSmrg    if ((status = GetGeometry(client, &rep)) != Success)
934f7df2e56Smrg        return status;
93505b261ecSmrg
93605b261ecSmrg    WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep);
9376747b715Smrg    return Success;
93805b261ecSmrg}
93905b261ecSmrg
94005b261ecSmrgint
94105b261ecSmrgProcQueryTree(ClientPtr client)
94205b261ecSmrg{
94305b261ecSmrg    xQueryTreeReply reply;
94405b261ecSmrg    int rc, numChildren = 0;
94505b261ecSmrg    WindowPtr pChild, pWin, pHead;
946f7df2e56Smrg    Window *childIDs = (Window *) NULL;
947f7df2e56Smrg
94805b261ecSmrg    REQUEST(xResourceReq);
94905b261ecSmrg
95005b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
9514642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
95205b261ecSmrg    if (rc != Success)
95305b261ecSmrg        return rc;
954f7df2e56Smrg
955f7df2e56Smrg    reply = (xQueryTreeReply) {
956f7df2e56Smrg        .type = X_Reply,
957f7df2e56Smrg        .sequenceNumber = client->sequence,
958f7df2e56Smrg        .root = pWin->drawable.pScreen->root->drawable.id,
959f7df2e56Smrg        .parent = (pWin->parent) ? pWin->parent->drawable.id : (Window) None
960f7df2e56Smrg    };
96105b261ecSmrg    pHead = RealChildHead(pWin);
96205b261ecSmrg    for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib)
963f7df2e56Smrg        numChildren++;
964f7df2e56Smrg    if (numChildren) {
965f7df2e56Smrg        int curChild = 0;
96605b261ecSmrg
967f7df2e56Smrg        childIDs = xallocarray(numChildren, sizeof(Window));
968f7df2e56Smrg        if (!childIDs)
969f7df2e56Smrg            return BadAlloc;
970f7df2e56Smrg        for (pChild = pWin->lastChild; pChild != pHead;
971f7df2e56Smrg             pChild = pChild->prevSib)
972f7df2e56Smrg            childIDs[curChild++] = pChild->drawable.id;
97305b261ecSmrg    }
974f7df2e56Smrg
97505b261ecSmrg    reply.nChildren = numChildren;
9766747b715Smrg    reply.length = bytes_to_int32(numChildren * sizeof(Window));
977f7df2e56Smrg
97805b261ecSmrg    WriteReplyToClient(client, sizeof(xQueryTreeReply), &reply);
979f7df2e56Smrg    if (numChildren) {
980f7df2e56Smrg        client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
981f7df2e56Smrg        WriteSwappedDataToClient(client, numChildren * sizeof(Window),
982f7df2e56Smrg                                 childIDs);
983f7df2e56Smrg        free(childIDs);
98405b261ecSmrg    }
98505b261ecSmrg
9866747b715Smrg    return Success;
98705b261ecSmrg}
98805b261ecSmrg
98905b261ecSmrgint
99005b261ecSmrgProcInternAtom(ClientPtr client)
99105b261ecSmrg{
99205b261ecSmrg    Atom atom;
99305b261ecSmrg    char *tchar;
994f7df2e56Smrg
99505b261ecSmrg    REQUEST(xInternAtomReq);
99605b261ecSmrg
99705b261ecSmrg    REQUEST_FIXED_SIZE(xInternAtomReq, stuff->nbytes);
998f7df2e56Smrg    if ((stuff->onlyIfExists != xTrue) && (stuff->onlyIfExists != xFalse)) {
999f7df2e56Smrg        client->errorValue = stuff->onlyIfExists;
10006747b715Smrg        return BadValue;
100105b261ecSmrg    }
100205b261ecSmrg    tchar = (char *) &stuff[1];
100305b261ecSmrg    atom = MakeAtom(tchar, stuff->nbytes, !stuff->onlyIfExists);
1004f7df2e56Smrg    if (atom != BAD_RESOURCE) {
1005f7df2e56Smrg        xInternAtomReply reply = {
1006f7df2e56Smrg            .type = X_Reply,
1007f7df2e56Smrg            .sequenceNumber = client->sequence,
1008f7df2e56Smrg            .length = 0,
1009f7df2e56Smrg            .atom = atom
1010f7df2e56Smrg        };
1011f7df2e56Smrg        WriteReplyToClient(client, sizeof(xInternAtomReply), &reply);
1012f7df2e56Smrg        return Success;
101305b261ecSmrg    }
101405b261ecSmrg    else
1015f7df2e56Smrg        return BadAlloc;
101605b261ecSmrg}
101705b261ecSmrg
101805b261ecSmrgint
101905b261ecSmrgProcGetAtomName(ClientPtr client)
102005b261ecSmrg{
10216747b715Smrg    const char *str;
1022f7df2e56Smrg
102305b261ecSmrg    REQUEST(xResourceReq);
102405b261ecSmrg
102505b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
1026f7df2e56Smrg    if ((str = NameForAtom(stuff->id))) {
1027f7df2e56Smrg        int len = strlen(str);
1028f7df2e56Smrg        xGetAtomNameReply reply = {
1029f7df2e56Smrg            .type = X_Reply,
1030f7df2e56Smrg            .sequenceNumber = client->sequence,
1031f7df2e56Smrg            .length = bytes_to_int32(len),
1032f7df2e56Smrg            .nameLength = len
1033f7df2e56Smrg        };
1034f7df2e56Smrg
1035f7df2e56Smrg        WriteReplyToClient(client, sizeof(xGetAtomNameReply), &reply);
1036f7df2e56Smrg        WriteToClient(client, len, str);
1037f7df2e56Smrg        return Success;
103805b261ecSmrg    }
1039f7df2e56Smrg    else {
1040f7df2e56Smrg        client->errorValue = stuff->id;
1041f7df2e56Smrg        return BadAtom;
104205b261ecSmrg    }
104305b261ecSmrg}
104405b261ecSmrg
104505b261ecSmrgint
104605b261ecSmrgProcGrabServer(ClientPtr client)
104705b261ecSmrg{
10484642e01fSmrg    int rc;
1049f7df2e56Smrg
105005b261ecSmrg    REQUEST_SIZE_MATCH(xReq);
1051f7df2e56Smrg    if (grabState != GrabNone && client != grabClient) {
1052f7df2e56Smrg        ResetCurrentRequest(client);
1053f7df2e56Smrg        client->sequence--;
1054f7df2e56Smrg        BITSET(grabWaiters, client->index);
1055f7df2e56Smrg        IgnoreClient(client);
1056f7df2e56Smrg        return Success;
105705b261ecSmrg    }
10584642e01fSmrg    rc = OnlyListenToOneClient(client);
10594642e01fSmrg    if (rc != Success)
1060f7df2e56Smrg        return rc;
106105b261ecSmrg    grabState = GrabKickout;
106205b261ecSmrg    grabClient = client;
106305b261ecSmrg
1064f7df2e56Smrg    if (ServerGrabCallback) {
1065f7df2e56Smrg        ServerGrabInfoRec grabinfo;
1066f7df2e56Smrg
1067f7df2e56Smrg        grabinfo.client = client;
1068f7df2e56Smrg        grabinfo.grabstate = SERVER_GRABBED;
1069f7df2e56Smrg        CallCallbacks(&ServerGrabCallback, (void *) &grabinfo);
107005b261ecSmrg    }
107105b261ecSmrg
10726747b715Smrg    return Success;
107305b261ecSmrg}
107405b261ecSmrg
107505b261ecSmrgstatic void
107605b261ecSmrgUngrabServer(ClientPtr client)
107705b261ecSmrg{
107805b261ecSmrg    int i;
107905b261ecSmrg
108005b261ecSmrg    grabState = GrabNone;
108105b261ecSmrg    ListenToAllClients();
1082f7df2e56Smrg    for (i = mskcnt; --i >= 0 && !grabWaiters[i];);
1083f7df2e56Smrg    if (i >= 0) {
1084f7df2e56Smrg        i <<= 5;
1085f7df2e56Smrg        while (!GETBIT(grabWaiters, i))
1086f7df2e56Smrg            i++;
1087f7df2e56Smrg        BITCLEAR(grabWaiters, i);
1088f7df2e56Smrg        AttendClient(clients[i]);
108905b261ecSmrg    }
109005b261ecSmrg
1091f7df2e56Smrg    if (ServerGrabCallback) {
1092f7df2e56Smrg        ServerGrabInfoRec grabinfo;
1093f7df2e56Smrg
1094f7df2e56Smrg        grabinfo.client = client;
1095f7df2e56Smrg        grabinfo.grabstate = SERVER_UNGRABBED;
1096f7df2e56Smrg        CallCallbacks(&ServerGrabCallback, (void *) &grabinfo);
109705b261ecSmrg    }
109805b261ecSmrg}
109905b261ecSmrg
110005b261ecSmrgint
110105b261ecSmrgProcUngrabServer(ClientPtr client)
110205b261ecSmrg{
110305b261ecSmrg    REQUEST_SIZE_MATCH(xReq);
110405b261ecSmrg    UngrabServer(client);
11056747b715Smrg    return Success;
110605b261ecSmrg}
110705b261ecSmrg
110805b261ecSmrgint
110905b261ecSmrgProcTranslateCoords(ClientPtr client)
111005b261ecSmrg{
111105b261ecSmrg    REQUEST(xTranslateCoordsReq);
111205b261ecSmrg
111305b261ecSmrg    WindowPtr pWin, pDst;
111405b261ecSmrg    xTranslateCoordsReply rep;
111505b261ecSmrg    int rc;
111605b261ecSmrg
111705b261ecSmrg    REQUEST_SIZE_MATCH(xTranslateCoordsReq);
11184642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->srcWid, client, DixGetAttrAccess);
111905b261ecSmrg    if (rc != Success)
112005b261ecSmrg        return rc;
11214642e01fSmrg    rc = dixLookupWindow(&pDst, stuff->dstWid, client, DixGetAttrAccess);
112205b261ecSmrg    if (rc != Success)
112305b261ecSmrg        return rc;
1124f7df2e56Smrg
1125f7df2e56Smrg    rep = (xTranslateCoordsReply) {
1126f7df2e56Smrg        .type = X_Reply,
1127f7df2e56Smrg        .sequenceNumber = client->sequence,
1128f7df2e56Smrg        .length = 0
1129f7df2e56Smrg    };
1130f7df2e56Smrg    if (!SAME_SCREENS(pWin->drawable, pDst->drawable)) {
1131f7df2e56Smrg        rep.sameScreen = xFalse;
113205b261ecSmrg        rep.child = None;
1133f7df2e56Smrg        rep.dstX = rep.dstY = 0;
113405b261ecSmrg    }
1135f7df2e56Smrg    else {
1136f7df2e56Smrg        INT16 x, y;
1137f7df2e56Smrg
1138f7df2e56Smrg        rep.sameScreen = xTrue;
1139f7df2e56Smrg        rep.child = None;
1140f7df2e56Smrg        /* computing absolute coordinates -- adjust to destination later */
1141f7df2e56Smrg        x = pWin->drawable.x + stuff->srcX;
1142f7df2e56Smrg        y = pWin->drawable.y + stuff->srcY;
1143f7df2e56Smrg        pWin = pDst->firstChild;
1144f7df2e56Smrg        while (pWin) {
1145f7df2e56Smrg            BoxRec box;
1146f7df2e56Smrg
1147f7df2e56Smrg            if ((pWin->mapped) &&
1148f7df2e56Smrg                (x >= pWin->drawable.x - wBorderWidth(pWin)) &&
1149f7df2e56Smrg                (x < pWin->drawable.x + (int) pWin->drawable.width +
1150f7df2e56Smrg                 wBorderWidth(pWin)) &&
1151f7df2e56Smrg                (y >= pWin->drawable.y - wBorderWidth(pWin)) &&
1152f7df2e56Smrg                (y < pWin->drawable.y + (int) pWin->drawable.height +
1153f7df2e56Smrg                 wBorderWidth(pWin))
1154f7df2e56Smrg                /* When a window is shaped, a further check
1155f7df2e56Smrg                 * is made to see if the point is inside
1156f7df2e56Smrg                 * borderSize
1157f7df2e56Smrg                 */
1158f7df2e56Smrg                && (!wBoundingShape(pWin) ||
1159f7df2e56Smrg                    RegionContainsPoint(&pWin->borderSize, x, y, &box))
1160f7df2e56Smrg
1161f7df2e56Smrg                && (!wInputShape(pWin) ||
1162f7df2e56Smrg                    RegionContainsPoint(wInputShape(pWin),
1163f7df2e56Smrg                                        x - pWin->drawable.x,
1164f7df2e56Smrg                                        y - pWin->drawable.y, &box))
1165f7df2e56Smrg                ) {
1166f7df2e56Smrg                rep.child = pWin->drawable.id;
1167f7df2e56Smrg                pWin = (WindowPtr) NULL;
1168f7df2e56Smrg            }
1169f7df2e56Smrg            else
1170f7df2e56Smrg                pWin = pWin->nextSib;
1171f7df2e56Smrg        }
1172f7df2e56Smrg        /* adjust to destination coordinates */
1173f7df2e56Smrg        rep.dstX = x - pDst->drawable.x;
1174f7df2e56Smrg        rep.dstY = y - pDst->drawable.y;
117505b261ecSmrg    }
117605b261ecSmrg    WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep);
11776747b715Smrg    return Success;
117805b261ecSmrg}
117905b261ecSmrg
118005b261ecSmrgint
118105b261ecSmrgProcOpenFont(ClientPtr client)
118205b261ecSmrg{
1183f7df2e56Smrg    int err;
1184f7df2e56Smrg
118505b261ecSmrg    REQUEST(xOpenFontReq);
118605b261ecSmrg
118705b261ecSmrg    REQUEST_FIXED_SIZE(xOpenFontReq, stuff->nbytes);
118805b261ecSmrg    client->errorValue = stuff->fid;
118905b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->fid, client);
119005b261ecSmrg    err = OpenFont(client, stuff->fid, (Mask) 0,
1191f7df2e56Smrg                   stuff->nbytes, (char *) &stuff[1]);
1192f7df2e56Smrg    if (err == Success) {
1193f7df2e56Smrg        return Success;
119405b261ecSmrg    }
119505b261ecSmrg    else
1196f7df2e56Smrg        return err;
119705b261ecSmrg}
119805b261ecSmrg
119905b261ecSmrgint
120005b261ecSmrgProcCloseFont(ClientPtr client)
120105b261ecSmrg{
120205b261ecSmrg    FontPtr pFont;
12036747b715Smrg    int rc;
1204f7df2e56Smrg
120505b261ecSmrg    REQUEST(xResourceReq);
120605b261ecSmrg
120705b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
1208f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pFont, stuff->id, RT_FONT,
1209f7df2e56Smrg                                 client, DixDestroyAccess);
1210f7df2e56Smrg    if (rc == Success) {
121105b261ecSmrg        FreeResource(stuff->id, RT_NONE);
1212f7df2e56Smrg        return Success;
121305b261ecSmrg    }
1214f7df2e56Smrg    else {
1215f7df2e56Smrg        client->errorValue = stuff->id;
12166747b715Smrg        return rc;
121705b261ecSmrg    }
121805b261ecSmrg}
121905b261ecSmrg
122005b261ecSmrgint
122105b261ecSmrgProcQueryFont(ClientPtr client)
122205b261ecSmrg{
1223f7df2e56Smrg    xQueryFontReply *reply;
122405b261ecSmrg    FontPtr pFont;
12254642e01fSmrg    int rc;
1226f7df2e56Smrg
122705b261ecSmrg    REQUEST(xResourceReq);
122805b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
12294642e01fSmrg
12306747b715Smrg    rc = dixLookupFontable(&pFont, stuff->id, client, DixGetAttrAccess);
12314642e01fSmrg    if (rc != Success)
1232f7df2e56Smrg        return rc;
123305b261ecSmrg
123405b261ecSmrg    {
1235f7df2e56Smrg        xCharInfo *pmax = FONTINKMAX(pFont);
1236f7df2e56Smrg        xCharInfo *pmin = FONTINKMIN(pFont);
1237f7df2e56Smrg        int nprotoxcistructs;
1238f7df2e56Smrg        int rlength;
1239f7df2e56Smrg
1240f7df2e56Smrg        nprotoxcistructs = (pmax->rightSideBearing == pmin->rightSideBearing &&
1241f7df2e56Smrg                            pmax->leftSideBearing == pmin->leftSideBearing &&
1242f7df2e56Smrg                            pmax->descent == pmin->descent &&
1243f7df2e56Smrg                            pmax->ascent == pmin->ascent &&
1244f7df2e56Smrg                            pmax->characterWidth == pmin->characterWidth) ?
1245f7df2e56Smrg            0 : N2dChars(pFont);
1246f7df2e56Smrg
1247f7df2e56Smrg        rlength = sizeof(xQueryFontReply) +
1248f7df2e56Smrg            FONTINFONPROPS(FONTCHARSET(pFont)) * sizeof(xFontProp) +
1249f7df2e56Smrg            nprotoxcistructs * sizeof(xCharInfo);
1250f7df2e56Smrg        reply = calloc(1, rlength);
1251f7df2e56Smrg        if (!reply) {
1252f7df2e56Smrg            return BadAlloc;
1253f7df2e56Smrg        }
1254f7df2e56Smrg
1255f7df2e56Smrg        reply->type = X_Reply;
1256f7df2e56Smrg        reply->length = bytes_to_int32(rlength - sizeof(xGenericReply));
1257f7df2e56Smrg        reply->sequenceNumber = client->sequence;
1258f7df2e56Smrg        QueryFont(pFont, reply, nprotoxcistructs);
125905b261ecSmrg
126005b261ecSmrg        WriteReplyToClient(client, rlength, reply);
1261f7df2e56Smrg        free(reply);
1262f7df2e56Smrg        return Success;
126305b261ecSmrg    }
126405b261ecSmrg}
126505b261ecSmrg
126605b261ecSmrgint
126705b261ecSmrgProcQueryTextExtents(ClientPtr client)
126805b261ecSmrg{
126905b261ecSmrg    xQueryTextExtentsReply reply;
127005b261ecSmrg    FontPtr pFont;
127105b261ecSmrg    ExtentInfoRec info;
127205b261ecSmrg    unsigned long length;
12734642e01fSmrg    int rc;
1274f7df2e56Smrg
12754642e01fSmrg    REQUEST(xQueryTextExtentsReq);
127605b261ecSmrg    REQUEST_AT_LEAST_SIZE(xQueryTextExtentsReq);
1277f7df2e56Smrg
12786747b715Smrg    rc = dixLookupFontable(&pFont, stuff->fid, client, DixGetAttrAccess);
12794642e01fSmrg    if (rc != Success)
1280f7df2e56Smrg        return rc;
12814642e01fSmrg
12826747b715Smrg    length = client->req_len - bytes_to_int32(sizeof(xQueryTextExtentsReq));
128305b261ecSmrg    length = length << 1;
1284f7df2e56Smrg    if (stuff->oddLength) {
1285f7df2e56Smrg        if (length == 0)
1286f7df2e56Smrg            return BadLength;
128705b261ecSmrg        length--;
128805b261ecSmrg    }
1289f7df2e56Smrg    if (!QueryTextExtents(pFont, length, (unsigned char *) &stuff[1], &info))
1290f7df2e56Smrg        return BadAlloc;
1291f7df2e56Smrg    reply = (xQueryTextExtentsReply) {
1292f7df2e56Smrg        .type = X_Reply,
1293f7df2e56Smrg        .drawDirection = info.drawDirection,
1294f7df2e56Smrg        .sequenceNumber = client->sequence,
1295f7df2e56Smrg        .length = 0,
1296f7df2e56Smrg        .fontAscent = info.fontAscent,
1297f7df2e56Smrg        .fontDescent = info.fontDescent,
1298f7df2e56Smrg        .overallAscent = info.overallAscent,
1299f7df2e56Smrg        .overallDescent = info.overallDescent,
1300f7df2e56Smrg        .overallWidth = info.overallWidth,
1301f7df2e56Smrg        .overallLeft = info.overallLeft,
1302f7df2e56Smrg        .overallRight = info.overallRight
1303f7df2e56Smrg    };
130405b261ecSmrg    WriteReplyToClient(client, sizeof(xQueryTextExtentsReply), &reply);
13056747b715Smrg    return Success;
130605b261ecSmrg}
130705b261ecSmrg
130805b261ecSmrgint
130905b261ecSmrgProcListFonts(ClientPtr client)
131005b261ecSmrg{
131105b261ecSmrg    REQUEST(xListFontsReq);
131205b261ecSmrg
131305b261ecSmrg    REQUEST_FIXED_SIZE(xListFontsReq, stuff->nbytes);
131405b261ecSmrg
1315f7df2e56Smrg    return ListFonts(client, (unsigned char *) &stuff[1], stuff->nbytes,
1316f7df2e56Smrg                     stuff->maxNames);
131705b261ecSmrg}
131805b261ecSmrg
131905b261ecSmrgint
132005b261ecSmrgProcListFontsWithInfo(ClientPtr client)
132105b261ecSmrg{
132205b261ecSmrg    REQUEST(xListFontsWithInfoReq);
132305b261ecSmrg
132405b261ecSmrg    REQUEST_FIXED_SIZE(xListFontsWithInfoReq, stuff->nbytes);
132505b261ecSmrg
132605b261ecSmrg    return StartListFontsWithInfo(client, stuff->nbytes,
1327f7df2e56Smrg                                  (unsigned char *) &stuff[1], stuff->maxNames);
132805b261ecSmrg}
132905b261ecSmrg
133005b261ecSmrg/**
133105b261ecSmrg *
133205b261ecSmrg *  \param value must conform to DeleteType
133305b261ecSmrg */
133405b261ecSmrgint
1335f7df2e56SmrgdixDestroyPixmap(void *value, XID pid)
133605b261ecSmrg{
1337f7df2e56Smrg    PixmapPtr pPixmap = (PixmapPtr) value;
1338f7df2e56Smrg
1339f7df2e56Smrg    return (*pPixmap->drawable.pScreen->DestroyPixmap) (pPixmap);
134005b261ecSmrg}
134105b261ecSmrg
134205b261ecSmrgint
134305b261ecSmrgProcCreatePixmap(ClientPtr client)
134405b261ecSmrg{
134505b261ecSmrg    PixmapPtr pMap;
134605b261ecSmrg    DrawablePtr pDraw;
1347f7df2e56Smrg
134805b261ecSmrg    REQUEST(xCreatePixmapReq);
134905b261ecSmrg    DepthPtr pDepth;
135005b261ecSmrg    int i, rc;
135105b261ecSmrg
135205b261ecSmrg    REQUEST_SIZE_MATCH(xCreatePixmapReq);
135305b261ecSmrg    client->errorValue = stuff->pid;
135405b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->pid, client);
1355f7df2e56Smrg
135605b261ecSmrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
1357f7df2e56Smrg                           DixGetAttrAccess);
135805b261ecSmrg    if (rc != Success)
1359f7df2e56Smrg        return rc;
136005b261ecSmrg
1361f7df2e56Smrg    if (!stuff->width || !stuff->height) {
1362f7df2e56Smrg        client->errorValue = 0;
136305b261ecSmrg        return BadValue;
136405b261ecSmrg    }
1365f7df2e56Smrg    if (stuff->width > 32767 || stuff->height > 32767) {
1366f7df2e56Smrg        /* It is allowed to try and allocate a pixmap which is larger than
1367f7df2e56Smrg         * 32767 in either dimension. However, all of the framebuffer code
1368f7df2e56Smrg         * is buggy and does not reliably draw to such big pixmaps, basically
1369f7df2e56Smrg         * because the Region data structure operates with signed shorts
1370f7df2e56Smrg         * for the rectangles in it.
1371f7df2e56Smrg         *
1372f7df2e56Smrg         * Furthermore, several places in the X server computes the
1373f7df2e56Smrg         * size in bytes of the pixmap and tries to store it in an
1374f7df2e56Smrg         * integer. This integer can overflow and cause the allocated size
1375f7df2e56Smrg         * to be much smaller.
1376f7df2e56Smrg         *
1377f7df2e56Smrg         * So, such big pixmaps are rejected here with a BadAlloc
1378f7df2e56Smrg         */
1379f7df2e56Smrg        return BadAlloc;
1380f7df2e56Smrg    }
1381f7df2e56Smrg    if (stuff->depth != 1) {
138205b261ecSmrg        pDepth = pDraw->pScreen->allowedDepths;
1383f7df2e56Smrg        for (i = 0; i < pDraw->pScreen->numDepths; i++, pDepth++)
1384f7df2e56Smrg            if (pDepth->depth == stuff->depth)
1385f7df2e56Smrg                goto CreatePmap;
1386f7df2e56Smrg        client->errorValue = stuff->depth;
138705b261ecSmrg        return BadValue;
138805b261ecSmrg    }
1389f7df2e56Smrg CreatePmap:
1390f7df2e56Smrg    pMap = (PixmapPtr) (*pDraw->pScreen->CreatePixmap)
1391f7df2e56Smrg        (pDraw->pScreen, stuff->width, stuff->height, stuff->depth, 0);
1392f7df2e56Smrg    if (pMap) {
1393f7df2e56Smrg        pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
1394f7df2e56Smrg        pMap->drawable.id = stuff->pid;
1395f7df2e56Smrg        /* security creation/labeling check */
1396f7df2e56Smrg        rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, RT_PIXMAP,
1397f7df2e56Smrg                      pMap, RT_NONE, NULL, DixCreateAccess);
1398f7df2e56Smrg        if (rc != Success) {
1399f7df2e56Smrg            (*pDraw->pScreen->DestroyPixmap) (pMap);
1400f7df2e56Smrg            return rc;
1401f7df2e56Smrg        }
1402f7df2e56Smrg        if (AddResource(stuff->pid, RT_PIXMAP, (void *) pMap))
1403f7df2e56Smrg            return Success;
140405b261ecSmrg    }
14056747b715Smrg    return BadAlloc;
140605b261ecSmrg}
140705b261ecSmrg
140805b261ecSmrgint
140905b261ecSmrgProcFreePixmap(ClientPtr client)
141005b261ecSmrg{
141105b261ecSmrg    PixmapPtr pMap;
14124642e01fSmrg    int rc;
1413f7df2e56Smrg
141405b261ecSmrg    REQUEST(xResourceReq);
141505b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
14164642e01fSmrg
1417f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pMap, stuff->id, RT_PIXMAP,
1418f7df2e56Smrg                                 client, DixDestroyAccess);
1419f7df2e56Smrg    if (rc == Success) {
1420f7df2e56Smrg        FreeResource(stuff->id, RT_NONE);
1421f7df2e56Smrg        return Success;
142205b261ecSmrg    }
1423f7df2e56Smrg    else {
1424f7df2e56Smrg        client->errorValue = stuff->id;
1425f7df2e56Smrg        return rc;
142605b261ecSmrg    }
142705b261ecSmrg}
142805b261ecSmrg
142905b261ecSmrgint
143005b261ecSmrgProcCreateGC(ClientPtr client)
143105b261ecSmrg{
143205b261ecSmrg    int error, rc;
143305b261ecSmrg    GC *pGC;
143405b261ecSmrg    DrawablePtr pDraw;
143505b261ecSmrg    unsigned len;
1436f7df2e56Smrg
143705b261ecSmrg    REQUEST(xCreateGCReq);
143805b261ecSmrg
143905b261ecSmrg    REQUEST_AT_LEAST_SIZE(xCreateGCReq);
144005b261ecSmrg    client->errorValue = stuff->gc;
144105b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->gc, client);
14424642e01fSmrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
1443f7df2e56Smrg                           DixGetAttrAccess);
144405b261ecSmrg    if (rc != Success)
1445f7df2e56Smrg        return rc;
144605b261ecSmrg
1447f7df2e56Smrg    len = client->req_len - bytes_to_int32(sizeof(xCreateGCReq));
144805b261ecSmrg    if (len != Ones(stuff->mask))
144905b261ecSmrg        return BadLength;
1450f7df2e56Smrg    pGC = (GC *) CreateGC(pDraw, stuff->mask, (XID *) &stuff[1], &error,
1451f7df2e56Smrg                          stuff->gc, client);
145205b261ecSmrg    if (error != Success)
145305b261ecSmrg        return error;
1454f7df2e56Smrg    if (!AddResource(stuff->gc, RT_GC, (void *) pGC))
1455f7df2e56Smrg        return BadAlloc;
14566747b715Smrg    return Success;
145705b261ecSmrg}
145805b261ecSmrg
145905b261ecSmrgint
146005b261ecSmrgProcChangeGC(ClientPtr client)
146105b261ecSmrg{
146205b261ecSmrg    GC *pGC;
146305b261ecSmrg    int result;
146405b261ecSmrg    unsigned len;
1465f7df2e56Smrg
146605b261ecSmrg    REQUEST(xChangeGCReq);
146705b261ecSmrg    REQUEST_AT_LEAST_SIZE(xChangeGCReq);
146805b261ecSmrg
14694642e01fSmrg    result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess);
147005b261ecSmrg    if (result != Success)
1471f7df2e56Smrg        return result;
147205b261ecSmrg
1473f7df2e56Smrg    len = client->req_len - bytes_to_int32(sizeof(xChangeGCReq));
147405b261ecSmrg    if (len != Ones(stuff->mask))
147505b261ecSmrg        return BadLength;
147605b261ecSmrg
14776747b715Smrg    return ChangeGCXIDs(client, pGC, stuff->mask, (CARD32 *) &stuff[1]);
147805b261ecSmrg}
147905b261ecSmrg
148005b261ecSmrgint
148105b261ecSmrgProcCopyGC(ClientPtr client)
148205b261ecSmrg{
148305b261ecSmrg    GC *dstGC;
148405b261ecSmrg    GC *pGC;
148505b261ecSmrg    int result;
1486f7df2e56Smrg
148705b261ecSmrg    REQUEST(xCopyGCReq);
148805b261ecSmrg    REQUEST_SIZE_MATCH(xCopyGCReq);
148905b261ecSmrg
14904642e01fSmrg    result = dixLookupGC(&pGC, stuff->srcGC, client, DixGetAttrAccess);
149105b261ecSmrg    if (result != Success)
1492f7df2e56Smrg        return result;
14934642e01fSmrg    result = dixLookupGC(&dstGC, stuff->dstGC, client, DixSetAttrAccess);
149405b261ecSmrg    if (result != Success)
1495f7df2e56Smrg        return result;
149605b261ecSmrg    if ((dstGC->pScreen != pGC->pScreen) || (dstGC->depth != pGC->depth))
14976747b715Smrg        return BadMatch;
1498f7df2e56Smrg    if (stuff->mask & ~GCAllBits) {
1499f7df2e56Smrg        client->errorValue = stuff->mask;
1500f7df2e56Smrg        return BadValue;
150105b261ecSmrg    }
15026747b715Smrg    return CopyGC(pGC, dstGC, stuff->mask);
150305b261ecSmrg}
150405b261ecSmrg
150505b261ecSmrgint
150605b261ecSmrgProcSetDashes(ClientPtr client)
150705b261ecSmrg{
150805b261ecSmrg    GC *pGC;
150905b261ecSmrg    int result;
1510f7df2e56Smrg
151105b261ecSmrg    REQUEST(xSetDashesReq);
151205b261ecSmrg
151305b261ecSmrg    REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes);
1514f7df2e56Smrg    if (stuff->nDashes == 0) {
1515f7df2e56Smrg        client->errorValue = 0;
1516f7df2e56Smrg        return BadValue;
151705b261ecSmrg    }
151805b261ecSmrg
1519f7df2e56Smrg    result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess);
152005b261ecSmrg    if (result != Success)
1521f7df2e56Smrg        return result;
152205b261ecSmrg
15236747b715Smrg    /* If there's an error, either there's no sensible errorValue,
15246747b715Smrg     * or there was a dash segment of 0. */
15256747b715Smrg    client->errorValue = 0;
15266747b715Smrg    return SetDashes(pGC, stuff->dashOffset, stuff->nDashes,
1527f7df2e56Smrg                     (unsigned char *) &stuff[1]);
152805b261ecSmrg}
152905b261ecSmrg
153005b261ecSmrgint
153105b261ecSmrgProcSetClipRectangles(ClientPtr client)
153205b261ecSmrg{
1533f7df2e56Smrg    int nr, result;
153405b261ecSmrg    GC *pGC;
1535f7df2e56Smrg
153605b261ecSmrg    REQUEST(xSetClipRectanglesReq);
153705b261ecSmrg
153805b261ecSmrg    REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq);
153905b261ecSmrg    if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) &&
1540f7df2e56Smrg        (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded)) {
1541f7df2e56Smrg        client->errorValue = stuff->ordering;
154205b261ecSmrg        return BadValue;
154305b261ecSmrg    }
1544f7df2e56Smrg    result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess);
154505b261ecSmrg    if (result != Success)
1546f7df2e56Smrg        return result;
1547f7df2e56Smrg
154805b261ecSmrg    nr = (client->req_len << 2) - sizeof(xSetClipRectanglesReq);
154905b261ecSmrg    if (nr & 4)
1550f7df2e56Smrg        return BadLength;
155105b261ecSmrg    nr >>= 3;
15526747b715Smrg    return SetClipRects(pGC, stuff->xOrigin, stuff->yOrigin,
1553f7df2e56Smrg                        nr, (xRectangle *) &stuff[1], (int) stuff->ordering);
155405b261ecSmrg}
155505b261ecSmrg
155605b261ecSmrgint
155705b261ecSmrgProcFreeGC(ClientPtr client)
155805b261ecSmrg{
155905b261ecSmrg    GC *pGC;
156005b261ecSmrg    int rc;
1561f7df2e56Smrg
156205b261ecSmrg    REQUEST(xResourceReq);
156305b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
156405b261ecSmrg
156505b261ecSmrg    rc = dixLookupGC(&pGC, stuff->id, client, DixDestroyAccess);
156605b261ecSmrg    if (rc != Success)
1567f7df2e56Smrg        return rc;
156805b261ecSmrg
156905b261ecSmrg    FreeResource(stuff->id, RT_NONE);
15706747b715Smrg    return Success;
157105b261ecSmrg}
157205b261ecSmrg
157305b261ecSmrgint
157405b261ecSmrgProcClearToBackground(ClientPtr client)
157505b261ecSmrg{
157605b261ecSmrg    REQUEST(xClearAreaReq);
157705b261ecSmrg    WindowPtr pWin;
157805b261ecSmrg    int rc;
157905b261ecSmrg
158005b261ecSmrg    REQUEST_SIZE_MATCH(xClearAreaReq);
158105b261ecSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess);
158205b261ecSmrg    if (rc != Success)
158305b261ecSmrg        return rc;
1584f7df2e56Smrg    if (pWin->drawable.class == InputOnly) {
1585f7df2e56Smrg        client->errorValue = stuff->window;
1586f7df2e56Smrg        return BadMatch;
1587f7df2e56Smrg    }
1588f7df2e56Smrg    if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse)) {
1589f7df2e56Smrg        client->errorValue = stuff->exposures;
15906747b715Smrg        return BadValue;
159105b261ecSmrg    }
1592f7df2e56Smrg    (*pWin->drawable.pScreen->ClearToBackground) (pWin, stuff->x, stuff->y,
1593f7df2e56Smrg                                                  stuff->width, stuff->height,
1594f7df2e56Smrg                                                  (Bool) stuff->exposures);
15956747b715Smrg    return Success;
159605b261ecSmrg}
159705b261ecSmrg
1598f7df2e56Smrg/* send GraphicsExpose events, or a NoExpose event, based on the region */
1599f7df2e56Smrgvoid
1600f7df2e56SmrgSendGraphicsExpose(ClientPtr client, RegionPtr pRgn, XID drawable,
1601f7df2e56Smrg                     int major, int minor)
1602f7df2e56Smrg{
1603f7df2e56Smrg    if (pRgn && !RegionNil(pRgn)) {
1604f7df2e56Smrg        xEvent *pEvent;
1605f7df2e56Smrg        xEvent *pe;
1606f7df2e56Smrg        BoxPtr pBox;
1607f7df2e56Smrg        int i;
1608f7df2e56Smrg        int numRects;
1609f7df2e56Smrg
1610f7df2e56Smrg        numRects = RegionNumRects(pRgn);
1611f7df2e56Smrg        pBox = RegionRects(pRgn);
1612f7df2e56Smrg        if (!(pEvent = calloc(numRects, sizeof(xEvent))))
1613f7df2e56Smrg            return;
1614f7df2e56Smrg        pe = pEvent;
1615f7df2e56Smrg
1616f7df2e56Smrg        for (i = 1; i <= numRects; i++, pe++, pBox++) {
1617f7df2e56Smrg            pe->u.u.type = GraphicsExpose;
1618f7df2e56Smrg            pe->u.graphicsExposure.drawable = drawable;
1619f7df2e56Smrg            pe->u.graphicsExposure.x = pBox->x1;
1620f7df2e56Smrg            pe->u.graphicsExposure.y = pBox->y1;
1621f7df2e56Smrg            pe->u.graphicsExposure.width = pBox->x2 - pBox->x1;
1622f7df2e56Smrg            pe->u.graphicsExposure.height = pBox->y2 - pBox->y1;
1623f7df2e56Smrg            pe->u.graphicsExposure.count = numRects - i;
1624f7df2e56Smrg            pe->u.graphicsExposure.majorEvent = major;
1625f7df2e56Smrg            pe->u.graphicsExposure.minorEvent = minor;
1626f7df2e56Smrg        }
1627f7df2e56Smrg        /* GraphicsExpose is a "critical event", which TryClientEvents
1628f7df2e56Smrg         * handles specially. */
1629f7df2e56Smrg        TryClientEvents(client, NULL, pEvent, numRects,
1630f7df2e56Smrg                        (Mask) 0, NoEventMask, NullGrab);
1631f7df2e56Smrg        free(pEvent);
1632f7df2e56Smrg    }
1633f7df2e56Smrg    else {
1634f7df2e56Smrg        xEvent event = {
1635f7df2e56Smrg            .u.noExposure.drawable = drawable,
1636f7df2e56Smrg            .u.noExposure.majorEvent = major,
1637f7df2e56Smrg            .u.noExposure.minorEvent = minor
1638f7df2e56Smrg        };
1639f7df2e56Smrg        event.u.u.type = NoExpose;
1640f7df2e56Smrg        WriteEventsToClient(client, 1, &event);
1641f7df2e56Smrg    }
1642f7df2e56Smrg}
1643f7df2e56Smrg
164405b261ecSmrgint
164505b261ecSmrgProcCopyArea(ClientPtr client)
164605b261ecSmrg{
164705b261ecSmrg    DrawablePtr pDst;
164805b261ecSmrg    DrawablePtr pSrc;
164905b261ecSmrg    GC *pGC;
1650f7df2e56Smrg
165105b261ecSmrg    REQUEST(xCopyAreaReq);
165205b261ecSmrg    RegionPtr pRgn;
165305b261ecSmrg    int rc;
165405b261ecSmrg
165505b261ecSmrg    REQUEST_SIZE_MATCH(xCopyAreaReq);
165605b261ecSmrg
1657f7df2e56Smrg    VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, DixWriteAccess);
1658f7df2e56Smrg    if (stuff->dstDrawable != stuff->srcDrawable) {
1659f7df2e56Smrg        rc = dixLookupDrawable(&pSrc, stuff->srcDrawable, client, 0,
1660f7df2e56Smrg                               DixReadAccess);
1661f7df2e56Smrg        if (rc != Success)
1662f7df2e56Smrg            return rc;
1663f7df2e56Smrg        if ((pDst->pScreen != pSrc->pScreen) || (pDst->depth != pSrc->depth)) {
1664f7df2e56Smrg            client->errorValue = stuff->dstDrawable;
1665f7df2e56Smrg            return BadMatch;
1666f7df2e56Smrg        }
166705b261ecSmrg    }
166805b261ecSmrg    else
166905b261ecSmrg        pSrc = pDst;
167005b261ecSmrg
1671f7df2e56Smrg    pRgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, stuff->srcX, stuff->srcY,
1672f7df2e56Smrg                                  stuff->width, stuff->height,
1673f7df2e56Smrg                                  stuff->dstX, stuff->dstY);
1674f7df2e56Smrg    if (pGC->graphicsExposures) {
1675f7df2e56Smrg        SendGraphicsExpose(client, pRgn, stuff->dstDrawable, X_CopyArea, 0);
1676f7df2e56Smrg        if (pRgn)
1677f7df2e56Smrg            RegionDestroy(pRgn);
167805b261ecSmrg    }
167905b261ecSmrg
16806747b715Smrg    return Success;
168105b261ecSmrg}
168205b261ecSmrg
168305b261ecSmrgint
168405b261ecSmrgProcCopyPlane(ClientPtr client)
168505b261ecSmrg{
168605b261ecSmrg    DrawablePtr psrcDraw, pdstDraw;
168705b261ecSmrg    GC *pGC;
1688f7df2e56Smrg
168905b261ecSmrg    REQUEST(xCopyPlaneReq);
169005b261ecSmrg    RegionPtr pRgn;
169105b261ecSmrg    int rc;
169205b261ecSmrg
169305b261ecSmrg    REQUEST_SIZE_MATCH(xCopyPlaneReq);
169405b261ecSmrg
16954642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pdstDraw, DixWriteAccess);
1696f7df2e56Smrg    if (stuff->dstDrawable != stuff->srcDrawable) {
1697f7df2e56Smrg        rc = dixLookupDrawable(&psrcDraw, stuff->srcDrawable, client, 0,
1698f7df2e56Smrg                               DixReadAccess);
1699f7df2e56Smrg        if (rc != Success)
1700f7df2e56Smrg            return rc;
1701f7df2e56Smrg
1702f7df2e56Smrg        if (pdstDraw->pScreen != psrcDraw->pScreen) {
1703f7df2e56Smrg            client->errorValue = stuff->dstDrawable;
1704f7df2e56Smrg            return BadMatch;
1705f7df2e56Smrg        }
170605b261ecSmrg    }
170705b261ecSmrg    else
170805b261ecSmrg        psrcDraw = pdstDraw;
170905b261ecSmrg
171005b261ecSmrg    /* Check to see if stuff->bitPlane has exactly ONE good bit set */
1711f7df2e56Smrg    if (stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) ||
1712f7df2e56Smrg        (stuff->bitPlane > (1L << (psrcDraw->depth - 1)))) {
1713f7df2e56Smrg        client->errorValue = stuff->bitPlane;
1714f7df2e56Smrg        return BadValue;
171505b261ecSmrg    }
171605b261ecSmrg
1717f7df2e56Smrg    pRgn =
1718f7df2e56Smrg        (*pGC->ops->CopyPlane) (psrcDraw, pdstDraw, pGC, stuff->srcX,
1719f7df2e56Smrg                                stuff->srcY, stuff->width, stuff->height,
1720f7df2e56Smrg                                stuff->dstX, stuff->dstY, stuff->bitPlane);
1721f7df2e56Smrg    if (pGC->graphicsExposures) {
1722f7df2e56Smrg        SendGraphicsExpose(client, pRgn, stuff->dstDrawable, X_CopyPlane, 0);
1723f7df2e56Smrg        if (pRgn)
1724f7df2e56Smrg            RegionDestroy(pRgn);
172505b261ecSmrg    }
17266747b715Smrg    return Success;
172705b261ecSmrg}
172805b261ecSmrg
172905b261ecSmrgint
173005b261ecSmrgProcPolyPoint(ClientPtr client)
173105b261ecSmrg{
173205b261ecSmrg    int npoint;
173305b261ecSmrg    GC *pGC;
173405b261ecSmrg    DrawablePtr pDraw;
1735f7df2e56Smrg
173605b261ecSmrg    REQUEST(xPolyPointReq);
173705b261ecSmrg
173805b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolyPointReq);
1739f7df2e56Smrg    if ((stuff->coordMode != CoordModeOrigin) &&
1740f7df2e56Smrg        (stuff->coordMode != CoordModePrevious)) {
1741f7df2e56Smrg        client->errorValue = stuff->coordMode;
174205b261ecSmrg        return BadValue;
174305b261ecSmrg    }
1744f7df2e56Smrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
17456747b715Smrg    npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyPointReq));
174605b261ecSmrg    if (npoint)
1747f7df2e56Smrg        (*pGC->ops->PolyPoint) (pDraw, pGC, stuff->coordMode, npoint,
1748f7df2e56Smrg                                (xPoint *) &stuff[1]);
17496747b715Smrg    return Success;
175005b261ecSmrg}
175105b261ecSmrg
175205b261ecSmrgint
175305b261ecSmrgProcPolyLine(ClientPtr client)
175405b261ecSmrg{
175505b261ecSmrg    int npoint;
175605b261ecSmrg    GC *pGC;
175705b261ecSmrg    DrawablePtr pDraw;
1758f7df2e56Smrg
175905b261ecSmrg    REQUEST(xPolyLineReq);
176005b261ecSmrg
176105b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolyLineReq);
1762f7df2e56Smrg    if ((stuff->coordMode != CoordModeOrigin) &&
1763f7df2e56Smrg        (stuff->coordMode != CoordModePrevious)) {
1764f7df2e56Smrg        client->errorValue = stuff->coordMode;
176505b261ecSmrg        return BadValue;
176605b261ecSmrg    }
17674642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
17686747b715Smrg    npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyLineReq));
176905b261ecSmrg    if (npoint > 1)
1770f7df2e56Smrg        (*pGC->ops->Polylines) (pDraw, pGC, stuff->coordMode, npoint,
1771f7df2e56Smrg                                (DDXPointPtr) &stuff[1]);
17726747b715Smrg    return Success;
177305b261ecSmrg}
177405b261ecSmrg
177505b261ecSmrgint
177605b261ecSmrgProcPolySegment(ClientPtr client)
177705b261ecSmrg{
177805b261ecSmrg    int nsegs;
177905b261ecSmrg    GC *pGC;
178005b261ecSmrg    DrawablePtr pDraw;
1781f7df2e56Smrg
178205b261ecSmrg    REQUEST(xPolySegmentReq);
178305b261ecSmrg
178405b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolySegmentReq);
17854642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
178605b261ecSmrg    nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq);
178705b261ecSmrg    if (nsegs & 4)
1788f7df2e56Smrg        return BadLength;
178905b261ecSmrg    nsegs >>= 3;
179005b261ecSmrg    if (nsegs)
1791f7df2e56Smrg        (*pGC->ops->PolySegment) (pDraw, pGC, nsegs, (xSegment *) &stuff[1]);
17926747b715Smrg    return Success;
179305b261ecSmrg}
179405b261ecSmrg
179505b261ecSmrgint
1796f7df2e56SmrgProcPolyRectangle(ClientPtr client)
179705b261ecSmrg{
179805b261ecSmrg    int nrects;
179905b261ecSmrg    GC *pGC;
180005b261ecSmrg    DrawablePtr pDraw;
1801f7df2e56Smrg
180205b261ecSmrg    REQUEST(xPolyRectangleReq);
180305b261ecSmrg
180405b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolyRectangleReq);
18054642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
180605b261ecSmrg    nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq);
180705b261ecSmrg    if (nrects & 4)
1808f7df2e56Smrg        return BadLength;
180905b261ecSmrg    nrects >>= 3;
181005b261ecSmrg    if (nrects)
1811f7df2e56Smrg        (*pGC->ops->PolyRectangle) (pDraw, pGC,
1812f7df2e56Smrg                                    nrects, (xRectangle *) &stuff[1]);
18136747b715Smrg    return Success;
181405b261ecSmrg}
181505b261ecSmrg
181605b261ecSmrgint
181705b261ecSmrgProcPolyArc(ClientPtr client)
181805b261ecSmrg{
1819f7df2e56Smrg    int narcs;
182005b261ecSmrg    GC *pGC;
182105b261ecSmrg    DrawablePtr pDraw;
1822f7df2e56Smrg
182305b261ecSmrg    REQUEST(xPolyArcReq);
182405b261ecSmrg
182505b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolyArcReq);
18264642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
182705b261ecSmrg    narcs = (client->req_len << 2) - sizeof(xPolyArcReq);
182805b261ecSmrg    if (narcs % sizeof(xArc))
1829f7df2e56Smrg        return BadLength;
183005b261ecSmrg    narcs /= sizeof(xArc);
183105b261ecSmrg    if (narcs)
1832f7df2e56Smrg        (*pGC->ops->PolyArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]);
18336747b715Smrg    return Success;
183405b261ecSmrg}
183505b261ecSmrg
183605b261ecSmrgint
183705b261ecSmrgProcFillPoly(ClientPtr client)
183805b261ecSmrg{
1839f7df2e56Smrg    int things;
184005b261ecSmrg    GC *pGC;
184105b261ecSmrg    DrawablePtr pDraw;
1842f7df2e56Smrg
184305b261ecSmrg    REQUEST(xFillPolyReq);
184405b261ecSmrg
184505b261ecSmrg    REQUEST_AT_LEAST_SIZE(xFillPolyReq);
1846f7df2e56Smrg    if ((stuff->shape != Complex) && (stuff->shape != Nonconvex) &&
1847f7df2e56Smrg        (stuff->shape != Convex)) {
1848f7df2e56Smrg        client->errorValue = stuff->shape;
184905b261ecSmrg        return BadValue;
185005b261ecSmrg    }
1851f7df2e56Smrg    if ((stuff->coordMode != CoordModeOrigin) &&
1852f7df2e56Smrg        (stuff->coordMode != CoordModePrevious)) {
1853f7df2e56Smrg        client->errorValue = stuff->coordMode;
185405b261ecSmrg        return BadValue;
185505b261ecSmrg    }
185605b261ecSmrg
18574642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
18586747b715Smrg    things = bytes_to_int32((client->req_len << 2) - sizeof(xFillPolyReq));
185905b261ecSmrg    if (things)
186005b261ecSmrg        (*pGC->ops->FillPolygon) (pDraw, pGC, stuff->shape,
1861f7df2e56Smrg                                  stuff->coordMode, things,
1862f7df2e56Smrg                                  (DDXPointPtr) &stuff[1]);
18636747b715Smrg    return Success;
186405b261ecSmrg}
186505b261ecSmrg
186605b261ecSmrgint
186705b261ecSmrgProcPolyFillRectangle(ClientPtr client)
186805b261ecSmrg{
1869f7df2e56Smrg    int things;
187005b261ecSmrg    GC *pGC;
187105b261ecSmrg    DrawablePtr pDraw;
1872f7df2e56Smrg
187305b261ecSmrg    REQUEST(xPolyFillRectangleReq);
187405b261ecSmrg
187505b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq);
18764642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
187705b261ecSmrg    things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq);
187805b261ecSmrg    if (things & 4)
1879f7df2e56Smrg        return BadLength;
188005b261ecSmrg    things >>= 3;
188105b261ecSmrg
188205b261ecSmrg    if (things)
188305b261ecSmrg        (*pGC->ops->PolyFillRect) (pDraw, pGC, things,
1884f7df2e56Smrg                                   (xRectangle *) &stuff[1]);
18856747b715Smrg    return Success;
188605b261ecSmrg}
188705b261ecSmrg
188805b261ecSmrgint
188905b261ecSmrgProcPolyFillArc(ClientPtr client)
189005b261ecSmrg{
1891f7df2e56Smrg    int narcs;
189205b261ecSmrg    GC *pGC;
189305b261ecSmrg    DrawablePtr pDraw;
1894f7df2e56Smrg
189505b261ecSmrg    REQUEST(xPolyFillArcReq);
189605b261ecSmrg
189705b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolyFillArcReq);
18984642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
189905b261ecSmrg    narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq);
190005b261ecSmrg    if (narcs % sizeof(xArc))
1901f7df2e56Smrg        return BadLength;
190205b261ecSmrg    narcs /= sizeof(xArc);
190305b261ecSmrg    if (narcs)
190405b261ecSmrg        (*pGC->ops->PolyFillArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]);
19056747b715Smrg    return Success;
190605b261ecSmrg}
190705b261ecSmrg
190805b261ecSmrg#ifdef MATCH_CLIENT_ENDIAN
190905b261ecSmrg
191005b261ecSmrgint
1911f7df2e56SmrgServerOrder(void)
191205b261ecSmrg{
1913f7df2e56Smrg    int whichbyte = 1;
191405b261ecSmrg
191505b261ecSmrg    if (*((char *) &whichbyte))
1916f7df2e56Smrg        return LSBFirst;
191705b261ecSmrg    return MSBFirst;
191805b261ecSmrg}
191905b261ecSmrg
192005b261ecSmrg#define ClientOrder(client) ((client)->swapped ? !ServerOrder() : ServerOrder())
192105b261ecSmrg
192205b261ecSmrgvoid
1923f7df2e56SmrgReformatImage(char *base, int nbytes, int bpp, int order)
192405b261ecSmrg{
192505b261ecSmrg    switch (bpp) {
1926f7df2e56Smrg    case 1:                    /* yuck */
1927f7df2e56Smrg        if (BITMAP_BIT_ORDER != order)
1928f7df2e56Smrg            BitOrderInvert((unsigned char *) base, nbytes);
192905b261ecSmrg#if IMAGE_BYTE_ORDER != BITMAP_BIT_ORDER && BITMAP_SCANLINE_UNIT != 8
1930f7df2e56Smrg        ReformatImage(base, nbytes, BITMAP_SCANLINE_UNIT, order);
193105b261ecSmrg#endif
1932f7df2e56Smrg        break;
193305b261ecSmrg    case 4:
1934f7df2e56Smrg        break;                  /* yuck */
193505b261ecSmrg    case 8:
1936f7df2e56Smrg        break;
193705b261ecSmrg    case 16:
1938f7df2e56Smrg        if (IMAGE_BYTE_ORDER != order)
1939f7df2e56Smrg            TwoByteSwap((unsigned char *) base, nbytes);
1940f7df2e56Smrg        break;
194105b261ecSmrg    case 32:
1942f7df2e56Smrg        if (IMAGE_BYTE_ORDER != order)
1943f7df2e56Smrg            FourByteSwap((unsigned char *) base, nbytes);
1944f7df2e56Smrg        break;
194505b261ecSmrg    }
194605b261ecSmrg}
194705b261ecSmrg#else
194805b261ecSmrg#define ReformatImage(b,n,bpp,o)
194905b261ecSmrg#endif
195005b261ecSmrg
195105b261ecSmrg/* 64-bit server notes: the protocol restricts padding of images to
195205b261ecSmrg * 8-, 16-, or 32-bits. We would like to have 64-bits for the server
195305b261ecSmrg * to use internally. Removes need for internal alignment checking.
195405b261ecSmrg * All of the PutImage functions could be changed individually, but
195505b261ecSmrg * as currently written, they call other routines which require things
195605b261ecSmrg * to be 64-bit padded on scanlines, so we changed things here.
195705b261ecSmrg * If an image would be padded differently for 64- versus 32-, then
195805b261ecSmrg * copy each scanline to a 64-bit padded scanline.
195905b261ecSmrg * Also, we need to make sure that the image is aligned on a 64-bit
196005b261ecSmrg * boundary, even if the scanlines are padded to our satisfaction.
196105b261ecSmrg */
196205b261ecSmrgint
196305b261ecSmrgProcPutImage(ClientPtr client)
196405b261ecSmrg{
196505b261ecSmrg    GC *pGC;
196605b261ecSmrg    DrawablePtr pDraw;
1967f7df2e56Smrg    long length;                /* length of scanline server padded */
1968f7df2e56Smrg    long lengthProto;           /* length of scanline protocol padded */
1969f7df2e56Smrg    char *tmpImage;
1970f7df2e56Smrg
197105b261ecSmrg    REQUEST(xPutImageReq);
197205b261ecSmrg
197305b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPutImageReq);
19744642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
1975f7df2e56Smrg    if (stuff->format == XYBitmap) {
197605b261ecSmrg        if ((stuff->depth != 1) ||
1977f7df2e56Smrg            (stuff->leftPad >= (unsigned int) screenInfo.bitmapScanlinePad))
197805b261ecSmrg            return BadMatch;
1979f7df2e56Smrg        length = BitmapBytePad(stuff->width + stuff->leftPad);
198005b261ecSmrg    }
1981f7df2e56Smrg    else if (stuff->format == XYPixmap) {
1982f7df2e56Smrg        if ((pDraw->depth != stuff->depth) ||
1983f7df2e56Smrg            (stuff->leftPad >= (unsigned int) screenInfo.bitmapScanlinePad))
198405b261ecSmrg            return BadMatch;
1985f7df2e56Smrg        length = BitmapBytePad(stuff->width + stuff->leftPad);
1986f7df2e56Smrg        length *= stuff->depth;
198705b261ecSmrg    }
1988f7df2e56Smrg    else if (stuff->format == ZPixmap) {
198905b261ecSmrg        if ((pDraw->depth != stuff->depth) || (stuff->leftPad != 0))
199005b261ecSmrg            return BadMatch;
1991f7df2e56Smrg        length = PixmapBytePad(stuff->width, stuff->depth);
199205b261ecSmrg    }
1993f7df2e56Smrg    else {
1994f7df2e56Smrg        client->errorValue = stuff->format;
199505b261ecSmrg        return BadValue;
199605b261ecSmrg    }
199705b261ecSmrg
1998f7df2e56Smrg    tmpImage = (char *) &stuff[1];
199905b261ecSmrg    lengthProto = length;
20000b0d8713Smrg
2001f7df2e56Smrg    if (stuff->height != 0 && lengthProto >= (INT32_MAX / stuff->height))
20020b0d8713Smrg        return BadLength;
2003f7df2e56Smrg
20046747b715Smrg    if ((bytes_to_int32(lengthProto * stuff->height) +
2005f7df2e56Smrg         bytes_to_int32(sizeof(xPutImageReq))) != client->req_len)
2006f7df2e56Smrg        return BadLength;
2007f7df2e56Smrg
2008f7df2e56Smrg    ReformatImage(tmpImage, lengthProto * stuff->height,
2009f7df2e56Smrg                  stuff->format == ZPixmap ? BitsPerPixel(stuff->depth) : 1,
2010f7df2e56Smrg                  ClientOrder(client));
201105b261ecSmrg
201205b261ecSmrg    (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, stuff->dstX, stuff->dstY,
2013f7df2e56Smrg                           stuff->width, stuff->height,
2014f7df2e56Smrg                           stuff->leftPad, stuff->format, tmpImage);
201505b261ecSmrg
2016f7df2e56Smrg    return Success;
201705b261ecSmrg}
201805b261ecSmrg
201905b261ecSmrgstatic int
2020f7df2e56SmrgDoGetImage(ClientPtr client, int format, Drawable drawable,
2021f7df2e56Smrg           int x, int y, int width, int height,
2022f7df2e56Smrg           Mask planemask)
202305b261ecSmrg{
2024f7df2e56Smrg    DrawablePtr pDraw, pBoundingDraw;
2025f7df2e56Smrg    int nlines, linesPerBuf, rc;
2026f7df2e56Smrg    int linesDone;
2027f7df2e56Smrg
20286747b715Smrg    /* coordinates relative to the bounding drawable */
2029f7df2e56Smrg    int relx, rely;
2030f7df2e56Smrg    long widthBytesLine, length;
2031f7df2e56Smrg    Mask plane = 0;
2032f7df2e56Smrg    char *pBuf;
2033f7df2e56Smrg    xGetImageReply xgi;
203405b261ecSmrg    RegionPtr pVisibleRegion = NULL;
203505b261ecSmrg
2036f7df2e56Smrg    if ((format != XYPixmap) && (format != ZPixmap)) {
2037f7df2e56Smrg        client->errorValue = format;
20386747b715Smrg        return BadValue;
203905b261ecSmrg    }
204005b261ecSmrg    rc = dixLookupDrawable(&pDraw, drawable, client, 0, DixReadAccess);
204105b261ecSmrg    if (rc != Success)
2042f7df2e56Smrg        return rc;
204305b261ecSmrg
20446747b715Smrg    memset(&xgi, 0, sizeof(xGetImageReply));
20456747b715Smrg
20466747b715Smrg    relx = x;
20476747b715Smrg    rely = y;
20486747b715Smrg
2049f7df2e56Smrg    if (pDraw->type == DRAWABLE_WINDOW) {
2050f7df2e56Smrg        WindowPtr pWin = (WindowPtr) pDraw;
2051f7df2e56Smrg
2052f7df2e56Smrg        /* "If the drawable is a window, the window must be viewable ... or a
2053f7df2e56Smrg         * BadMatch error results" */
2054f7df2e56Smrg        if (!pWin->viewable)
2055f7df2e56Smrg            return BadMatch;
20566747b715Smrg
2057f7df2e56Smrg        /* If the drawable is a window, the rectangle must be contained within
2058f7df2e56Smrg         * its bounds (including the border). */
2059f7df2e56Smrg        if (x < -wBorderWidth(pWin) ||
2060f7df2e56Smrg            x + width > wBorderWidth(pWin) + (int) pDraw->width ||
2061f7df2e56Smrg            y < -wBorderWidth(pWin) ||
2062f7df2e56Smrg            y + height > wBorderWidth(pWin) + (int) pDraw->height)
2063f7df2e56Smrg            return BadMatch;
20646747b715Smrg
2065f7df2e56Smrg        relx += pDraw->x;
2066f7df2e56Smrg        rely += pDraw->y;
20676747b715Smrg
2068f7df2e56Smrg        if (pDraw->pScreen->GetWindowPixmap) {
2069f7df2e56Smrg            PixmapPtr pPix = (*pDraw->pScreen->GetWindowPixmap) (pWin);
20706747b715Smrg
2071f7df2e56Smrg            pBoundingDraw = &pPix->drawable;
20726747b715Smrg#ifdef COMPOSITE
2073f7df2e56Smrg            relx -= pPix->screen_x;
2074f7df2e56Smrg            rely -= pPix->screen_y;
20756747b715Smrg#endif
2076f7df2e56Smrg        }
2077f7df2e56Smrg        else {
2078f7df2e56Smrg            pBoundingDraw = (DrawablePtr) pDraw->pScreen->root;
2079f7df2e56Smrg        }
20806747b715Smrg
2081f7df2e56Smrg        xgi.visual = wVisual(pWin);
208205b261ecSmrg    }
2083f7df2e56Smrg    else {
2084f7df2e56Smrg        pBoundingDraw = pDraw;
2085f7df2e56Smrg        xgi.visual = None;
208605b261ecSmrg    }
208705b261ecSmrg
20886747b715Smrg    /* "If the drawable is a pixmap, the given rectangle must be wholly
20896747b715Smrg     *  contained within the pixmap, or a BadMatch error results.  If the
20906747b715Smrg     *  drawable is a window [...] it must be the case that if there were no
20916747b715Smrg     *  inferiors or overlapping windows, the specified rectangle of the window
20926747b715Smrg     *  would be fully visible on the screen and wholly contained within the
20936747b715Smrg     *  outside edges of the window, or a BadMatch error results."
20946747b715Smrg     *
20956747b715Smrg     * We relax the window case slightly to mean that the rectangle must exist
20966747b715Smrg     * within the bounds of the window's backing pixmap.  In particular, this
20976747b715Smrg     * means that a GetImage request may succeed or fail with BadMatch depending
20986747b715Smrg     * on whether any of its ancestor windows are redirected.  */
2099f7df2e56Smrg    if (relx < 0 || relx + width > (int) pBoundingDraw->width ||
2100f7df2e56Smrg        rely < 0 || rely + height > (int) pBoundingDraw->height)
2101f7df2e56Smrg        return BadMatch;
21026747b715Smrg
210305b261ecSmrg    xgi.type = X_Reply;
210405b261ecSmrg    xgi.sequenceNumber = client->sequence;
210505b261ecSmrg    xgi.depth = pDraw->depth;
2106f7df2e56Smrg    if (format == ZPixmap) {
2107f7df2e56Smrg        widthBytesLine = PixmapBytePad(width, pDraw->depth);
2108f7df2e56Smrg        length = widthBytesLine * height;
210905b261ecSmrg
211005b261ecSmrg    }
2111f7df2e56Smrg    else {
2112f7df2e56Smrg        widthBytesLine = BitmapBytePad(width);
2113f7df2e56Smrg        plane = ((Mask) 1) << (pDraw->depth - 1);
2114f7df2e56Smrg        /* only planes asked for */
2115f7df2e56Smrg        length = widthBytesLine * height *
2116f7df2e56Smrg            Ones(planemask & (plane | (plane - 1)));
211705b261ecSmrg
211805b261ecSmrg    }
211905b261ecSmrg
212005b261ecSmrg    xgi.length = length;
212105b261ecSmrg
2122f7df2e56Smrg    xgi.length = bytes_to_int32(xgi.length);
2123f7df2e56Smrg    if (widthBytesLine == 0 || height == 0)
2124f7df2e56Smrg        linesPerBuf = 0;
2125f7df2e56Smrg    else if (widthBytesLine >= IMAGE_BUFSIZE)
2126f7df2e56Smrg        linesPerBuf = 1;
2127f7df2e56Smrg    else {
2128f7df2e56Smrg        linesPerBuf = IMAGE_BUFSIZE / widthBytesLine;
2129f7df2e56Smrg        if (linesPerBuf > height)
2130f7df2e56Smrg            linesPerBuf = height;
2131f7df2e56Smrg    }
2132f7df2e56Smrg    length = linesPerBuf * widthBytesLine;
2133f7df2e56Smrg    if (linesPerBuf < height) {
2134f7df2e56Smrg        /* we have to make sure intermediate buffers don't need padding */
2135f7df2e56Smrg        while ((linesPerBuf > 1) &&
2136f7df2e56Smrg               (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD) - 1))) {
2137f7df2e56Smrg            linesPerBuf--;
2138f7df2e56Smrg            length -= widthBytesLine;
2139f7df2e56Smrg        }
2140f7df2e56Smrg        while (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD) - 1)) {
2141f7df2e56Smrg            linesPerBuf++;
2142f7df2e56Smrg            length += widthBytesLine;
2143f7df2e56Smrg        }
214405b261ecSmrg    }
2145f7df2e56Smrg    if (!(pBuf = calloc(1, length)))
2146f7df2e56Smrg        return BadAlloc;
2147f7df2e56Smrg    WriteReplyToClient(client, sizeof(xGetImageReply), &xgi);
214805b261ecSmrg
2149f7df2e56Smrg    if (pDraw->type == DRAWABLE_WINDOW) {
2150f7df2e56Smrg        pVisibleRegion = NotClippedByChildren((WindowPtr) pDraw);
2151f7df2e56Smrg        if (pVisibleRegion) {
2152f7df2e56Smrg            RegionTranslate(pVisibleRegion, -pDraw->x, -pDraw->y);
2153f7df2e56Smrg        }
215405b261ecSmrg    }
2155f7df2e56Smrg
2156f7df2e56Smrg    if (linesPerBuf == 0) {
2157f7df2e56Smrg        /* nothing to do */
2158f7df2e56Smrg    }
2159f7df2e56Smrg    else if (format == ZPixmap) {
216005b261ecSmrg        linesDone = 0;
2161f7df2e56Smrg        while (height - linesDone > 0) {
2162f7df2e56Smrg            nlines = min(linesPerBuf, height - linesDone);
2163f7df2e56Smrg            (*pDraw->pScreen->GetImage) (pDraw,
2164f7df2e56Smrg                                         x,
2165f7df2e56Smrg                                         y + linesDone,
2166f7df2e56Smrg                                         width,
2167f7df2e56Smrg                                         nlines,
2168f7df2e56Smrg                                         format, planemask, (void *) pBuf);
2169f7df2e56Smrg            if (pVisibleRegion)
2170f7df2e56Smrg                XaceCensorImage(client, pVisibleRegion, widthBytesLine,
2171f7df2e56Smrg                                pDraw, x, y + linesDone, width,
2172f7df2e56Smrg                                nlines, format, pBuf);
2173f7df2e56Smrg
2174f7df2e56Smrg            /* Note that this is NOT a call to WriteSwappedDataToClient,
217505b261ecSmrg               as we do NOT byte swap */
2176f7df2e56Smrg            ReformatImage(pBuf, (int) (nlines * widthBytesLine),
2177f7df2e56Smrg                          BitsPerPixel(pDraw->depth), ClientOrder(client));
2178f7df2e56Smrg
2179f7df2e56Smrg            WriteToClient(client, (int) (nlines * widthBytesLine), pBuf);
2180f7df2e56Smrg            linesDone += nlines;
218105b261ecSmrg        }
218205b261ecSmrg    }
2183f7df2e56Smrg    else {                      /* XYPixmap */
2184f7df2e56Smrg
2185f7df2e56Smrg        for (; plane; plane >>= 1) {
2186f7df2e56Smrg            if (planemask & plane) {
2187f7df2e56Smrg                linesDone = 0;
2188f7df2e56Smrg                while (height - linesDone > 0) {
2189f7df2e56Smrg                    nlines = min(linesPerBuf, height - linesDone);
2190f7df2e56Smrg                    (*pDraw->pScreen->GetImage) (pDraw,
2191f7df2e56Smrg                                                 x,
2192f7df2e56Smrg                                                 y + linesDone,
2193f7df2e56Smrg                                                 width,
2194f7df2e56Smrg                                                 nlines,
2195f7df2e56Smrg                                                 format, plane, (void *) pBuf);
2196f7df2e56Smrg                    if (pVisibleRegion)
2197f7df2e56Smrg                        XaceCensorImage(client, pVisibleRegion,
2198f7df2e56Smrg                                        widthBytesLine,
2199f7df2e56Smrg                                        pDraw, x, y + linesDone, width,
2200f7df2e56Smrg                                        nlines, format, pBuf);
2201f7df2e56Smrg
2202f7df2e56Smrg                    /* Note: NOT a call to WriteSwappedDataToClient,
2203f7df2e56Smrg                       as we do NOT byte swap */
2204f7df2e56Smrg                    ReformatImage(pBuf, (int) (nlines * widthBytesLine),
2205f7df2e56Smrg                                  1, ClientOrder(client));
2206f7df2e56Smrg
2207f7df2e56Smrg                    WriteToClient(client, (int)(nlines * widthBytesLine), pBuf);
2208f7df2e56Smrg                    linesDone += nlines;
2209f7df2e56Smrg                }
221005b261ecSmrg            }
2211f7df2e56Smrg        }
221205b261ecSmrg    }
221305b261ecSmrg    if (pVisibleRegion)
2214f7df2e56Smrg        RegionDestroy(pVisibleRegion);
2215f7df2e56Smrg    free(pBuf);
22166747b715Smrg    return Success;
221705b261ecSmrg}
221805b261ecSmrg
221905b261ecSmrgint
222005b261ecSmrgProcGetImage(ClientPtr client)
222105b261ecSmrg{
222205b261ecSmrg    REQUEST(xGetImageReq);
222305b261ecSmrg
222405b261ecSmrg    REQUEST_SIZE_MATCH(xGetImageReq);
222505b261ecSmrg
222605b261ecSmrg    return DoGetImage(client, stuff->format, stuff->drawable,
2227f7df2e56Smrg                      stuff->x, stuff->y,
2228f7df2e56Smrg                      (int) stuff->width, (int) stuff->height,
2229f7df2e56Smrg                      stuff->planeMask);
223005b261ecSmrg}
223105b261ecSmrg
223205b261ecSmrgint
223305b261ecSmrgProcPolyText(ClientPtr client)
223405b261ecSmrg{
2235f7df2e56Smrg    int err;
2236f7df2e56Smrg
223705b261ecSmrg    REQUEST(xPolyTextReq);
223805b261ecSmrg    DrawablePtr pDraw;
223905b261ecSmrg    GC *pGC;
224005b261ecSmrg
224105b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolyTextReq);
22424642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
224305b261ecSmrg
224405b261ecSmrg    err = PolyText(client,
2245f7df2e56Smrg                   pDraw,
2246f7df2e56Smrg                   pGC,
2247f7df2e56Smrg                   (unsigned char *) &stuff[1],
2248f7df2e56Smrg                   ((unsigned char *) stuff) + (client->req_len << 2),
2249f7df2e56Smrg                   stuff->x, stuff->y, stuff->reqType, stuff->drawable);
2250f7df2e56Smrg
2251f7df2e56Smrg    if (err == Success) {
2252f7df2e56Smrg        return Success;
225305b261ecSmrg    }
225405b261ecSmrg    else
2255f7df2e56Smrg        return err;
225605b261ecSmrg}
225705b261ecSmrg
225805b261ecSmrgint
225905b261ecSmrgProcImageText8(ClientPtr client)
226005b261ecSmrg{
2261f7df2e56Smrg    int err;
226205b261ecSmrg    DrawablePtr pDraw;
226305b261ecSmrg    GC *pGC;
226405b261ecSmrg
226505b261ecSmrg    REQUEST(xImageTextReq);
226605b261ecSmrg
226705b261ecSmrg    REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars);
22684642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
226905b261ecSmrg
227005b261ecSmrg    err = ImageText(client,
2271f7df2e56Smrg                    pDraw,
2272f7df2e56Smrg                    pGC,
2273f7df2e56Smrg                    stuff->nChars,
2274f7df2e56Smrg                    (unsigned char *) &stuff[1],
2275f7df2e56Smrg                    stuff->x, stuff->y, stuff->reqType, stuff->drawable);
2276f7df2e56Smrg
2277f7df2e56Smrg    if (err == Success) {
2278f7df2e56Smrg        return Success;
227905b261ecSmrg    }
228005b261ecSmrg    else
2281f7df2e56Smrg        return err;
228205b261ecSmrg}
228305b261ecSmrg
228405b261ecSmrgint
228505b261ecSmrgProcImageText16(ClientPtr client)
228605b261ecSmrg{
2287f7df2e56Smrg    int err;
228805b261ecSmrg    DrawablePtr pDraw;
228905b261ecSmrg    GC *pGC;
229005b261ecSmrg
229105b261ecSmrg    REQUEST(xImageTextReq);
229205b261ecSmrg
229305b261ecSmrg    REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars << 1);
22944642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
229505b261ecSmrg
229605b261ecSmrg    err = ImageText(client,
2297f7df2e56Smrg                    pDraw,
2298f7df2e56Smrg                    pGC,
2299f7df2e56Smrg                    stuff->nChars,
2300f7df2e56Smrg                    (unsigned char *) &stuff[1],
2301f7df2e56Smrg                    stuff->x, stuff->y, stuff->reqType, stuff->drawable);
2302f7df2e56Smrg
2303f7df2e56Smrg    if (err == Success) {
2304f7df2e56Smrg        return Success;
230505b261ecSmrg    }
230605b261ecSmrg    else
2307f7df2e56Smrg        return err;
230805b261ecSmrg}
230905b261ecSmrg
231005b261ecSmrgint
231105b261ecSmrgProcCreateColormap(ClientPtr client)
231205b261ecSmrg{
2313f7df2e56Smrg    VisualPtr pVisual;
2314f7df2e56Smrg    ColormapPtr pmap;
2315f7df2e56Smrg    Colormap mid;
2316f7df2e56Smrg    WindowPtr pWin;
231705b261ecSmrg    ScreenPtr pScreen;
2318f7df2e56Smrg
231905b261ecSmrg    REQUEST(xCreateColormapReq);
232005b261ecSmrg    int i, result;
232105b261ecSmrg
232205b261ecSmrg    REQUEST_SIZE_MATCH(xCreateColormapReq);
232305b261ecSmrg
2324f7df2e56Smrg    if ((stuff->alloc != AllocNone) && (stuff->alloc != AllocAll)) {
2325f7df2e56Smrg        client->errorValue = stuff->alloc;
23266747b715Smrg        return BadValue;
232705b261ecSmrg    }
232805b261ecSmrg    mid = stuff->mid;
232905b261ecSmrg    LEGAL_NEW_RESOURCE(mid, client);
23304642e01fSmrg    result = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
233105b261ecSmrg    if (result != Success)
233205b261ecSmrg        return result;
233305b261ecSmrg
233405b261ecSmrg    pScreen = pWin->drawable.pScreen;
233505b261ecSmrg    for (i = 0, pVisual = pScreen->visuals;
2336f7df2e56Smrg         i < pScreen->numVisuals; i++, pVisual++) {
2337f7df2e56Smrg        if (pVisual->vid != stuff->visual)
2338f7df2e56Smrg            continue;
2339f7df2e56Smrg        return CreateColormap(mid, pScreen, pVisual, &pmap,
2340f7df2e56Smrg                              (int) stuff->alloc, client->index);
234105b261ecSmrg    }
234205b261ecSmrg    client->errorValue = stuff->visual;
23436747b715Smrg    return BadMatch;
234405b261ecSmrg}
234505b261ecSmrg
234605b261ecSmrgint
234705b261ecSmrgProcFreeColormap(ClientPtr client)
234805b261ecSmrg{
234905b261ecSmrg    ColormapPtr pmap;
23504642e01fSmrg    int rc;
2351f7df2e56Smrg
235205b261ecSmrg    REQUEST(xResourceReq);
235305b261ecSmrg
235405b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
2355f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pmap, stuff->id, RT_COLORMAP,
2356f7df2e56Smrg                                 client, DixDestroyAccess);
2357f7df2e56Smrg    if (rc == Success) {
2358f7df2e56Smrg        /* Freeing a default colormap is a no-op */
2359f7df2e56Smrg        if (!(pmap->flags & IsDefault))
2360f7df2e56Smrg            FreeResource(stuff->id, RT_NONE);
2361f7df2e56Smrg        return Success;
236205b261ecSmrg    }
2363f7df2e56Smrg    else {
2364f7df2e56Smrg        client->errorValue = stuff->id;
2365f7df2e56Smrg        return rc;
236605b261ecSmrg    }
236705b261ecSmrg}
236805b261ecSmrg
236905b261ecSmrgint
237005b261ecSmrgProcCopyColormapAndFree(ClientPtr client)
237105b261ecSmrg{
2372f7df2e56Smrg    Colormap mid;
2373f7df2e56Smrg    ColormapPtr pSrcMap;
2374f7df2e56Smrg
237505b261ecSmrg    REQUEST(xCopyColormapAndFreeReq);
23764642e01fSmrg    int rc;
237705b261ecSmrg
237805b261ecSmrg    REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq);
237905b261ecSmrg    mid = stuff->mid;
238005b261ecSmrg    LEGAL_NEW_RESOURCE(mid, client);
2381f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pSrcMap, stuff->srcCmap,
2382f7df2e56Smrg                                 RT_COLORMAP, client,
2383f7df2e56Smrg                                 DixReadAccess | DixRemoveAccess);
23844642e01fSmrg    if (rc == Success)
2385f7df2e56Smrg        return CopyColormapAndFree(mid, pSrcMap, client->index);
23866747b715Smrg    client->errorValue = stuff->srcCmap;
23876747b715Smrg    return rc;
238805b261ecSmrg}
238905b261ecSmrg
239005b261ecSmrgint
239105b261ecSmrgProcInstallColormap(ClientPtr client)
239205b261ecSmrg{
239305b261ecSmrg    ColormapPtr pcmp;
23944642e01fSmrg    int rc;
2395f7df2e56Smrg
239605b261ecSmrg    REQUEST(xResourceReq);
239705b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
23984642e01fSmrg
2399f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->id, RT_COLORMAP,
2400f7df2e56Smrg                                 client, DixInstallAccess);
24014642e01fSmrg    if (rc != Success)
2402f7df2e56Smrg        goto out;
24034642e01fSmrg
24044642e01fSmrg    rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess);
24056747b715Smrg    if (rc != Success) {
2406f7df2e56Smrg        if (rc == BadValue)
2407f7df2e56Smrg            rc = BadColor;
2408f7df2e56Smrg        goto out;
24096747b715Smrg    }
24104642e01fSmrg
24114642e01fSmrg    (*(pcmp->pScreen->InstallColormap)) (pcmp);
24126747b715Smrg    return Success;
24134642e01fSmrg
2414f7df2e56Smrg out:
24154642e01fSmrg    client->errorValue = stuff->id;
24166747b715Smrg    return rc;
241705b261ecSmrg}
241805b261ecSmrg
241905b261ecSmrgint
242005b261ecSmrgProcUninstallColormap(ClientPtr client)
242105b261ecSmrg{
242205b261ecSmrg    ColormapPtr pcmp;
24234642e01fSmrg    int rc;
2424f7df2e56Smrg
242505b261ecSmrg    REQUEST(xResourceReq);
242605b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
24274642e01fSmrg
2428f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->id, RT_COLORMAP,
2429f7df2e56Smrg                                 client, DixUninstallAccess);
24304642e01fSmrg    if (rc != Success)
2431f7df2e56Smrg        goto out;
24324642e01fSmrg
24334642e01fSmrg    rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess);
24346747b715Smrg    if (rc != Success) {
2435f7df2e56Smrg        if (rc == BadValue)
2436f7df2e56Smrg            rc = BadColor;
2437f7df2e56Smrg        goto out;
24386747b715Smrg    }
24394642e01fSmrg
2440f7df2e56Smrg    if (pcmp->mid != pcmp->pScreen->defColormap)
2441f7df2e56Smrg        (*(pcmp->pScreen->UninstallColormap)) (pcmp);
24426747b715Smrg    return Success;
24434642e01fSmrg
2444f7df2e56Smrg out:
24454642e01fSmrg    client->errorValue = stuff->id;
24466747b715Smrg    return rc;
244705b261ecSmrg}
244805b261ecSmrg
244905b261ecSmrgint
245005b261ecSmrgProcListInstalledColormaps(ClientPtr client)
245105b261ecSmrg{
2452f7df2e56Smrg    xListInstalledColormapsReply *preply;
245305b261ecSmrg    int nummaps, rc;
245405b261ecSmrg    WindowPtr pWin;
2455f7df2e56Smrg
245605b261ecSmrg    REQUEST(xResourceReq);
245705b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
24584642e01fSmrg
24594642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
246005b261ecSmrg    if (rc != Success)
2461f7df2e56Smrg        return rc;
24624642e01fSmrg
24634642e01fSmrg    rc = XaceHook(XACE_SCREEN_ACCESS, client, pWin->drawable.pScreen,
2464f7df2e56Smrg                  DixGetAttrAccess);
24654642e01fSmrg    if (rc != Success)
2466f7df2e56Smrg        return rc;
246705b261ecSmrg
24686747b715Smrg    preply = malloc(sizeof(xListInstalledColormapsReply) +
2469f7df2e56Smrg                    pWin->drawable.pScreen->maxInstalledCmaps *
2470f7df2e56Smrg                    sizeof(Colormap));
2471f7df2e56Smrg    if (!preply)
24726747b715Smrg        return BadAlloc;
247305b261ecSmrg
247405b261ecSmrg    preply->type = X_Reply;
247505b261ecSmrg    preply->sequenceNumber = client->sequence;
247605b261ecSmrg    nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps)
2477f7df2e56Smrg        (pWin->drawable.pScreen, (Colormap *) &preply[1]);
247805b261ecSmrg    preply->nColormaps = nummaps;
247905b261ecSmrg    preply->length = nummaps;
2480f7df2e56Smrg    WriteReplyToClient(client, sizeof(xListInstalledColormapsReply), preply);
248105b261ecSmrg    client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
248205b261ecSmrg    WriteSwappedDataToClient(client, nummaps * sizeof(Colormap), &preply[1]);
24836747b715Smrg    free(preply);
24846747b715Smrg    return Success;
248505b261ecSmrg}
248605b261ecSmrg
248705b261ecSmrgint
2488f7df2e56SmrgProcAllocColor(ClientPtr client)
248905b261ecSmrg{
249005b261ecSmrg    ColormapPtr pmap;
24914642e01fSmrg    int rc;
2492f7df2e56Smrg
249305b261ecSmrg    REQUEST(xAllocColorReq);
249405b261ecSmrg
249505b261ecSmrg    REQUEST_SIZE_MATCH(xAllocColorReq);
2496f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pmap, stuff->cmap, RT_COLORMAP,
2497f7df2e56Smrg                                 client, DixAddAccess);
2498f7df2e56Smrg    if (rc == Success) {
2499f7df2e56Smrg        xAllocColorReply acr = {
2500f7df2e56Smrg            .type = X_Reply,
2501f7df2e56Smrg            .sequenceNumber = client->sequence,
2502f7df2e56Smrg            .length = 0,
2503f7df2e56Smrg            .red = stuff->red,
2504f7df2e56Smrg            .green = stuff->green,
2505f7df2e56Smrg            .blue = stuff->blue,
2506f7df2e56Smrg            .pixel = 0
2507f7df2e56Smrg        };
2508f7df2e56Smrg        if ((rc = AllocColor(pmap, &acr.red, &acr.green, &acr.blue,
2509f7df2e56Smrg                             &acr.pixel, client->index)))
2510f7df2e56Smrg            return rc;
251105b261ecSmrg#ifdef PANORAMIX
2512f7df2e56Smrg        if (noPanoramiXExtension || !pmap->pScreen->myNum)
251305b261ecSmrg#endif
2514f7df2e56Smrg            WriteReplyToClient(client, sizeof(xAllocColorReply), &acr);
2515f7df2e56Smrg        return Success;
251605b261ecSmrg
251705b261ecSmrg    }
2518f7df2e56Smrg    else {
251905b261ecSmrg        client->errorValue = stuff->cmap;
25206747b715Smrg        return rc;
252105b261ecSmrg    }
252205b261ecSmrg}
252305b261ecSmrg
252405b261ecSmrgint
2525f7df2e56SmrgProcAllocNamedColor(ClientPtr client)
252605b261ecSmrg{
252705b261ecSmrg    ColormapPtr pcmp;
25284642e01fSmrg    int rc;
2529f7df2e56Smrg
253005b261ecSmrg    REQUEST(xAllocNamedColorReq);
253105b261ecSmrg
253205b261ecSmrg    REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes);
2533f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2534f7df2e56Smrg                                 client, DixAddAccess);
2535f7df2e56Smrg    if (rc == Success) {
2536f7df2e56Smrg        xAllocNamedColorReply ancr = {
2537f7df2e56Smrg            .type = X_Reply,
2538f7df2e56Smrg            .sequenceNumber = client->sequence,
2539f7df2e56Smrg            .length = 0
2540f7df2e56Smrg        };
2541f7df2e56Smrg        if (OsLookupColor
2542f7df2e56Smrg            (pcmp->pScreen->myNum, (char *) &stuff[1], stuff->nbytes,
2543f7df2e56Smrg             &ancr.exactRed, &ancr.exactGreen, &ancr.exactBlue)) {
2544f7df2e56Smrg            ancr.screenRed = ancr.exactRed;
2545f7df2e56Smrg            ancr.screenGreen = ancr.exactGreen;
2546f7df2e56Smrg            ancr.screenBlue = ancr.exactBlue;
2547f7df2e56Smrg            ancr.pixel = 0;
2548f7df2e56Smrg            if ((rc = AllocColor(pcmp,
2549f7df2e56Smrg                                 &ancr.screenRed, &ancr.screenGreen,
2550f7df2e56Smrg                                 &ancr.screenBlue, &ancr.pixel, client->index)))
2551f7df2e56Smrg                return rc;
255205b261ecSmrg#ifdef PANORAMIX
2553f7df2e56Smrg            if (noPanoramiXExtension || !pcmp->pScreen->myNum)
255405b261ecSmrg#endif
2555f7df2e56Smrg                WriteReplyToClient(client, sizeof(xAllocNamedColorReply),
2556f7df2e56Smrg                                   &ancr);
2557f7df2e56Smrg            return Success;
2558f7df2e56Smrg        }
2559f7df2e56Smrg        else
2560f7df2e56Smrg            return BadName;
2561f7df2e56Smrg
256205b261ecSmrg    }
2563f7df2e56Smrg    else {
256405b261ecSmrg        client->errorValue = stuff->cmap;
25656747b715Smrg        return rc;
256605b261ecSmrg    }
256705b261ecSmrg}
256805b261ecSmrg
256905b261ecSmrgint
2570f7df2e56SmrgProcAllocColorCells(ClientPtr client)
257105b261ecSmrg{
257205b261ecSmrg    ColormapPtr pcmp;
25734642e01fSmrg    int rc;
2574f7df2e56Smrg
257505b261ecSmrg    REQUEST(xAllocColorCellsReq);
257605b261ecSmrg
257705b261ecSmrg    REQUEST_SIZE_MATCH(xAllocColorCellsReq);
2578f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2579f7df2e56Smrg                                 client, DixAddAccess);
2580f7df2e56Smrg    if (rc == Success) {
2581f7df2e56Smrg        int npixels, nmasks;
2582f7df2e56Smrg        long length;
2583f7df2e56Smrg        Pixel *ppixels, *pmasks;
2584f7df2e56Smrg
2585f7df2e56Smrg        npixels = stuff->colors;
2586f7df2e56Smrg        if (!npixels) {
2587f7df2e56Smrg            client->errorValue = npixels;
2588f7df2e56Smrg            return BadValue;
2589f7df2e56Smrg        }
2590f7df2e56Smrg        if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) {
2591f7df2e56Smrg            client->errorValue = stuff->contiguous;
2592f7df2e56Smrg            return BadValue;
2593f7df2e56Smrg        }
2594f7df2e56Smrg        nmasks = stuff->planes;
2595f7df2e56Smrg        length = ((long) npixels + (long) nmasks) * sizeof(Pixel);
2596f7df2e56Smrg        ppixels = malloc(length);
2597f7df2e56Smrg        if (!ppixels)
25986747b715Smrg            return BadAlloc;
2599f7df2e56Smrg        pmasks = ppixels + npixels;
2600f7df2e56Smrg
2601f7df2e56Smrg        if ((rc = AllocColorCells(client->index, pcmp, npixels, nmasks,
2602f7df2e56Smrg                                  (Bool) stuff->contiguous, ppixels, pmasks))) {
2603f7df2e56Smrg            free(ppixels);
2604f7df2e56Smrg            return rc;
2605f7df2e56Smrg        }
260605b261ecSmrg#ifdef PANORAMIX
2607f7df2e56Smrg        if (noPanoramiXExtension || !pcmp->pScreen->myNum)
260805b261ecSmrg#endif
2609f7df2e56Smrg        {
2610f7df2e56Smrg            xAllocColorCellsReply accr = {
2611f7df2e56Smrg                .type = X_Reply,
2612f7df2e56Smrg                .sequenceNumber = client->sequence,
2613f7df2e56Smrg                .length = bytes_to_int32(length),
2614f7df2e56Smrg                .nPixels = npixels,
2615f7df2e56Smrg                .nMasks = nmasks
2616f7df2e56Smrg            };
2617f7df2e56Smrg            WriteReplyToClient(client, sizeof(xAllocColorCellsReply), &accr);
2618f7df2e56Smrg            client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
2619f7df2e56Smrg            WriteSwappedDataToClient(client, length, ppixels);
2620f7df2e56Smrg        }
2621f7df2e56Smrg        free(ppixels);
26226747b715Smrg        return Success;
262305b261ecSmrg    }
2624f7df2e56Smrg    else {
262505b261ecSmrg        client->errorValue = stuff->cmap;
26266747b715Smrg        return rc;
262705b261ecSmrg    }
262805b261ecSmrg}
262905b261ecSmrg
263005b261ecSmrgint
263105b261ecSmrgProcAllocColorPlanes(ClientPtr client)
263205b261ecSmrg{
263305b261ecSmrg    ColormapPtr pcmp;
26344642e01fSmrg    int rc;
2635f7df2e56Smrg
263605b261ecSmrg    REQUEST(xAllocColorPlanesReq);
263705b261ecSmrg
263805b261ecSmrg    REQUEST_SIZE_MATCH(xAllocColorPlanesReq);
2639f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2640f7df2e56Smrg                                 client, DixAddAccess);
2641f7df2e56Smrg    if (rc == Success) {
2642f7df2e56Smrg        xAllocColorPlanesReply acpr;
2643f7df2e56Smrg        int npixels;
2644f7df2e56Smrg        long length;
2645f7df2e56Smrg        Pixel *ppixels;
2646f7df2e56Smrg
2647f7df2e56Smrg        npixels = stuff->colors;
2648f7df2e56Smrg        if (!npixels) {
2649f7df2e56Smrg            client->errorValue = npixels;
2650f7df2e56Smrg            return BadValue;
2651f7df2e56Smrg        }
2652f7df2e56Smrg        if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) {
2653f7df2e56Smrg            client->errorValue = stuff->contiguous;
2654f7df2e56Smrg            return BadValue;
2655f7df2e56Smrg        }
2656f7df2e56Smrg        acpr = (xAllocColorPlanesReply) {
2657f7df2e56Smrg            .type = X_Reply,
2658f7df2e56Smrg            .sequenceNumber = client->sequence,
2659f7df2e56Smrg            .nPixels = npixels
2660f7df2e56Smrg        };
2661f7df2e56Smrg        length = (long) npixels *sizeof(Pixel);
2662f7df2e56Smrg
2663f7df2e56Smrg        ppixels = malloc(length);
2664f7df2e56Smrg        if (!ppixels)
26656747b715Smrg            return BadAlloc;
2666f7df2e56Smrg        if ((rc = AllocColorPlanes(client->index, pcmp, npixels,
2667f7df2e56Smrg                                   (int) stuff->red, (int) stuff->green,
2668f7df2e56Smrg                                   (int) stuff->blue, (Bool) stuff->contiguous,
2669f7df2e56Smrg                                   ppixels, &acpr.redMask, &acpr.greenMask,
2670f7df2e56Smrg                                   &acpr.blueMask))) {
26716747b715Smrg            free(ppixels);
2672f7df2e56Smrg            return rc;
2673f7df2e56Smrg        }
2674f7df2e56Smrg        acpr.length = bytes_to_int32(length);
267505b261ecSmrg#ifdef PANORAMIX
2676f7df2e56Smrg        if (noPanoramiXExtension || !pcmp->pScreen->myNum)
267705b261ecSmrg#endif
2678f7df2e56Smrg        {
2679f7df2e56Smrg            WriteReplyToClient(client, sizeof(xAllocColorPlanesReply), &acpr);
2680f7df2e56Smrg            client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
2681f7df2e56Smrg            WriteSwappedDataToClient(client, length, ppixels);
2682f7df2e56Smrg        }
2683f7df2e56Smrg        free(ppixels);
26846747b715Smrg        return Success;
268505b261ecSmrg    }
2686f7df2e56Smrg    else {
268705b261ecSmrg        client->errorValue = stuff->cmap;
26886747b715Smrg        return rc;
268905b261ecSmrg    }
269005b261ecSmrg}
269105b261ecSmrg
269205b261ecSmrgint
269305b261ecSmrgProcFreeColors(ClientPtr client)
269405b261ecSmrg{
269505b261ecSmrg    ColormapPtr pcmp;
26964642e01fSmrg    int rc;
2697f7df2e56Smrg
269805b261ecSmrg    REQUEST(xFreeColorsReq);
269905b261ecSmrg
270005b261ecSmrg    REQUEST_AT_LEAST_SIZE(xFreeColorsReq);
2701f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2702f7df2e56Smrg                                 client, DixRemoveAccess);
2703f7df2e56Smrg    if (rc == Success) {
2704f7df2e56Smrg        int count;
270505b261ecSmrg
2706f7df2e56Smrg        if (pcmp->flags & AllAllocated)
2707f7df2e56Smrg            return BadAccess;
2708f7df2e56Smrg        count = bytes_to_int32((client->req_len << 2) - sizeof(xFreeColorsReq));
2709f7df2e56Smrg        return FreeColors(pcmp, client->index, count,
2710f7df2e56Smrg                          (Pixel *) &stuff[1], (Pixel) stuff->planeMask);
271105b261ecSmrg    }
2712f7df2e56Smrg    else {
271305b261ecSmrg        client->errorValue = stuff->cmap;
27146747b715Smrg        return rc;
271505b261ecSmrg    }
271605b261ecSmrg}
271705b261ecSmrg
271805b261ecSmrgint
2719f7df2e56SmrgProcStoreColors(ClientPtr client)
272005b261ecSmrg{
272105b261ecSmrg    ColormapPtr pcmp;
27224642e01fSmrg    int rc;
2723f7df2e56Smrg
272405b261ecSmrg    REQUEST(xStoreColorsReq);
272505b261ecSmrg
272605b261ecSmrg    REQUEST_AT_LEAST_SIZE(xStoreColorsReq);
2727f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2728f7df2e56Smrg                                 client, DixWriteAccess);
2729f7df2e56Smrg    if (rc == Success) {
2730f7df2e56Smrg        int count;
273105b261ecSmrg
273205b261ecSmrg        count = (client->req_len << 2) - sizeof(xStoreColorsReq);
2733f7df2e56Smrg        if (count % sizeof(xColorItem))
2734f7df2e56Smrg            return BadLength;
2735f7df2e56Smrg        count /= sizeof(xColorItem);
2736f7df2e56Smrg        return StoreColors(pcmp, count, (xColorItem *) &stuff[1], client);
273705b261ecSmrg    }
2738f7df2e56Smrg    else {
273905b261ecSmrg        client->errorValue = stuff->cmap;
27406747b715Smrg        return rc;
274105b261ecSmrg    }
274205b261ecSmrg}
274305b261ecSmrg
274405b261ecSmrgint
2745f7df2e56SmrgProcStoreNamedColor(ClientPtr client)
274605b261ecSmrg{
274705b261ecSmrg    ColormapPtr pcmp;
27484642e01fSmrg    int rc;
2749f7df2e56Smrg
275005b261ecSmrg    REQUEST(xStoreNamedColorReq);
275105b261ecSmrg
275205b261ecSmrg    REQUEST_FIXED_SIZE(xStoreNamedColorReq, stuff->nbytes);
2753f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2754f7df2e56Smrg                                 client, DixWriteAccess);
2755f7df2e56Smrg    if (rc == Success) {
2756f7df2e56Smrg        xColorItem def;
2757f7df2e56Smrg
2758f7df2e56Smrg        if (OsLookupColor(pcmp->pScreen->myNum, (char *) &stuff[1],
2759f7df2e56Smrg                          stuff->nbytes, &def.red, &def.green, &def.blue)) {
2760f7df2e56Smrg            def.flags = stuff->flags;
2761f7df2e56Smrg            def.pixel = stuff->pixel;
2762f7df2e56Smrg            return StoreColors(pcmp, 1, &def, client);
2763f7df2e56Smrg        }
27646747b715Smrg        return BadName;
276505b261ecSmrg    }
2766f7df2e56Smrg    else {
276705b261ecSmrg        client->errorValue = stuff->cmap;
27686747b715Smrg        return rc;
276905b261ecSmrg    }
277005b261ecSmrg}
277105b261ecSmrg
277205b261ecSmrgint
277305b261ecSmrgProcQueryColors(ClientPtr client)
277405b261ecSmrg{
277505b261ecSmrg    ColormapPtr pcmp;
27764642e01fSmrg    int rc;
2777f7df2e56Smrg
277805b261ecSmrg    REQUEST(xQueryColorsReq);
277905b261ecSmrg
278005b261ecSmrg    REQUEST_AT_LEAST_SIZE(xQueryColorsReq);
2781f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2782f7df2e56Smrg                                 client, DixReadAccess);
2783f7df2e56Smrg    if (rc == Success) {
2784f7df2e56Smrg        int count;
2785f7df2e56Smrg        xrgb *prgbs;
2786f7df2e56Smrg        xQueryColorsReply qcr;
2787f7df2e56Smrg
2788f7df2e56Smrg        count =
2789f7df2e56Smrg            bytes_to_int32((client->req_len << 2) - sizeof(xQueryColorsReq));
2790f7df2e56Smrg        prgbs = calloc(count, sizeof(xrgb));
2791f7df2e56Smrg        if (!prgbs && count)
27926747b715Smrg            return BadAlloc;
2793f7df2e56Smrg        if ((rc =
2794f7df2e56Smrg             QueryColors(pcmp, count, (Pixel *) &stuff[1], prgbs, client))) {
2795f7df2e56Smrg            free(prgbs);
2796f7df2e56Smrg            return rc;
2797f7df2e56Smrg        }
2798f7df2e56Smrg        qcr = (xQueryColorsReply) {
2799f7df2e56Smrg            .type = X_Reply,
2800f7df2e56Smrg            .sequenceNumber = client->sequence,
2801f7df2e56Smrg            .length = bytes_to_int32(count * sizeof(xrgb)),
2802f7df2e56Smrg            .nColors = count
2803f7df2e56Smrg        };
2804f7df2e56Smrg        WriteReplyToClient(client, sizeof(xQueryColorsReply), &qcr);
2805f7df2e56Smrg        if (count) {
2806f7df2e56Smrg            client->pSwapReplyFunc = (ReplySwapPtr) SQColorsExtend;
2807f7df2e56Smrg            WriteSwappedDataToClient(client, count * sizeof(xrgb), prgbs);
2808f7df2e56Smrg        }
2809f7df2e56Smrg        free(prgbs);
2810f7df2e56Smrg        return Success;
2811f7df2e56Smrg
281205b261ecSmrg    }
2813f7df2e56Smrg    else {
281405b261ecSmrg        client->errorValue = stuff->cmap;
28156747b715Smrg        return rc;
281605b261ecSmrg    }
2817f7df2e56Smrg}
281805b261ecSmrg
281905b261ecSmrgint
282005b261ecSmrgProcLookupColor(ClientPtr client)
282105b261ecSmrg{
282205b261ecSmrg    ColormapPtr pcmp;
28234642e01fSmrg    int rc;
2824f7df2e56Smrg
282505b261ecSmrg    REQUEST(xLookupColorReq);
282605b261ecSmrg
282705b261ecSmrg    REQUEST_FIXED_SIZE(xLookupColorReq, stuff->nbytes);
2828f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2829f7df2e56Smrg                                 client, DixReadAccess);
2830f7df2e56Smrg    if (rc == Success) {
2831f7df2e56Smrg        CARD16 exactRed, exactGreen, exactBlue;
2832f7df2e56Smrg
2833f7df2e56Smrg        if (OsLookupColor
2834f7df2e56Smrg            (pcmp->pScreen->myNum, (char *) &stuff[1], stuff->nbytes,
2835f7df2e56Smrg             &exactRed, &exactGreen, &exactBlue)) {
2836f7df2e56Smrg            xLookupColorReply lcr = {
2837f7df2e56Smrg                .type = X_Reply,
2838f7df2e56Smrg                .sequenceNumber = client->sequence,
2839f7df2e56Smrg                .length = 0,
2840f7df2e56Smrg                .exactRed = exactRed,
2841f7df2e56Smrg                .exactGreen = exactGreen,
2842f7df2e56Smrg                .exactBlue = exactBlue,
2843f7df2e56Smrg                .screenRed = exactRed,
2844f7df2e56Smrg                .screenGreen = exactGreen,
2845f7df2e56Smrg                .screenBlue = exactBlue
2846f7df2e56Smrg            };
2847f7df2e56Smrg            (*pcmp->pScreen->ResolveColor) (&lcr.screenRed,
2848f7df2e56Smrg                                            &lcr.screenGreen,
2849f7df2e56Smrg                                            &lcr.screenBlue, pcmp->pVisual);
2850f7df2e56Smrg            WriteReplyToClient(client, sizeof(xLookupColorReply), &lcr);
2851f7df2e56Smrg            return Success;
2852f7df2e56Smrg        }
28536747b715Smrg        return BadName;
285405b261ecSmrg    }
2855f7df2e56Smrg    else {
285605b261ecSmrg        client->errorValue = stuff->cmap;
28576747b715Smrg        return rc;
285805b261ecSmrg    }
285905b261ecSmrg}
286005b261ecSmrg
286105b261ecSmrgint
2862f7df2e56SmrgProcCreateCursor(ClientPtr client)
286305b261ecSmrg{
2864f7df2e56Smrg    CursorPtr pCursor;
2865f7df2e56Smrg    PixmapPtr src;
2866f7df2e56Smrg    PixmapPtr msk;
2867f7df2e56Smrg    unsigned char *srcbits;
2868f7df2e56Smrg    unsigned char *mskbits;
2869f7df2e56Smrg    unsigned short width, height;
2870f7df2e56Smrg    long n;
2871f7df2e56Smrg    CursorMetricRec cm;
28724642e01fSmrg    int rc;
287305b261ecSmrg
287405b261ecSmrg    REQUEST(xCreateCursorReq);
287505b261ecSmrg
287605b261ecSmrg    REQUEST_SIZE_MATCH(xCreateCursorReq);
287705b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->cid, client);
287805b261ecSmrg
2879f7df2e56Smrg    rc = dixLookupResourceByType((void **) &src, stuff->source, RT_PIXMAP,
2880f7df2e56Smrg                                 client, DixReadAccess);
28814642e01fSmrg    if (rc != Success) {
2882f7df2e56Smrg        client->errorValue = stuff->source;
2883f7df2e56Smrg        return rc;
288405b261ecSmrg    }
28854642e01fSmrg
2886f7df2e56Smrg    if (src->drawable.depth != 1)
2887f7df2e56Smrg        return (BadMatch);
2888f7df2e56Smrg
2889f7df2e56Smrg    /* Find and validate cursor mask pixmap, if one is provided */
2890f7df2e56Smrg    if (stuff->mask != None) {
2891f7df2e56Smrg        rc = dixLookupResourceByType((void **) &msk, stuff->mask, RT_PIXMAP,
2892f7df2e56Smrg                                     client, DixReadAccess);
2893f7df2e56Smrg        if (rc != Success) {
2894f7df2e56Smrg            client->errorValue = stuff->mask;
2895f7df2e56Smrg            return rc;
2896f7df2e56Smrg        }
2897f7df2e56Smrg
2898f7df2e56Smrg        if (src->drawable.width != msk->drawable.width
2899f7df2e56Smrg            || src->drawable.height != msk->drawable.height
2900f7df2e56Smrg            || src->drawable.depth != 1 || msk->drawable.depth != 1)
2901f7df2e56Smrg            return BadMatch;
2902f7df2e56Smrg    }
2903f7df2e56Smrg    else
2904f7df2e56Smrg        msk = NULL;
290505b261ecSmrg
290605b261ecSmrg    width = src->drawable.width;
290705b261ecSmrg    height = src->drawable.height;
290805b261ecSmrg
2909f7df2e56Smrg    if (stuff->x > width || stuff->y > height)
2910f7df2e56Smrg        return BadMatch;
291105b261ecSmrg
2912f7df2e56Smrg    srcbits = calloc(BitmapBytePad(width), height);
291305b261ecSmrg    if (!srcbits)
2914f7df2e56Smrg        return BadAlloc;
2915f7df2e56Smrg    n = BitmapBytePad(width) * height;
29166747b715Smrg    mskbits = malloc(n);
2917f7df2e56Smrg    if (!mskbits) {
2918f7df2e56Smrg        free(srcbits);
2919f7df2e56Smrg        return BadAlloc;
292005b261ecSmrg    }
292105b261ecSmrg
2922f7df2e56Smrg    (*src->drawable.pScreen->GetImage) ((DrawablePtr) src, 0, 0, width, height,
2923f7df2e56Smrg                                        XYPixmap, 1, (void *) srcbits);
2924f7df2e56Smrg    if (msk == (PixmapPtr) NULL) {
2925f7df2e56Smrg        unsigned char *bits = mskbits;
2926f7df2e56Smrg
2927f7df2e56Smrg        while (--n >= 0)
2928f7df2e56Smrg            *bits++ = ~0;
292905b261ecSmrg    }
2930f7df2e56Smrg    else {
2931f7df2e56Smrg        /* zeroing the (pad) bits helps some ddx cursor handling */
2932f7df2e56Smrg        memset((char *) mskbits, 0, n);
2933f7df2e56Smrg        (*msk->drawable.pScreen->GetImage) ((DrawablePtr) msk, 0, 0, width,
2934f7df2e56Smrg                                            height, XYPixmap, 1,
2935f7df2e56Smrg                                            (void *) mskbits);
293605b261ecSmrg    }
293705b261ecSmrg    cm.width = width;
293805b261ecSmrg    cm.height = height;
293905b261ecSmrg    cm.xhot = stuff->x;
294005b261ecSmrg    cm.yhot = stuff->y;
29414642e01fSmrg    rc = AllocARGBCursor(srcbits, mskbits, NULL, &cm,
2942f7df2e56Smrg                         stuff->foreRed, stuff->foreGreen, stuff->foreBlue,
2943f7df2e56Smrg                         stuff->backRed, stuff->backGreen, stuff->backBlue,
2944f7df2e56Smrg                         &pCursor, client, stuff->cid);
294505b261ecSmrg
29464642e01fSmrg    if (rc != Success)
2947f7df2e56Smrg        goto bail;
2948f7df2e56Smrg    if (!AddResource(stuff->cid, RT_CURSOR, (void *) pCursor)) {
2949f7df2e56Smrg        rc = BadAlloc;
2950f7df2e56Smrg        goto bail;
2951f7df2e56Smrg    }
29524642e01fSmrg
29536747b715Smrg    return Success;
2954f7df2e56Smrg bail:
2955f7df2e56Smrg    free(srcbits);
2956f7df2e56Smrg    free(mskbits);
2957f7df2e56Smrg    return rc;
295805b261ecSmrg}
295905b261ecSmrg
296005b261ecSmrgint
2961f7df2e56SmrgProcCreateGlyphCursor(ClientPtr client)
296205b261ecSmrg{
296305b261ecSmrg    CursorPtr pCursor;
296405b261ecSmrg    int res;
296505b261ecSmrg
296605b261ecSmrg    REQUEST(xCreateGlyphCursorReq);
296705b261ecSmrg
296805b261ecSmrg    REQUEST_SIZE_MATCH(xCreateGlyphCursorReq);
296905b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->cid, client);
297005b261ecSmrg
297105b261ecSmrg    res = AllocGlyphCursor(stuff->source, stuff->sourceChar,
2972f7df2e56Smrg                           stuff->mask, stuff->maskChar,
2973f7df2e56Smrg                           stuff->foreRed, stuff->foreGreen, stuff->foreBlue,
2974f7df2e56Smrg                           stuff->backRed, stuff->backGreen, stuff->backBlue,
2975f7df2e56Smrg                           &pCursor, client, stuff->cid);
297605b261ecSmrg    if (res != Success)
2977f7df2e56Smrg        return res;
2978f7df2e56Smrg    if (AddResource(stuff->cid, RT_CURSOR, (void *) pCursor))
2979f7df2e56Smrg        return Success;
298005b261ecSmrg    return BadAlloc;
298105b261ecSmrg}
298205b261ecSmrg
298305b261ecSmrgint
2984f7df2e56SmrgProcFreeCursor(ClientPtr client)
298505b261ecSmrg{
298605b261ecSmrg    CursorPtr pCursor;
29874642e01fSmrg    int rc;
2988f7df2e56Smrg
298905b261ecSmrg    REQUEST(xResourceReq);
299005b261ecSmrg
299105b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
2992f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pCursor, stuff->id, RT_CURSOR,
2993f7df2e56Smrg                                 client, DixDestroyAccess);
2994f7df2e56Smrg    if (rc == Success) {
2995f7df2e56Smrg        FreeResource(stuff->id, RT_NONE);
2996f7df2e56Smrg        return Success;
299705b261ecSmrg    }
2998f7df2e56Smrg    else {
2999f7df2e56Smrg        client->errorValue = stuff->id;
3000f7df2e56Smrg        return rc;
300105b261ecSmrg    }
300205b261ecSmrg}
300305b261ecSmrg
300405b261ecSmrgint
3005f7df2e56SmrgProcQueryBestSize(ClientPtr client)
300605b261ecSmrg{
3007f7df2e56Smrg    xQueryBestSizeReply reply;
300805b261ecSmrg    DrawablePtr pDraw;
300905b261ecSmrg    ScreenPtr pScreen;
301005b261ecSmrg    int rc;
3011f7df2e56Smrg
301205b261ecSmrg    REQUEST(xQueryBestSizeReq);
301305b261ecSmrg    REQUEST_SIZE_MATCH(xQueryBestSizeReq);
301405b261ecSmrg
3015f7df2e56Smrg    if ((stuff->class != CursorShape) &&
3016f7df2e56Smrg        (stuff->class != TileShape) && (stuff->class != StippleShape)) {
3017f7df2e56Smrg        client->errorValue = stuff->class;
30186747b715Smrg        return BadValue;
301905b261ecSmrg    }
302005b261ecSmrg
302105b261ecSmrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
3022f7df2e56Smrg                           DixGetAttrAccess);
302305b261ecSmrg    if (rc != Success)
3024f7df2e56Smrg        return rc;
302505b261ecSmrg    if (stuff->class != CursorShape && pDraw->type == UNDRAWABLE_WINDOW)
3026f7df2e56Smrg        return BadMatch;
302705b261ecSmrg    pScreen = pDraw->pScreen;
30284642e01fSmrg    rc = XaceHook(XACE_SCREEN_ACCESS, client, pScreen, DixGetAttrAccess);
30294642e01fSmrg    if (rc != Success)
3030f7df2e56Smrg        return rc;
3031f7df2e56Smrg    (*pScreen->QueryBestSize) (stuff->class, &stuff->width,
3032f7df2e56Smrg                               &stuff->height, pScreen);
3033f7df2e56Smrg    reply = (xQueryBestSizeReply) {
3034f7df2e56Smrg        .type = X_Reply,
3035f7df2e56Smrg        .sequenceNumber = client->sequence,
3036f7df2e56Smrg        .length = 0,
3037f7df2e56Smrg        .width = stuff->width,
3038f7df2e56Smrg        .height = stuff->height
3039f7df2e56Smrg    };
304005b261ecSmrg    WriteReplyToClient(client, sizeof(xQueryBestSizeReply), &reply);
30416747b715Smrg    return Success;
304205b261ecSmrg}
304305b261ecSmrg
304405b261ecSmrgint
3045f7df2e56SmrgProcSetScreenSaver(ClientPtr client)
304605b261ecSmrg{
30474642e01fSmrg    int rc, i, blankingOption, exposureOption;
3048f7df2e56Smrg
304905b261ecSmrg    REQUEST(xSetScreenSaverReq);
305005b261ecSmrg    REQUEST_SIZE_MATCH(xSetScreenSaverReq);
30514642e01fSmrg
30524642e01fSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
3053f7df2e56Smrg        rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i],
3054f7df2e56Smrg                      DixSetAttrAccess);
3055f7df2e56Smrg        if (rc != Success)
3056f7df2e56Smrg            return rc;
30574642e01fSmrg    }
30584642e01fSmrg
305905b261ecSmrg    blankingOption = stuff->preferBlank;
306005b261ecSmrg    if ((blankingOption != DontPreferBlanking) &&
306105b261ecSmrg        (blankingOption != PreferBlanking) &&
3062f7df2e56Smrg        (blankingOption != DefaultBlanking)) {
3063f7df2e56Smrg        client->errorValue = blankingOption;
306405b261ecSmrg        return BadValue;
306505b261ecSmrg    }
306605b261ecSmrg    exposureOption = stuff->allowExpose;
306705b261ecSmrg    if ((exposureOption != DontAllowExposures) &&
306805b261ecSmrg        (exposureOption != AllowExposures) &&
3069f7df2e56Smrg        (exposureOption != DefaultExposures)) {
3070f7df2e56Smrg        client->errorValue = exposureOption;
307105b261ecSmrg        return BadValue;
307205b261ecSmrg    }
3073f7df2e56Smrg    if (stuff->timeout < -1) {
3074f7df2e56Smrg        client->errorValue = stuff->timeout;
307505b261ecSmrg        return BadValue;
307605b261ecSmrg    }
3077f7df2e56Smrg    if (stuff->interval < -1) {
3078f7df2e56Smrg        client->errorValue = stuff->interval;
307905b261ecSmrg        return BadValue;
308005b261ecSmrg    }
308105b261ecSmrg
308205b261ecSmrg    if (blankingOption == DefaultBlanking)
3083f7df2e56Smrg        ScreenSaverBlanking = defaultScreenSaverBlanking;
308405b261ecSmrg    else
3085f7df2e56Smrg        ScreenSaverBlanking = blankingOption;
308605b261ecSmrg    if (exposureOption == DefaultExposures)
3087f7df2e56Smrg        ScreenSaverAllowExposures = defaultScreenSaverAllowExposures;
308805b261ecSmrg    else
3089f7df2e56Smrg        ScreenSaverAllowExposures = exposureOption;
309005b261ecSmrg
309105b261ecSmrg    if (stuff->timeout >= 0)
3092f7df2e56Smrg        ScreenSaverTime = stuff->timeout * MILLI_PER_SECOND;
3093f7df2e56Smrg    else
3094f7df2e56Smrg        ScreenSaverTime = defaultScreenSaverTime;
309505b261ecSmrg    if (stuff->interval >= 0)
3096f7df2e56Smrg        ScreenSaverInterval = stuff->interval * MILLI_PER_SECOND;
309705b261ecSmrg    else
3098f7df2e56Smrg        ScreenSaverInterval = defaultScreenSaverInterval;
309905b261ecSmrg
310005b261ecSmrg    SetScreenSaverTimer();
31016747b715Smrg    return Success;
310205b261ecSmrg}
310305b261ecSmrg
310405b261ecSmrgint
310505b261ecSmrgProcGetScreenSaver(ClientPtr client)
310605b261ecSmrg{
310705b261ecSmrg    xGetScreenSaverReply rep;
31084642e01fSmrg    int rc, i;
3109f7df2e56Smrg
311005b261ecSmrg    REQUEST_SIZE_MATCH(xReq);
31114642e01fSmrg
31124642e01fSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
3113f7df2e56Smrg        rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i],
3114f7df2e56Smrg                      DixGetAttrAccess);
3115f7df2e56Smrg        if (rc != Success)
3116f7df2e56Smrg            return rc;
3117f7df2e56Smrg    }
3118f7df2e56Smrg
3119f7df2e56Smrg    rep = (xGetScreenSaverReply) {
3120f7df2e56Smrg        .type = X_Reply,
3121f7df2e56Smrg        .sequenceNumber = client->sequence,
3122f7df2e56Smrg        .length = 0,
3123f7df2e56Smrg        .timeout = ScreenSaverTime / MILLI_PER_SECOND,
3124f7df2e56Smrg        .interval = ScreenSaverInterval / MILLI_PER_SECOND,
3125f7df2e56Smrg        .preferBlanking = ScreenSaverBlanking,
3126f7df2e56Smrg        .allowExposures = ScreenSaverAllowExposures
3127f7df2e56Smrg    };
312805b261ecSmrg    WriteReplyToClient(client, sizeof(xGetScreenSaverReply), &rep);
31296747b715Smrg    return Success;
313005b261ecSmrg}
313105b261ecSmrg
313205b261ecSmrgint
313305b261ecSmrgProcChangeHosts(ClientPtr client)
313405b261ecSmrg{
313505b261ecSmrg    REQUEST(xChangeHostsReq);
313605b261ecSmrg
313705b261ecSmrg    REQUEST_FIXED_SIZE(xChangeHostsReq, stuff->hostLength);
313805b261ecSmrg
3139f7df2e56Smrg    if (stuff->mode == HostInsert)
3140f7df2e56Smrg        return AddHost(client, (int) stuff->hostFamily,
3141f7df2e56Smrg                       stuff->hostLength, (void *) &stuff[1]);
31426747b715Smrg    if (stuff->mode == HostDelete)
3143f7df2e56Smrg        return RemoveHost(client, (int) stuff->hostFamily,
3144f7df2e56Smrg                          stuff->hostLength, (void *) &stuff[1]);
31456747b715Smrg    client->errorValue = stuff->mode;
31466747b715Smrg    return BadValue;
314705b261ecSmrg}
314805b261ecSmrg
314905b261ecSmrgint
315005b261ecSmrgProcListHosts(ClientPtr client)
315105b261ecSmrg{
315205b261ecSmrg    xListHostsReply reply;
3153f7df2e56Smrg    int len, nHosts, result;
3154f7df2e56Smrg    BOOL enabled;
3155f7df2e56Smrg    void *pdata;
3156f7df2e56Smrg
315705b261ecSmrg    /* REQUEST(xListHostsReq); */
315805b261ecSmrg
315905b261ecSmrg    REQUEST_SIZE_MATCH(xListHostsReq);
316005b261ecSmrg
316105b261ecSmrg    /* untrusted clients can't list hosts */
31624642e01fSmrg    result = XaceHook(XACE_SERVER_ACCESS, client, DixReadAccess);
31634642e01fSmrg    if (result != Success)
3164f7df2e56Smrg        return result;
316505b261ecSmrg
3166f7df2e56Smrg    result = GetHosts(&pdata, &nHosts, &len, &enabled);
316705b261ecSmrg    if (result != Success)
3168f7df2e56Smrg        return result;
3169f7df2e56Smrg
3170f7df2e56Smrg    reply = (xListHostsReply) {
3171f7df2e56Smrg        .type = X_Reply,
3172f7df2e56Smrg        .enabled = enabled,
3173f7df2e56Smrg        .sequenceNumber = client->sequence,
3174f7df2e56Smrg        .length = bytes_to_int32(len),
3175f7df2e56Smrg        .nHosts = nHosts
3176f7df2e56Smrg    };
317705b261ecSmrg    WriteReplyToClient(client, sizeof(xListHostsReply), &reply);
3178f7df2e56Smrg    if (nHosts) {
3179f7df2e56Smrg        client->pSwapReplyFunc = (ReplySwapPtr) SLHostsExtend;
3180f7df2e56Smrg        WriteSwappedDataToClient(client, len, pdata);
318105b261ecSmrg    }
31826747b715Smrg    free(pdata);
31836747b715Smrg    return Success;
318405b261ecSmrg}
318505b261ecSmrg
318605b261ecSmrgint
318705b261ecSmrgProcChangeAccessControl(ClientPtr client)
318805b261ecSmrg{
318905b261ecSmrg    REQUEST(xSetAccessControlReq);
319005b261ecSmrg
319105b261ecSmrg    REQUEST_SIZE_MATCH(xSetAccessControlReq);
3192f7df2e56Smrg    if ((stuff->mode != EnableAccess) && (stuff->mode != DisableAccess)) {
3193f7df2e56Smrg        client->errorValue = stuff->mode;
319405b261ecSmrg        return BadValue;
319505b261ecSmrg    }
31966747b715Smrg    return ChangeAccessControl(client, stuff->mode == EnableAccess);
319705b261ecSmrg}
319805b261ecSmrg
319905b261ecSmrg/*********************
320005b261ecSmrg * CloseDownRetainedResources
320105b261ecSmrg *
3202f7df2e56Smrg *    Find all clients that are gone and have terminated in RetainTemporary
320305b261ecSmrg *    and destroy their resources.
320405b261ecSmrg *********************/
320505b261ecSmrg
320605b261ecSmrgstatic void
320705b261ecSmrgCloseDownRetainedResources(void)
320805b261ecSmrg{
320905b261ecSmrg    int i;
321005b261ecSmrg    ClientPtr client;
321105b261ecSmrg
3212f7df2e56Smrg    for (i = 1; i < currentMaxClients; i++) {
321305b261ecSmrg        client = clients[i];
321405b261ecSmrg        if (client && (client->closeDownMode == RetainTemporary)
3215f7df2e56Smrg            && (client->clientGone))
3216f7df2e56Smrg            CloseDownClient(client);
321705b261ecSmrg    }
321805b261ecSmrg}
321905b261ecSmrg
322005b261ecSmrgint
322105b261ecSmrgProcKillClient(ClientPtr client)
322205b261ecSmrg{
322305b261ecSmrg    REQUEST(xResourceReq);
322405b261ecSmrg    ClientPtr killclient;
322505b261ecSmrg    int rc;
322605b261ecSmrg
322705b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
3228f7df2e56Smrg    if (stuff->id == AllTemporary) {
3229f7df2e56Smrg        CloseDownRetainedResources();
32306747b715Smrg        return Success;
323105b261ecSmrg    }
323205b261ecSmrg
323305b261ecSmrg    rc = dixLookupClient(&killclient, stuff->id, client, DixDestroyAccess);
323405b261ecSmrg    if (rc == Success) {
3235f7df2e56Smrg        CloseDownClient(killclient);
3236f7df2e56Smrg        if (client == killclient) {
3237f7df2e56Smrg            /* force yield and return Success, so that Dispatch()
3238f7df2e56Smrg             * doesn't try to touch client
3239f7df2e56Smrg             */
3240f7df2e56Smrg            isItTimeToYield = TRUE;
3241f7df2e56Smrg        }
3242f7df2e56Smrg        return Success;
324305b261ecSmrg    }
324405b261ecSmrg    else
3245f7df2e56Smrg        return rc;
324605b261ecSmrg}
324705b261ecSmrg
324805b261ecSmrgint
324905b261ecSmrgProcSetFontPath(ClientPtr client)
325005b261ecSmrg{
325105b261ecSmrg    unsigned char *ptr;
325205b261ecSmrg    unsigned long nbytes, total;
325305b261ecSmrg    long nfonts;
32546747b715Smrg    int n;
3255f7df2e56Smrg
325605b261ecSmrg    REQUEST(xSetFontPathReq);
3257f7df2e56Smrg
325805b261ecSmrg    REQUEST_AT_LEAST_SIZE(xSetFontPathReq);
3259f7df2e56Smrg
326005b261ecSmrg    nbytes = (client->req_len << 2) - sizeof(xSetFontPathReq);
326105b261ecSmrg    total = nbytes;
3262f7df2e56Smrg    ptr = (unsigned char *) &stuff[1];
326305b261ecSmrg    nfonts = stuff->nFonts;
3264f7df2e56Smrg    while (--nfonts >= 0) {
3265f7df2e56Smrg        if ((total == 0) || (total < (n = (*ptr + 1))))
3266f7df2e56Smrg            return BadLength;
3267f7df2e56Smrg        total -= n;
3268f7df2e56Smrg        ptr += n;
326905b261ecSmrg    }
327005b261ecSmrg    if (total >= 4)
3271f7df2e56Smrg        return BadLength;
3272f7df2e56Smrg    return SetFontPath(client, stuff->nFonts, (unsigned char *) &stuff[1]);
327305b261ecSmrg}
327405b261ecSmrg
327505b261ecSmrgint
327605b261ecSmrgProcGetFontPath(ClientPtr client)
327705b261ecSmrg{
327805b261ecSmrg    xGetFontPathReply reply;
32794642e01fSmrg    int rc, stringLens, numpaths;
328005b261ecSmrg    unsigned char *bufferStart;
3281f7df2e56Smrg
328205b261ecSmrg    /* REQUEST (xReq); */
328305b261ecSmrg
328405b261ecSmrg    REQUEST_SIZE_MATCH(xReq);
32854642e01fSmrg    rc = GetFontPath(client, &numpaths, &stringLens, &bufferStart);
32864642e01fSmrg    if (rc != Success)
3287f7df2e56Smrg        return rc;
328805b261ecSmrg
3289f7df2e56Smrg    reply = (xGetFontPathReply) {
3290f7df2e56Smrg        .type = X_Reply,
3291f7df2e56Smrg        .sequenceNumber = client->sequence,
3292f7df2e56Smrg        .length = bytes_to_int32(stringLens + numpaths),
3293f7df2e56Smrg        .nPaths = numpaths
3294f7df2e56Smrg    };
329505b261ecSmrg
329605b261ecSmrg    WriteReplyToClient(client, sizeof(xGetFontPathReply), &reply);
329705b261ecSmrg    if (stringLens || numpaths)
3298f7df2e56Smrg        WriteToClient(client, stringLens + numpaths, bufferStart);
32996747b715Smrg    return Success;
330005b261ecSmrg}
330105b261ecSmrg
330205b261ecSmrgint
330305b261ecSmrgProcChangeCloseDownMode(ClientPtr client)
330405b261ecSmrg{
33054642e01fSmrg    int rc;
3306f7df2e56Smrg
330705b261ecSmrg    REQUEST(xSetCloseDownModeReq);
330805b261ecSmrg    REQUEST_SIZE_MATCH(xSetCloseDownModeReq);
33094642e01fSmrg
33104642e01fSmrg    rc = XaceHook(XACE_CLIENT_ACCESS, client, client, DixManageAccess);
33114642e01fSmrg    if (rc != Success)
3312f7df2e56Smrg        return rc;
33134642e01fSmrg
331405b261ecSmrg    if ((stuff->mode == AllTemporary) ||
3315f7df2e56Smrg        (stuff->mode == RetainPermanent) || (stuff->mode == RetainTemporary)) {
3316f7df2e56Smrg        client->closeDownMode = stuff->mode;
3317f7df2e56Smrg        return Success;
331805b261ecSmrg    }
3319f7df2e56Smrg    else {
3320f7df2e56Smrg        client->errorValue = stuff->mode;
3321f7df2e56Smrg        return BadValue;
332205b261ecSmrg    }
332305b261ecSmrg}
332405b261ecSmrg
3325f7df2e56Smrgint
3326f7df2e56SmrgProcForceScreenSaver(ClientPtr client)
3327f7df2e56Smrg{
33284642e01fSmrg    int rc;
3329f7df2e56Smrg
333005b261ecSmrg    REQUEST(xForceScreenSaverReq);
333105b261ecSmrg
333205b261ecSmrg    REQUEST_SIZE_MATCH(xForceScreenSaverReq);
3333f7df2e56Smrg
3334f7df2e56Smrg    if ((stuff->mode != ScreenSaverReset) && (stuff->mode != ScreenSaverActive)) {
3335f7df2e56Smrg        client->errorValue = stuff->mode;
333605b261ecSmrg        return BadValue;
333705b261ecSmrg    }
3338f7df2e56Smrg    rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, (int) stuff->mode);
33394642e01fSmrg    if (rc != Success)
3340f7df2e56Smrg        return rc;
33416747b715Smrg    return Success;
334205b261ecSmrg}
334305b261ecSmrg
3344f7df2e56Smrgint
3345f7df2e56SmrgProcNoOperation(ClientPtr client)
334605b261ecSmrg{
334705b261ecSmrg    REQUEST_AT_LEAST_SIZE(xReq);
3348f7df2e56Smrg
334905b261ecSmrg    /* noop -- don't do anything */
33506747b715Smrg    return Success;
335105b261ecSmrg}
335205b261ecSmrg
335305b261ecSmrg/**********************
335405b261ecSmrg * CloseDownClient
335505b261ecSmrg *
335605b261ecSmrg *  Client can either mark his resources destroy or retain.  If retained and
335705b261ecSmrg *  then killed again, the client is really destroyed.
335805b261ecSmrg *********************/
335905b261ecSmrg
336005b261ecSmrgchar dispatchExceptionAtReset = DE_RESET;
336105b261ecSmrg
336205b261ecSmrgvoid
336305b261ecSmrgCloseDownClient(ClientPtr client)
336405b261ecSmrg{
336505b261ecSmrg    Bool really_close_down = client->clientGone ||
3366f7df2e56Smrg        client->closeDownMode == DestroyAll;
336705b261ecSmrg
3368f7df2e56Smrg    if (!client->clientGone) {
3369f7df2e56Smrg        /* ungrab server if grabbing client dies */
3370f7df2e56Smrg        if (grabState != GrabNone && grabClient == client) {
3371f7df2e56Smrg            UngrabServer(client);
3372f7df2e56Smrg        }
3373f7df2e56Smrg        BITCLEAR(grabWaiters, client->index);
3374f7df2e56Smrg        DeleteClientFromAnySelections(client);
3375f7df2e56Smrg        ReleaseActiveGrabs(client);
3376f7df2e56Smrg        DeleteClientFontStuff(client);
3377f7df2e56Smrg        if (!really_close_down) {
3378f7df2e56Smrg            /*  This frees resources that should never be retained
3379f7df2e56Smrg             *  no matter what the close down mode is.  Actually we
3380f7df2e56Smrg             *  could do this unconditionally, but it's probably
3381f7df2e56Smrg             *  better not to traverse all the client's resources
3382f7df2e56Smrg             *  twice (once here, once a few lines down in
3383f7df2e56Smrg             *  FreeClientResources) in the common case of
3384f7df2e56Smrg             *  really_close_down == TRUE.
3385f7df2e56Smrg             */
3386f7df2e56Smrg            FreeClientNeverRetainResources(client);
3387f7df2e56Smrg            client->clientState = ClientStateRetained;
3388f7df2e56Smrg            if (ClientStateCallback) {
3389f7df2e56Smrg                NewClientInfoRec clientinfo;
3390f7df2e56Smrg
3391f7df2e56Smrg                clientinfo.client = client;
3392f7df2e56Smrg                clientinfo.prefix = (xConnSetupPrefix *) NULL;
3393f7df2e56Smrg                clientinfo.setup = (xConnSetup *) NULL;
3394f7df2e56Smrg                CallCallbacks((&ClientStateCallback), (void *) &clientinfo);
3395f7df2e56Smrg            }
3396f7df2e56Smrg        }
3397f7df2e56Smrg        client->clientGone = TRUE;      /* so events aren't sent to client */
3398f7df2e56Smrg        if (ClientIsAsleep(client))
3399f7df2e56Smrg            ClientSignal(client);
3400f7df2e56Smrg        ProcessWorkQueueZombies();
3401f7df2e56Smrg        CloseDownConnection(client);
3402f7df2e56Smrg
3403f7df2e56Smrg        /* If the client made it to the Running stage, nClients has
3404f7df2e56Smrg         * been incremented on its behalf, so we need to decrement it
3405f7df2e56Smrg         * now.  If it hasn't gotten to Running, nClients has *not*
3406f7df2e56Smrg         * been incremented, so *don't* decrement it.
3407f7df2e56Smrg         */
3408f7df2e56Smrg        if (client->clientState != ClientStateInitial) {
3409f7df2e56Smrg            --nClients;
3410f7df2e56Smrg        }
3411f7df2e56Smrg    }
3412f7df2e56Smrg
3413f7df2e56Smrg    if (really_close_down) {
3414f7df2e56Smrg        if (client->clientState == ClientStateRunning && nClients == 0)
3415f7df2e56Smrg            dispatchException |= dispatchExceptionAtReset;
3416f7df2e56Smrg
3417f7df2e56Smrg        client->clientState = ClientStateGone;
3418f7df2e56Smrg        if (ClientStateCallback) {
3419f7df2e56Smrg            NewClientInfoRec clientinfo;
3420f7df2e56Smrg
3421f7df2e56Smrg            clientinfo.client = client;
3422f7df2e56Smrg            clientinfo.prefix = (xConnSetupPrefix *) NULL;
3423f7df2e56Smrg            clientinfo.setup = (xConnSetup *) NULL;
3424f7df2e56Smrg            CallCallbacks((&ClientStateCallback), (void *) &clientinfo);
3425f7df2e56Smrg        }
3426f7df2e56Smrg        TouchListenerGone(client->clientAsMask);
3427f7df2e56Smrg        FreeClientResources(client);
3428f7df2e56Smrg        /* Disable client ID tracking. This must be done after
3429f7df2e56Smrg         * ClientStateCallback. */
3430f7df2e56Smrg        ReleaseClientIds(client);
343105b261ecSmrg#ifdef XSERVER_DTRACE
3432f7df2e56Smrg        XSERVER_CLIENT_DISCONNECT(client->index);
3433f7df2e56Smrg#endif
3434f7df2e56Smrg        if (client->index < nextFreeClientID)
3435f7df2e56Smrg            nextFreeClientID = client->index;
3436f7df2e56Smrg        clients[client->index] = NullClient;
3437f7df2e56Smrg        SmartLastClient = NullClient;
3438f7df2e56Smrg        dixFreeObjectWithPrivates(client, PRIVATE_CLIENT);
343905b261ecSmrg
3440f7df2e56Smrg        while (!clients[currentMaxClients - 1])
3441f7df2e56Smrg            currentMaxClients--;
344205b261ecSmrg    }
344305b261ecSmrg}
344405b261ecSmrg
344505b261ecSmrgstatic void
344605b261ecSmrgKillAllClients(void)
344705b261ecSmrg{
344805b261ecSmrg    int i;
3449f7df2e56Smrg
3450f7df2e56Smrg    for (i = 1; i < currentMaxClients; i++)
345105b261ecSmrg        if (clients[i]) {
345205b261ecSmrg            /* Make sure Retained clients are released. */
345305b261ecSmrg            clients[i]->closeDownMode = DestroyAll;
3454f7df2e56Smrg            CloseDownClient(clients[i]);
345505b261ecSmrg        }
345605b261ecSmrg}
345705b261ecSmrg
3458f7df2e56Smrgvoid
3459f7df2e56SmrgInitClient(ClientPtr client, int i, void *ospriv)
346005b261ecSmrg{
346105b261ecSmrg    client->index = i;
3462f7df2e56Smrg    client->clientAsMask = ((Mask) i) << CLIENTOFFSET;
34634642e01fSmrg    client->closeDownMode = i ? DestroyAll : RetainPermanent;
346405b261ecSmrg    client->requestVector = InitialVector;
346505b261ecSmrg    client->osPrivate = ospriv;
3466f7df2e56Smrg    QueryMinMaxKeyCodes(&client->minKC, &client->maxKC);
346705b261ecSmrg    client->smart_start_tick = SmartScheduleTime;
346805b261ecSmrg    client->smart_stop_tick = SmartScheduleTime;
3469f7df2e56Smrg    client->clientIds = NULL;
347005b261ecSmrg}
347105b261ecSmrg
347205b261ecSmrg/************************
347305b261ecSmrg * int NextAvailableClient(ospriv)
347405b261ecSmrg *
347505b261ecSmrg * OS dependent portion can't assign client id's because of CloseDownModes.
347605b261ecSmrg * Returns NULL if there are no free clients.
347705b261ecSmrg *************************/
347805b261ecSmrg
3479f7df2e56SmrgClientPtr
3480f7df2e56SmrgNextAvailableClient(void *ospriv)
348105b261ecSmrg{
348205b261ecSmrg    int i;
348305b261ecSmrg    ClientPtr client;
348405b261ecSmrg    xReq data;
348505b261ecSmrg
348605b261ecSmrg    i = nextFreeClientID;
3487f7df2e56Smrg    if (i == LimitClients)
3488f7df2e56Smrg        return (ClientPtr) NULL;
3489f7df2e56Smrg    clients[i] = client =
3490f7df2e56Smrg        dixAllocateObjectWithPrivates(ClientRec, PRIVATE_CLIENT);
349105b261ecSmrg    if (!client)
3492f7df2e56Smrg        return (ClientPtr) NULL;
349305b261ecSmrg    InitClient(client, i, ospriv);
3494f7df2e56Smrg    if (!InitClientResources(client)) {
3495f7df2e56Smrg        dixFreeObjectWithPrivates(client, PRIVATE_CLIENT);
3496f7df2e56Smrg        return (ClientPtr) NULL;
349705b261ecSmrg    }
349805b261ecSmrg    data.reqType = 1;
34996747b715Smrg    data.length = bytes_to_int32(sz_xReq + sz_xConnClientPrefix);
3500f7df2e56Smrg    if (!InsertFakeRequest(client, (char *) &data, sz_xReq)) {
3501f7df2e56Smrg        FreeClientResources(client);
3502f7df2e56Smrg        dixFreeObjectWithPrivates(client, PRIVATE_CLIENT);
3503f7df2e56Smrg        return (ClientPtr) NULL;
350405b261ecSmrg    }
350505b261ecSmrg    if (i == currentMaxClients)
3506f7df2e56Smrg        currentMaxClients++;
3507f7df2e56Smrg    while ((nextFreeClientID < LimitClients) && clients[nextFreeClientID])
3508f7df2e56Smrg        nextFreeClientID++;
3509f7df2e56Smrg
3510f7df2e56Smrg    /* Enable client ID tracking. This must be done before
3511f7df2e56Smrg     * ClientStateCallback. */
3512f7df2e56Smrg    ReserveClientIds(client);
3513f7df2e56Smrg
3514f7df2e56Smrg    if (ClientStateCallback) {
3515f7df2e56Smrg        NewClientInfoRec clientinfo;
351605b261ecSmrg
3517f7df2e56Smrg        clientinfo.client = client;
3518f7df2e56Smrg        clientinfo.prefix = (xConnSetupPrefix *) NULL;
351905b261ecSmrg        clientinfo.setup = (xConnSetup *) NULL;
3520f7df2e56Smrg        CallCallbacks((&ClientStateCallback), (void *) &clientinfo);
3521f7df2e56Smrg    }
35226747b715Smrg    return client;
352305b261ecSmrg}
352405b261ecSmrg
352505b261ecSmrgint
352605b261ecSmrgProcInitialConnection(ClientPtr client)
352705b261ecSmrg{
352805b261ecSmrg    REQUEST(xReq);
352905b261ecSmrg    xConnClientPrefix *prefix;
353005b261ecSmrg    int whichbyte = 1;
3531f7df2e56Smrg    char order;
353205b261ecSmrg
3533f7df2e56Smrg    prefix = (xConnClientPrefix *) ((char *)stuff + sz_xReq);
3534f7df2e56Smrg    order = prefix->byteOrder;
3535f7df2e56Smrg    if (order != 'l' && order != 'B' && order != 'r' && order != 'R')
35366747b715Smrg	return client->noClientException = -1;
3537f7df2e56Smrg    if (((*(char *) &whichbyte) && (order == 'B' || order == 'R')) ||
3538f7df2e56Smrg	(!(*(char *) &whichbyte) && (order == 'l' || order == 'r'))) {
353905b261ecSmrg	client->swapped = TRUE;
354005b261ecSmrg	SwapConnClientPrefix(prefix);
354105b261ecSmrg    }
354205b261ecSmrg    stuff->reqType = 2;
35436747b715Smrg    stuff->length += bytes_to_int32(prefix->nbytesAuthProto) +
3544f7df2e56Smrg        bytes_to_int32(prefix->nbytesAuthString);
3545f7df2e56Smrg    if (client->swapped) {
3546f7df2e56Smrg        swaps(&stuff->length);
3547f7df2e56Smrg    }
3548f7df2e56Smrg    if (order == 'r' || order == 'R') {
3549f7df2e56Smrg	client->local = FALSE;
355005b261ecSmrg    }
355105b261ecSmrg    ResetCurrentRequest(client);
35526747b715Smrg    return Success;
355305b261ecSmrg}
355405b261ecSmrg
35554642e01fSmrgstatic int
3556f7df2e56SmrgSendConnSetup(ClientPtr client, const char *reason)
355705b261ecSmrg{
355805b261ecSmrg    xWindowRoot *root;
355905b261ecSmrg    int i;
356005b261ecSmrg    int numScreens;
3561f7df2e56Smrg    char *lConnectionInfo;
3562f7df2e56Smrg    xConnSetupPrefix *lconnSetupPrefix;
356305b261ecSmrg
3564f7df2e56Smrg    if (reason) {
3565f7df2e56Smrg        xConnSetupPrefix csp;
3566f7df2e56Smrg
3567f7df2e56Smrg        csp.success = xFalse;
3568f7df2e56Smrg        csp.lengthReason = strlen(reason);
3569f7df2e56Smrg        csp.length = bytes_to_int32(csp.lengthReason);
3570f7df2e56Smrg        csp.majorVersion = X_PROTOCOL;
3571f7df2e56Smrg        csp.minorVersion = X_PROTOCOL_REVISION;
3572f7df2e56Smrg        if (client->swapped)
3573f7df2e56Smrg            WriteSConnSetupPrefix(client, &csp);
3574f7df2e56Smrg        else
3575f7df2e56Smrg            WriteToClient(client, sz_xConnSetupPrefix, &csp);
3576f7df2e56Smrg        WriteToClient(client, (int) csp.lengthReason, reason);
3577f7df2e56Smrg        return client->noClientException = -1;
357805b261ecSmrg    }
357905b261ecSmrg
358005b261ecSmrg    numScreens = screenInfo.numScreens;
358105b261ecSmrg    lConnectionInfo = ConnectionInfo;
358205b261ecSmrg    lconnSetupPrefix = &connSetupPrefix;
358305b261ecSmrg
358405b261ecSmrg    /* We're about to start speaking X protocol back to the client by
358505b261ecSmrg     * sending the connection setup info.  This means the authorization
358605b261ecSmrg     * step is complete, and we can count the client as an
358705b261ecSmrg     * authorized one.
358805b261ecSmrg     */
358905b261ecSmrg    nClients++;
359005b261ecSmrg
359105b261ecSmrg    client->requestVector = client->swapped ? SwappedProcVector : ProcVector;
359205b261ecSmrg    client->sequence = 0;
3593f7df2e56Smrg    ((xConnSetup *) lConnectionInfo)->ridBase = client->clientAsMask;
3594f7df2e56Smrg    ((xConnSetup *) lConnectionInfo)->ridMask = RESOURCE_ID_MASK;
359505b261ecSmrg#ifdef MATCH_CLIENT_ENDIAN
3596f7df2e56Smrg    ((xConnSetup *) lConnectionInfo)->imageByteOrder = ClientOrder(client);
3597f7df2e56Smrg    ((xConnSetup *) lConnectionInfo)->bitmapBitOrder = ClientOrder(client);
359805b261ecSmrg#endif
359905b261ecSmrg    /* fill in the "currentInputMask" */
3600f7df2e56Smrg    root = (xWindowRoot *) (lConnectionInfo + connBlockScreenStart);
360105b261ecSmrg#ifdef PANORAMIX
360205b261ecSmrg    if (noPanoramiXExtension)
3603f7df2e56Smrg        numScreens = screenInfo.numScreens;
3604f7df2e56Smrg    else
3605f7df2e56Smrg        numScreens = ((xConnSetup *) ConnectionInfo)->numRoots;
360605b261ecSmrg#endif
360705b261ecSmrg
3608f7df2e56Smrg    for (i = 0; i < numScreens; i++) {
3609f7df2e56Smrg        unsigned int j;
3610f7df2e56Smrg        xDepth *pDepth;
3611f7df2e56Smrg        WindowPtr pRoot = screenInfo.screens[i]->root;
361205b261ecSmrg
36136747b715Smrg        root->currentInputMask = pRoot->eventMask | wOtherEventMasks(pRoot);
3614f7df2e56Smrg        pDepth = (xDepth *) (root + 1);
3615f7df2e56Smrg        for (j = 0; j < root->nDepths; j++) {
3616f7df2e56Smrg            pDepth = (xDepth *) (((char *) (pDepth + 1)) +
3617f7df2e56Smrg                                 pDepth->nVisuals * sizeof(xVisualType));
3618f7df2e56Smrg        }
3619f7df2e56Smrg        root = (xWindowRoot *) pDepth;
362005b261ecSmrg    }
362105b261ecSmrg
3622f7df2e56Smrg    if (client->swapped) {
3623f7df2e56Smrg        WriteSConnSetupPrefix(client, lconnSetupPrefix);
3624f7df2e56Smrg        WriteSConnectionInfo(client,
3625f7df2e56Smrg                             (unsigned long) (lconnSetupPrefix->length << 2),
3626f7df2e56Smrg                             lConnectionInfo);
362705b261ecSmrg    }
3628f7df2e56Smrg    else {
3629f7df2e56Smrg        WriteToClient(client, sizeof(xConnSetupPrefix), lconnSetupPrefix);
3630f7df2e56Smrg        WriteToClient(client, (int) (lconnSetupPrefix->length << 2),
3631f7df2e56Smrg		      lConnectionInfo);
363205b261ecSmrg    }
363305b261ecSmrg    client->clientState = ClientStateRunning;
3634f7df2e56Smrg    if (ClientStateCallback) {
3635f7df2e56Smrg        NewClientInfoRec clientinfo;
363605b261ecSmrg
3637f7df2e56Smrg        clientinfo.client = client;
3638f7df2e56Smrg        clientinfo.prefix = lconnSetupPrefix;
3639f7df2e56Smrg        clientinfo.setup = (xConnSetup *) lConnectionInfo;
3640f7df2e56Smrg        CallCallbacks((&ClientStateCallback), (void *) &clientinfo);
3641f7df2e56Smrg    }
36426747b715Smrg    return Success;
364305b261ecSmrg}
364405b261ecSmrg
364505b261ecSmrgint
364605b261ecSmrgProcEstablishConnection(ClientPtr client)
364705b261ecSmrg{
3648f7df2e56Smrg    const char *reason;
3649f7df2e56Smrg    char *auth_proto, *auth_string;
365005b261ecSmrg    xConnClientPrefix *prefix;
3651f7df2e56Smrg
365205b261ecSmrg    REQUEST(xReq);
365305b261ecSmrg
3654f7df2e56Smrg    prefix = (xConnClientPrefix *) ((char *) stuff + sz_xReq);
3655f7df2e56Smrg    auth_proto = (char *) prefix + sz_xConnClientPrefix;
36566747b715Smrg    auth_string = auth_proto + pad_to_int32(prefix->nbytesAuthProto);
365705b261ecSmrg    if ((prefix->majorVersion != X_PROTOCOL) ||
3658f7df2e56Smrg        (prefix->minorVersion != X_PROTOCOL_REVISION))
3659f7df2e56Smrg        reason = "Protocol version mismatch";
366005b261ecSmrg    else
3661f7df2e56Smrg        reason = ClientAuthorized(client,
3662f7df2e56Smrg                                  (unsigned short) prefix->nbytesAuthProto,
3663f7df2e56Smrg                                  auth_proto,
3664f7df2e56Smrg                                  (unsigned short) prefix->nbytesAuthString,
3665f7df2e56Smrg                                  auth_string);
3666f7df2e56Smrg
3667f7df2e56Smrg    return (SendConnSetup(client, reason));
366805b261ecSmrg}
366905b261ecSmrg
36706747b715Smrgvoid
3671f7df2e56SmrgSendErrorToClient(ClientPtr client, unsigned majorCode, unsigned minorCode,
367205b261ecSmrg                  XID resId, int errorCode)
367305b261ecSmrg{
3674f7df2e56Smrg    xError rep = {
3675f7df2e56Smrg        .type = X_Error,
3676f7df2e56Smrg        .errorCode = errorCode,
3677f7df2e56Smrg        .resourceID = resId,
3678f7df2e56Smrg        .minorCode = minorCode,
3679f7df2e56Smrg        .majorCode = majorCode
3680f7df2e56Smrg    };
368105b261ecSmrg
3682f7df2e56Smrg    WriteEventsToClient(client, 1, (xEvent *) &rep);
368305b261ecSmrg}
368405b261ecSmrg
368505b261ecSmrgvoid
368605b261ecSmrgMarkClientException(ClientPtr client)
368705b261ecSmrg{
368805b261ecSmrg    client->noClientException = -1;
368905b261ecSmrg}
36906747b715Smrg
36916747b715Smrg/*
36926747b715Smrg * This array encodes the answer to the question "what is the log base 2
36936747b715Smrg * of the number of pixels that fit in a scanline pad unit?"
36946747b715Smrg * Note that ~0 is an invalid entry (mostly for the benefit of the reader).
36956747b715Smrg */
36966747b715Smrgstatic int answer[6][4] = {
3697f7df2e56Smrg    /* pad   pad   pad     pad */
3698f7df2e56Smrg    /*  8     16    32    64 */
3699f7df2e56Smrg
3700f7df2e56Smrg    {3, 4, 5, 6},               /* 1 bit per pixel */
3701f7df2e56Smrg    {1, 2, 3, 4},               /* 4 bits per pixel */
3702f7df2e56Smrg    {0, 1, 2, 3},               /* 8 bits per pixel */
3703f7df2e56Smrg    {~0, 0, 1, 2},              /* 16 bits per pixel */
3704f7df2e56Smrg    {~0, ~0, 0, 1},             /* 24 bits per pixel */
3705f7df2e56Smrg    {~0, ~0, 0, 1}              /* 32 bits per pixel */
37066747b715Smrg};
37076747b715Smrg
37086747b715Smrg/*
37096747b715Smrg * This array gives the answer to the question "what is the first index for
37106747b715Smrg * the answer array above given the number of bits per pixel?"
37116747b715Smrg * Note that ~0 is an invalid entry (mostly for the benefit of the reader).
37126747b715Smrg */
3713f7df2e56Smrgstatic int indexForBitsPerPixel[33] = {
3714f7df2e56Smrg    ~0, 0, ~0, ~0,              /* 1 bit per pixel */
3715f7df2e56Smrg    1, ~0, ~0, ~0,              /* 4 bits per pixel */
3716f7df2e56Smrg    2, ~0, ~0, ~0,              /* 8 bits per pixel */
3717f7df2e56Smrg    ~0, ~0, ~0, ~0,
3718f7df2e56Smrg    3, ~0, ~0, ~0,              /* 16 bits per pixel */
3719f7df2e56Smrg    ~0, ~0, ~0, ~0,
3720f7df2e56Smrg    4, ~0, ~0, ~0,              /* 24 bits per pixel */
3721f7df2e56Smrg    ~0, ~0, ~0, ~0,
3722f7df2e56Smrg    5                           /* 32 bits per pixel */
37236747b715Smrg};
37246747b715Smrg
37256747b715Smrg/*
37266747b715Smrg * This array gives the bytesperPixel value for cases where the number
37276747b715Smrg * of bits per pixel is a multiple of 8 but not a power of 2.
37286747b715Smrg */
3729f7df2e56Smrgstatic int answerBytesPerPixel[33] = {
3730f7df2e56Smrg    ~0, 0, ~0, ~0,              /* 1 bit per pixel */
3731f7df2e56Smrg    0, ~0, ~0, ~0,              /* 4 bits per pixel */
3732f7df2e56Smrg    0, ~0, ~0, ~0,              /* 8 bits per pixel */
3733f7df2e56Smrg    ~0, ~0, ~0, ~0,
3734f7df2e56Smrg    0, ~0, ~0, ~0,              /* 16 bits per pixel */
3735f7df2e56Smrg    ~0, ~0, ~0, ~0,
3736f7df2e56Smrg    3, ~0, ~0, ~0,              /* 24 bits per pixel */
3737f7df2e56Smrg    ~0, ~0, ~0, ~0,
3738f7df2e56Smrg    0                           /* 32 bits per pixel */
37396747b715Smrg};
37406747b715Smrg
37416747b715Smrg/*
37426747b715Smrg * This array gives the answer to the question "what is the second index for
37436747b715Smrg * the answer array above given the number of bits per scanline pad unit?"
37446747b715Smrg * Note that ~0 is an invalid entry (mostly for the benefit of the reader).
37456747b715Smrg */
3746f7df2e56Smrgstatic int indexForScanlinePad[65] = {
3747f7df2e56Smrg    ~0, ~0, ~0, ~0,
3748f7df2e56Smrg    ~0, ~0, ~0, ~0,
3749f7df2e56Smrg    0, ~0, ~0, ~0,              /* 8 bits per scanline pad unit */
3750f7df2e56Smrg    ~0, ~0, ~0, ~0,
3751f7df2e56Smrg    1, ~0, ~0, ~0,              /* 16 bits per scanline pad unit */
3752f7df2e56Smrg    ~0, ~0, ~0, ~0,
3753f7df2e56Smrg    ~0, ~0, ~0, ~0,
3754f7df2e56Smrg    ~0, ~0, ~0, ~0,
3755f7df2e56Smrg    2, ~0, ~0, ~0,              /* 32 bits per scanline pad unit */
3756f7df2e56Smrg    ~0, ~0, ~0, ~0,
3757f7df2e56Smrg    ~0, ~0, ~0, ~0,
3758f7df2e56Smrg    ~0, ~0, ~0, ~0,
3759f7df2e56Smrg    ~0, ~0, ~0, ~0,
3760f7df2e56Smrg    ~0, ~0, ~0, ~0,
3761f7df2e56Smrg    ~0, ~0, ~0, ~0,
3762f7df2e56Smrg    ~0, ~0, ~0, ~0,
3763f7df2e56Smrg    3                           /* 64 bits per scanline pad unit */
37646747b715Smrg};
37656747b715Smrg
37666747b715Smrg/*
37676747b715Smrg	grow the array of screenRecs if necessary.
37686747b715Smrg	call the device-supplied initialization procedure
37696747b715Smrgwith its screen number, a pointer to its ScreenRec, argc, and argv.
37706747b715Smrg	return the number of successfully installed screens.
37716747b715Smrg
37726747b715Smrg*/
37736747b715Smrg
3774f7df2e56Smrgstatic int init_screen(ScreenPtr pScreen, int i, Bool gpu)
37756747b715Smrg{
37766747b715Smrg    int scanlinepad, format, depth, bitsPerPixel, j, k;
37776747b715Smrg
3778f7df2e56Smrg    dixInitScreenSpecificPrivates(pScreen);
37796747b715Smrg
37806747b715Smrg    if (!dixAllocatePrivates(&pScreen->devPrivates, PRIVATE_SCREEN)) {
3781f7df2e56Smrg        return -1;
37826747b715Smrg    }
37836747b715Smrg    pScreen->myNum = i;
3784f7df2e56Smrg    if (gpu) {
3785f7df2e56Smrg        pScreen->myNum += GPU_SCREEN_OFFSET;
3786f7df2e56Smrg        pScreen->isGPU = TRUE;
3787f7df2e56Smrg    }
3788f7df2e56Smrg    pScreen->totalPixmapSize = 0;       /* computed in CreateScratchPixmapForScreen */
3789f7df2e56Smrg    pScreen->ClipNotify = 0;    /* for R4 ddx compatibility */
37906747b715Smrg    pScreen->CreateScreenResources = 0;
37916747b715Smrg
3792f7df2e56Smrg    xorg_list_init(&pScreen->pixmap_dirty_list);
3793f7df2e56Smrg    xorg_list_init(&pScreen->unattached_list);
3794f7df2e56Smrg    xorg_list_init(&pScreen->output_slave_list);
3795f7df2e56Smrg    xorg_list_init(&pScreen->offload_slave_list);
3796f7df2e56Smrg
37976747b715Smrg    /*
37986747b715Smrg     * This loop gets run once for every Screen that gets added,
37996747b715Smrg     * but thats ok.  If the ddx layer initializes the formats
38006747b715Smrg     * one at a time calling AddScreen() after each, then each
38016747b715Smrg     * iteration will make it a little more accurate.  Worst case
38026747b715Smrg     * we do this loop N * numPixmapFormats where N is # of screens.
38036747b715Smrg     * Anyway, this must be called after InitOutput and before the
38046747b715Smrg     * screen init routine is called.
38056747b715Smrg     */
3806f7df2e56Smrg    for (format = 0; format < screenInfo.numPixmapFormats; format++) {
3807f7df2e56Smrg        depth = screenInfo.formats[format].depth;
3808f7df2e56Smrg        bitsPerPixel = screenInfo.formats[format].bitsPerPixel;
3809f7df2e56Smrg        scanlinepad = screenInfo.formats[format].scanlinePad;
3810f7df2e56Smrg        j = indexForBitsPerPixel[bitsPerPixel];
3811f7df2e56Smrg        k = indexForScanlinePad[scanlinepad];
3812f7df2e56Smrg        PixmapWidthPaddingInfo[depth].padPixelsLog2 = answer[j][k];
3813f7df2e56Smrg        PixmapWidthPaddingInfo[depth].padRoundUp =
3814f7df2e56Smrg            (scanlinepad / bitsPerPixel) - 1;
3815f7df2e56Smrg        j = indexForBitsPerPixel[8];    /* bits per byte */
3816f7df2e56Smrg        PixmapWidthPaddingInfo[depth].padBytesLog2 = answer[j][k];
3817f7df2e56Smrg        PixmapWidthPaddingInfo[depth].bitsPerPixel = bitsPerPixel;
3818f7df2e56Smrg        if (answerBytesPerPixel[bitsPerPixel]) {
3819f7df2e56Smrg            PixmapWidthPaddingInfo[depth].notPower2 = 1;
3820f7df2e56Smrg            PixmapWidthPaddingInfo[depth].bytesPerPixel =
3821f7df2e56Smrg                answerBytesPerPixel[bitsPerPixel];
3822f7df2e56Smrg        }
3823f7df2e56Smrg        else {
3824f7df2e56Smrg            PixmapWidthPaddingInfo[depth].notPower2 = 0;
3825f7df2e56Smrg        }
38266747b715Smrg    }
3827f7df2e56Smrg    return 0;
3828f7df2e56Smrg}
3829f7df2e56Smrg
3830f7df2e56Smrgint
3831f7df2e56SmrgAddScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ ,
3832f7df2e56Smrg                           int /*argc */ ,
3833f7df2e56Smrg                           char **      /*argv */
3834f7df2e56Smrg          ), int argc, char **argv)
3835f7df2e56Smrg{
3836f7df2e56Smrg
3837f7df2e56Smrg    int i;
3838f7df2e56Smrg    ScreenPtr pScreen;
3839f7df2e56Smrg    Bool ret;
3840f7df2e56Smrg
3841f7df2e56Smrg    i = screenInfo.numScreens;
3842f7df2e56Smrg    if (i == MAXSCREENS)
3843f7df2e56Smrg        return -1;
3844f7df2e56Smrg
3845f7df2e56Smrg    pScreen = (ScreenPtr) calloc(1, sizeof(ScreenRec));
3846f7df2e56Smrg    if (!pScreen)
3847f7df2e56Smrg        return -1;
38486747b715Smrg
3849f7df2e56Smrg    ret = init_screen(pScreen, i, FALSE);
3850f7df2e56Smrg    if (ret != 0) {
3851f7df2e56Smrg        free(pScreen);
3852f7df2e56Smrg        return ret;
3853f7df2e56Smrg    }
38546747b715Smrg    /* This is where screen specific stuff gets initialized.  Load the
38556747b715Smrg       screen structure, call the hardware, whatever.
38566747b715Smrg       This is also where the default colormap should be allocated and
38576747b715Smrg       also pixel values for blackPixel, whitePixel, and the cursor
38586747b715Smrg       Note that InitScreen is NOT allowed to modify argc, argv, or
38596747b715Smrg       any of the strings pointed to by argv.  They may be passed to
38606747b715Smrg       multiple screens.
3861f7df2e56Smrg     */
38626747b715Smrg    screenInfo.screens[i] = pScreen;
38636747b715Smrg    screenInfo.numScreens++;
3864f7df2e56Smrg    if (!(*pfnInit) (pScreen, argc, argv)) {
3865f7df2e56Smrg        dixFreeScreenSpecificPrivates(pScreen);
3866f7df2e56Smrg        dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN);
3867f7df2e56Smrg        free(pScreen);
3868f7df2e56Smrg        screenInfo.numScreens--;
3869f7df2e56Smrg        return -1;
38706747b715Smrg    }
38716747b715Smrg
3872f7df2e56Smrg    update_desktop_dimensions();
3873f7df2e56Smrg
3874f7df2e56Smrg    dixRegisterScreenPrivateKey(&cursorScreenDevPriv, pScreen, PRIVATE_CURSOR,
3875f7df2e56Smrg                                0);
38766747b715Smrg
38776747b715Smrg    return i;
38786747b715Smrg}
3879f7df2e56Smrg
3880f7df2e56Smrgint
3881f7df2e56SmrgAddGPUScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ ,
3882f7df2e56Smrg                              int /*argc */ ,
3883f7df2e56Smrg                              char **      /*argv */
3884f7df2e56Smrg                              ),
3885f7df2e56Smrg             int argc, char **argv)
3886f7df2e56Smrg{
3887f7df2e56Smrg    int i;
3888f7df2e56Smrg    ScreenPtr pScreen;
3889f7df2e56Smrg    Bool ret;
3890f7df2e56Smrg
3891f7df2e56Smrg    i = screenInfo.numGPUScreens;
3892f7df2e56Smrg    if (i == MAXGPUSCREENS)
3893f7df2e56Smrg        return -1;
3894f7df2e56Smrg
3895f7df2e56Smrg    pScreen = (ScreenPtr) calloc(1, sizeof(ScreenRec));
3896f7df2e56Smrg    if (!pScreen)
3897f7df2e56Smrg        return -1;
3898f7df2e56Smrg
3899f7df2e56Smrg    ret = init_screen(pScreen, i, TRUE);
3900f7df2e56Smrg    if (ret != 0) {
3901f7df2e56Smrg        free(pScreen);
3902f7df2e56Smrg        return ret;
3903f7df2e56Smrg    }
3904f7df2e56Smrg
3905f7df2e56Smrg    /* This is where screen specific stuff gets initialized.  Load the
3906f7df2e56Smrg       screen structure, call the hardware, whatever.
3907f7df2e56Smrg       This is also where the default colormap should be allocated and
3908f7df2e56Smrg       also pixel values for blackPixel, whitePixel, and the cursor
3909f7df2e56Smrg       Note that InitScreen is NOT allowed to modify argc, argv, or
3910f7df2e56Smrg       any of the strings pointed to by argv.  They may be passed to
3911f7df2e56Smrg       multiple screens.
3912f7df2e56Smrg     */
3913f7df2e56Smrg    screenInfo.gpuscreens[i] = pScreen;
3914f7df2e56Smrg    screenInfo.numGPUScreens++;
3915f7df2e56Smrg    if (!(*pfnInit) (pScreen, argc, argv)) {
3916f7df2e56Smrg        dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN);
3917f7df2e56Smrg        free(pScreen);
3918f7df2e56Smrg        screenInfo.numGPUScreens--;
3919f7df2e56Smrg        return -1;
3920f7df2e56Smrg    }
3921f7df2e56Smrg
3922f7df2e56Smrg    update_desktop_dimensions();
3923f7df2e56Smrg
3924f7df2e56Smrg    return i;
3925f7df2e56Smrg}
3926f7df2e56Smrg
3927f7df2e56Smrgvoid
3928f7df2e56SmrgRemoveGPUScreen(ScreenPtr pScreen)
3929f7df2e56Smrg{
3930f7df2e56Smrg    int idx, j;
3931f7df2e56Smrg    if (!pScreen->isGPU)
3932f7df2e56Smrg        return;
3933f7df2e56Smrg
3934f7df2e56Smrg    idx = pScreen->myNum - GPU_SCREEN_OFFSET;
3935f7df2e56Smrg    for (j = idx; j < screenInfo.numGPUScreens - 1; j++) {
3936f7df2e56Smrg        screenInfo.gpuscreens[j] = screenInfo.gpuscreens[j + 1];
3937f7df2e56Smrg        screenInfo.gpuscreens[j]->myNum = j + GPU_SCREEN_OFFSET;
3938f7df2e56Smrg    }
3939f7df2e56Smrg    screenInfo.numGPUScreens--;
3940f7df2e56Smrg
3941f7df2e56Smrg    /* this gets freed later in the resource list, but without
3942f7df2e56Smrg     * the screen existing it causes crashes - so remove it here */
3943f7df2e56Smrg    if (pScreen->defColormap)
3944f7df2e56Smrg        FreeResource(pScreen->defColormap, RT_COLORMAP);
3945f7df2e56Smrg    free(pScreen);
3946f7df2e56Smrg
3947f7df2e56Smrg}
3948f7df2e56Smrg
3949f7df2e56Smrgvoid
3950f7df2e56SmrgAttachUnboundGPU(ScreenPtr pScreen, ScreenPtr new)
3951f7df2e56Smrg{
3952f7df2e56Smrg    assert(new->isGPU);
3953f7df2e56Smrg    assert(!new->current_master);
3954f7df2e56Smrg    xorg_list_add(&new->unattached_head, &pScreen->unattached_list);
3955f7df2e56Smrg    new->current_master = pScreen;
3956f7df2e56Smrg}
3957f7df2e56Smrg
3958f7df2e56Smrgvoid
3959f7df2e56SmrgDetachUnboundGPU(ScreenPtr slave)
3960f7df2e56Smrg{
3961f7df2e56Smrg    assert(slave->isGPU);
3962f7df2e56Smrg    xorg_list_del(&slave->unattached_head);
3963f7df2e56Smrg    slave->current_master = NULL;
3964f7df2e56Smrg}
3965f7df2e56Smrg
3966f7df2e56Smrgvoid
3967f7df2e56SmrgAttachOutputGPU(ScreenPtr pScreen, ScreenPtr new)
3968f7df2e56Smrg{
3969f7df2e56Smrg    assert(new->isGPU);
3970f7df2e56Smrg    xorg_list_add(&new->output_head, &pScreen->output_slave_list);
3971f7df2e56Smrg    new->current_master = pScreen;
3972f7df2e56Smrg}
3973f7df2e56Smrg
3974f7df2e56Smrgvoid
3975f7df2e56SmrgDetachOutputGPU(ScreenPtr slave)
3976f7df2e56Smrg{
3977f7df2e56Smrg    assert(slave->isGPU);
3978f7df2e56Smrg    xorg_list_del(&slave->output_head);
3979f7df2e56Smrg    slave->current_master = NULL;
3980f7df2e56Smrg}
3981f7df2e56Smrg
3982f7df2e56Smrgvoid
3983f7df2e56SmrgAttachOffloadGPU(ScreenPtr pScreen, ScreenPtr new)
3984f7df2e56Smrg{
3985f7df2e56Smrg    assert(new->isGPU);
3986f7df2e56Smrg    xorg_list_add(&new->offload_head, &pScreen->offload_slave_list);
3987f7df2e56Smrg    new->current_master = pScreen;
3988f7df2e56Smrg}
3989f7df2e56Smrg
3990f7df2e56Smrgvoid
3991f7df2e56SmrgDetachOffloadGPU(ScreenPtr slave)
3992f7df2e56Smrg{
3993f7df2e56Smrg    assert(slave->isGPU);
3994f7df2e56Smrg    xorg_list_del(&slave->offload_head);
3995f7df2e56Smrg    slave->current_master = NULL;
3996f7df2e56Smrg}
3997f7df2e56Smrg
3998