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>
1117e31ba66Smrg#include <X11/fonts/libxfont2.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"
130f7df2e56Smrg#include "client.h"
1315a112b11Smrg#include "xfixesint.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;
1515a112b11Smrgstatic ClientPtr currentClient; /* Client for the request currently being dispatched */
152f7df2e56Smrg
15305b261ecSmrg#define GrabNone 0
15405b261ecSmrg#define GrabActive 1
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;
1685a112b11SmrgOsTimerPtr dispatchExceptionTimer;
16905b261ecSmrg
17005b261ecSmrg/* dispatchException & isItTimeToYield must be declared volatile since they
17105b261ecSmrg * are modified by signal handlers - otherwise optimizer may assume it doesn't
17205b261ecSmrg * need to actually check value in memory when used and may miss changes from
17305b261ecSmrg * signal handlers.
17405b261ecSmrg */
1756747b715Smrgvolatile char dispatchException = 0;
1766747b715Smrgvolatile char isItTimeToYield;
17705b261ecSmrg
17805b261ecSmrg#define SAME_SCREENS(a, b) (\
17905b261ecSmrg    (a.pScreen == b.pScreen))
18005b261ecSmrg
1815a112b11SmrgClientPtr
1825a112b11SmrgGetCurrentClient(void)
1835a112b11Smrg{
1845a112b11Smrg    if (in_input_thread()) {
1855a112b11Smrg        static Bool warned;
1865a112b11Smrg
1875a112b11Smrg        if (!warned) {
1885a112b11Smrg            ErrorF("[dix] Error GetCurrentClient called from input-thread\n");
1895a112b11Smrg            warned = TRUE;
1905a112b11Smrg        }
1915a112b11Smrg
1925a112b11Smrg        return NULL;
1935a112b11Smrg    }
1945a112b11Smrg
1955a112b11Smrg    return currentClient;
1965a112b11Smrg}
1975a112b11Smrg
1984642e01fSmrgvoid
19905b261ecSmrgSetInputCheck(HWEventQueuePtr c0, HWEventQueuePtr c1)
20005b261ecSmrg{
20105b261ecSmrg    checkForInput[0] = c0;
20205b261ecSmrg    checkForInput[1] = c1;
20305b261ecSmrg}
20405b261ecSmrg
2056747b715Smrgvoid
20605b261ecSmrgUpdateCurrentTime(void)
20705b261ecSmrg{
20805b261ecSmrg    TimeStamp systime;
20905b261ecSmrg
21005b261ecSmrg    /* To avoid time running backwards, we must call GetTimeInMillis before
21105b261ecSmrg     * calling ProcessInputEvents.
21205b261ecSmrg     */
21305b261ecSmrg    systime.months = currentTime.months;
21405b261ecSmrg    systime.milliseconds = GetTimeInMillis();
21505b261ecSmrg    if (systime.milliseconds < currentTime.milliseconds)
216f7df2e56Smrg        systime.months++;
2177e31ba66Smrg    if (InputCheckPending())
218f7df2e56Smrg        ProcessInputEvents();
21905b261ecSmrg    if (CompareTimeStamps(systime, currentTime) == LATER)
220f7df2e56Smrg        currentTime = systime;
22105b261ecSmrg}
22205b261ecSmrg
22305b261ecSmrg/* Like UpdateCurrentTime, but can't call ProcessInputEvents */
2246747b715Smrgvoid
22505b261ecSmrgUpdateCurrentTimeIf(void)
22605b261ecSmrg{
22705b261ecSmrg    TimeStamp systime;
22805b261ecSmrg
22905b261ecSmrg    systime.months = currentTime.months;
23005b261ecSmrg    systime.milliseconds = GetTimeInMillis();
23105b261ecSmrg    if (systime.milliseconds < currentTime.milliseconds)
232f7df2e56Smrg        systime.months++;
233f7df2e56Smrg    if (CompareTimeStamps(systime, currentTime) == LATER)
234f7df2e56Smrg        currentTime = systime;
23505b261ecSmrg}
23605b261ecSmrg
23705b261ecSmrg#undef SMART_DEBUG
23805b261ecSmrg
239f7df2e56Smrg/* in milliseconds */
240f7df2e56Smrg#define SMART_SCHEDULE_DEFAULT_INTERVAL	5
241f7df2e56Smrg#define SMART_SCHEDULE_MAX_SLICE	15
24205b261ecSmrg
2437e31ba66Smrg#ifdef HAVE_SETITIMER
2447e31ba66SmrgBool SmartScheduleSignalEnable = TRUE;
245f7df2e56Smrg#endif
2467e31ba66Smrg
2476747b715Smrglong SmartScheduleSlice = SMART_SCHEDULE_DEFAULT_INTERVAL;
2486747b715Smrglong SmartScheduleInterval = SMART_SCHEDULE_DEFAULT_INTERVAL;
2496747b715Smrglong SmartScheduleMaxSlice = SMART_SCHEDULE_MAX_SLICE;
2506747b715Smrglong SmartScheduleTime;
2516747b715Smrgint SmartScheduleLatencyLimited = 0;
252f7df2e56Smrgstatic ClientPtr SmartLastClient;
253f7df2e56Smrgstatic int SmartLastIndex[SMART_MAX_PRIORITY - SMART_MIN_PRIORITY + 1];
25405b261ecSmrg
25505b261ecSmrg#ifdef SMART_DEBUG
256f7df2e56Smrglong SmartLastPrint;
25705b261ecSmrg#endif
25805b261ecSmrg
259f7df2e56Smrgvoid Dispatch(void);
26005b261ecSmrg
2617e31ba66Smrgstatic struct xorg_list ready_clients;
2627e31ba66Smrgstatic struct xorg_list saved_ready_clients;
2637e31ba66Smrgstruct xorg_list output_pending_clients;
2647e31ba66Smrg
2657e31ba66Smrgstatic void
2667e31ba66Smrginit_client_ready(void)
26705b261ecSmrg{
2687e31ba66Smrg    xorg_list_init(&ready_clients);
2697e31ba66Smrg    xorg_list_init(&saved_ready_clients);
2707e31ba66Smrg    xorg_list_init(&output_pending_clients);
2717e31ba66Smrg}
2727e31ba66Smrg
2737e31ba66SmrgBool
2747e31ba66Smrgclients_are_ready(void)
2757e31ba66Smrg{
2767e31ba66Smrg    return !xorg_list_is_empty(&ready_clients);
2777e31ba66Smrg}
2787e31ba66Smrg
2797e31ba66Smrg/* Client has requests queued or data on the network */
2807e31ba66Smrgvoid
2817e31ba66Smrgmark_client_ready(ClientPtr client)
2827e31ba66Smrg{
2837e31ba66Smrg    if (xorg_list_is_empty(&client->ready))
2847e31ba66Smrg        xorg_list_append(&client->ready, &ready_clients);
2857e31ba66Smrg}
2867e31ba66Smrg
2877e31ba66Smrg/*
2887e31ba66Smrg * Client has requests queued or data on the network, but awaits a
2897e31ba66Smrg * server grab release
2907e31ba66Smrg */
2917e31ba66Smrgvoid mark_client_saved_ready(ClientPtr client)
2927e31ba66Smrg{
2937e31ba66Smrg    if (xorg_list_is_empty(&client->ready))
2947e31ba66Smrg        xorg_list_append(&client->ready, &saved_ready_clients);
2957e31ba66Smrg}
2967e31ba66Smrg
2977e31ba66Smrg/* Client has no requests queued and no data on network */
2987e31ba66Smrgvoid
2997e31ba66Smrgmark_client_not_ready(ClientPtr client)
3007e31ba66Smrg{
3017e31ba66Smrg    xorg_list_del(&client->ready);
3027e31ba66Smrg}
3037e31ba66Smrg
3047e31ba66Smrgstatic void
3057e31ba66Smrgmark_client_grab(ClientPtr grab)
3067e31ba66Smrg{
3077e31ba66Smrg    ClientPtr   client, tmp;
3087e31ba66Smrg
3097e31ba66Smrg    xorg_list_for_each_entry_safe(client, tmp, &ready_clients, ready) {
3107e31ba66Smrg        if (client != grab) {
3117e31ba66Smrg            xorg_list_del(&client->ready);
3127e31ba66Smrg            xorg_list_append(&client->ready, &saved_ready_clients);
3137e31ba66Smrg        }
3147e31ba66Smrg    }
3157e31ba66Smrg}
3167e31ba66Smrg
3177e31ba66Smrgstatic void
3187e31ba66Smrgmark_client_ungrab(void)
3197e31ba66Smrg{
3207e31ba66Smrg    ClientPtr   client, tmp;
3217e31ba66Smrg
3227e31ba66Smrg    xorg_list_for_each_entry_safe(client, tmp, &saved_ready_clients, ready) {
3237e31ba66Smrg        xorg_list_del(&client->ready);
3247e31ba66Smrg        xorg_list_append(&client->ready, &ready_clients);
3257e31ba66Smrg    }
3267e31ba66Smrg}
3277e31ba66Smrg
3287e31ba66Smrgstatic ClientPtr
3297e31ba66SmrgSmartScheduleClient(void)
3307e31ba66Smrg{
3317e31ba66Smrg    ClientPtr pClient, best = NULL;
332f7df2e56Smrg    int bestRobin, robin;
333f7df2e56Smrg    long now = SmartScheduleTime;
334f7df2e56Smrg    long idle;
3357e31ba66Smrg    int nready = 0;
33605b261ecSmrg
33705b261ecSmrg    bestRobin = 0;
33805b261ecSmrg    idle = 2 * SmartScheduleSlice;
3397e31ba66Smrg
3407e31ba66Smrg    xorg_list_for_each_entry(pClient, &ready_clients, ready) {
3417e31ba66Smrg        nready++;
3427e31ba66Smrg
343f7df2e56Smrg        /* Praise clients which haven't run in a while */
344f7df2e56Smrg        if ((now - pClient->smart_stop_tick) >= idle) {
345f7df2e56Smrg            if (pClient->smart_priority < 0)
346f7df2e56Smrg                pClient->smart_priority++;
347f7df2e56Smrg        }
348f7df2e56Smrg
349f7df2e56Smrg        /* check priority to select best client */
350f7df2e56Smrg        robin =
351f7df2e56Smrg            (pClient->index -
352f7df2e56Smrg             SmartLastIndex[pClient->smart_priority -
353f7df2e56Smrg                            SMART_MIN_PRIORITY]) & 0xff;
3547e31ba66Smrg
3557e31ba66Smrg        /* pick the best client */
3567e31ba66Smrg        if (!best ||
3577e31ba66Smrg            pClient->priority > best->priority ||
3587e31ba66Smrg            (pClient->priority == best->priority &&
3597e31ba66Smrg             (pClient->smart_priority > best->smart_priority ||
3607e31ba66Smrg              (pClient->smart_priority == best->smart_priority && robin > bestRobin))))
3617e31ba66Smrg        {
3627e31ba66Smrg            best = pClient;
363f7df2e56Smrg            bestRobin = robin;
364f7df2e56Smrg        }
36505b261ecSmrg#ifdef SMART_DEBUG
366f7df2e56Smrg        if ((now - SmartLastPrint) >= 5000)
3677e31ba66Smrg            fprintf(stderr, " %2d: %3d", pClient->index, pClient->smart_priority);
36805b261ecSmrg#endif
36905b261ecSmrg    }
37005b261ecSmrg#ifdef SMART_DEBUG
371f7df2e56Smrg    if ((now - SmartLastPrint) >= 5000) {
3727e31ba66Smrg        fprintf(stderr, " use %2d\n", best->index);
373f7df2e56Smrg        SmartLastPrint = now;
37405b261ecSmrg    }
37505b261ecSmrg#endif
3767e31ba66Smrg    SmartLastIndex[best->smart_priority - SMART_MIN_PRIORITY] = best->index;
37705b261ecSmrg    /*
37805b261ecSmrg     * Set current client pointer
37905b261ecSmrg     */
3807e31ba66Smrg    if (SmartLastClient != best) {
3817e31ba66Smrg        best->smart_start_tick = now;
3827e31ba66Smrg        SmartLastClient = best;
38305b261ecSmrg    }
38405b261ecSmrg    /*
38505b261ecSmrg     * Adjust slice
38605b261ecSmrg     */
387f7df2e56Smrg    if (nready == 1 && SmartScheduleLatencyLimited == 0) {
388f7df2e56Smrg        /*
389f7df2e56Smrg         * If it's been a long time since another client
390f7df2e56Smrg         * has run, bump the slice up to get maximal
391f7df2e56Smrg         * performance from a single client
392f7df2e56Smrg         */
3937e31ba66Smrg        if ((now - best->smart_start_tick) > 1000 &&
394f7df2e56Smrg            SmartScheduleSlice < SmartScheduleMaxSlice) {
395f7df2e56Smrg            SmartScheduleSlice += SmartScheduleInterval;
396f7df2e56Smrg        }
39705b261ecSmrg    }
398f7df2e56Smrg    else {
399f7df2e56Smrg        SmartScheduleSlice = SmartScheduleInterval;
40005b261ecSmrg    }
40105b261ecSmrg    return best;
40205b261ecSmrg}
40305b261ecSmrg
4045a112b11Smrgstatic CARD32
4055a112b11SmrgDispatchExceptionCallback(OsTimerPtr timer, CARD32 time, void *arg)
4065a112b11Smrg{
4075a112b11Smrg    dispatchException |= dispatchExceptionAtReset;
4085a112b11Smrg
4095a112b11Smrg    /* Don't re-arm the timer */
4105a112b11Smrg    return 0;
4115a112b11Smrg}
4125a112b11Smrg
4135a112b11Smrgstatic void
4145a112b11SmrgCancelDispatchExceptionTimer(void)
4155a112b11Smrg{
4165a112b11Smrg    TimerFree(dispatchExceptionTimer);
4175a112b11Smrg    dispatchExceptionTimer = NULL;
4185a112b11Smrg}
4195a112b11Smrg
4205a112b11Smrgstatic void
4215a112b11SmrgSetDispatchExceptionTimer(void)
4225a112b11Smrg{
4235a112b11Smrg    /* The timer delay is only for terminate, not reset */
4245a112b11Smrg    if (!(dispatchExceptionAtReset & DE_TERMINATE)) {
4255a112b11Smrg        dispatchException |= dispatchExceptionAtReset;
4265a112b11Smrg        return;
4275a112b11Smrg    }
4285a112b11Smrg
4295a112b11Smrg    CancelDispatchExceptionTimer();
4305a112b11Smrg
4315a112b11Smrg    if (terminateDelay == 0)
4325a112b11Smrg        dispatchException |= dispatchExceptionAtReset;
4335a112b11Smrg    else
4345a112b11Smrg        dispatchExceptionTimer = TimerSet(dispatchExceptionTimer,
4355a112b11Smrg                                          0, terminateDelay * 1000 /* msec */,
4365a112b11Smrg                                          &DispatchExceptionCallback,
4375a112b11Smrg                                          NULL);
4385a112b11Smrg}
4395a112b11Smrg
4405a112b11Smrgstatic Bool
4415a112b11SmrgShouldDisconnectRemainingClients(void)
4425a112b11Smrg{
4435a112b11Smrg    int i;
4445a112b11Smrg
4455a112b11Smrg    for (i = 1; i < currentMaxClients; i++) {
4465a112b11Smrg        if (clients[i]) {
4475a112b11Smrg            if (!XFixesShouldDisconnectClient(clients[i]))
4485a112b11Smrg                return FALSE;
4495a112b11Smrg        }
4505a112b11Smrg    }
4515a112b11Smrg
4525a112b11Smrg    /* All remaining clients can be safely ignored */
4535a112b11Smrg    return TRUE;
4545a112b11Smrg}
4555a112b11Smrg
456b1d344b3Smrgvoid
457b1d344b3SmrgEnableLimitedSchedulingLatency(void)
458b1d344b3Smrg{
459b1d344b3Smrg    ++SmartScheduleLatencyLimited;
460b1d344b3Smrg    SmartScheduleSlice = SmartScheduleInterval;
461b1d344b3Smrg}
462b1d344b3Smrg
463b1d344b3Smrgvoid
464b1d344b3SmrgDisableLimitedSchedulingLatency(void)
465b1d344b3Smrg{
466b1d344b3Smrg    --SmartScheduleLatencyLimited;
467b1d344b3Smrg
468b1d344b3Smrg    /* protect against bugs */
469b1d344b3Smrg    if (SmartScheduleLatencyLimited < 0)
470f7df2e56Smrg        SmartScheduleLatencyLimited = 0;
471b1d344b3Smrg}
472b1d344b3Smrg
47305b261ecSmrgvoid
47405b261ecSmrgDispatch(void)
47505b261ecSmrg{
476f7df2e56Smrg    int result;
477f7df2e56Smrg    ClientPtr client;
478f7df2e56Smrg    long start_tick;
47905b261ecSmrg
48005b261ecSmrg    nextFreeClientID = 1;
48105b261ecSmrg    nClients = 0;
48205b261ecSmrg
483b1d344b3Smrg    SmartScheduleSlice = SmartScheduleInterval;
4847e31ba66Smrg    init_client_ready();
4857e31ba66Smrg
486f7df2e56Smrg    while (!dispatchException) {
4877e31ba66Smrg        if (InputCheckPending()) {
488f7df2e56Smrg            ProcessInputEvents();
489f7df2e56Smrg            FlushIfCriticalOutputPending();
490f7df2e56Smrg        }
491f7df2e56Smrg
4927e31ba66Smrg        if (!WaitForSomething(clients_are_ready()))
4937e31ba66Smrg            continue;
494f7df2e56Smrg
495f7df2e56Smrg       /*****************
496f7df2e56Smrg	*  Handle events in round robin fashion, doing input between
497f7df2e56Smrg	*  each round
49805b261ecSmrg	*****************/
49905b261ecSmrg
5007e31ba66Smrg        if (!dispatchException && clients_are_ready()) {
5017e31ba66Smrg            client = SmartScheduleClient();
5027e31ba66Smrg
503f7df2e56Smrg            isItTimeToYield = FALSE;
504f7df2e56Smrg
505f7df2e56Smrg            start_tick = SmartScheduleTime;
506f7df2e56Smrg            while (!isItTimeToYield) {
5077e31ba66Smrg                if (InputCheckPending())
508f7df2e56Smrg                    ProcessInputEvents();
509f7df2e56Smrg
510f7df2e56Smrg                FlushIfCriticalOutputPending();
5117e31ba66Smrg                if ((SmartScheduleTime - start_tick) >= SmartScheduleSlice)
5127e31ba66Smrg                {
513f7df2e56Smrg                    /* Penalize clients which consume ticks */
514f7df2e56Smrg                    if (client->smart_priority > SMART_MIN_PRIORITY)
515f7df2e56Smrg                        client->smart_priority--;
516f7df2e56Smrg                    break;
517f7df2e56Smrg                }
518f7df2e56Smrg
5197e31ba66Smrg                /* now, finally, deal with client requests */
520f7df2e56Smrg                result = ReadRequestFromClient(client);
5212f76b07dSmrg                if (result == 0)
5222f76b07dSmrg                    break;
5232f76b07dSmrg                else if (result == -1) {
5242f76b07dSmrg                    CloseDownClient(client);
525f7df2e56Smrg                    break;
526f7df2e56Smrg                }
527f7df2e56Smrg
528f7df2e56Smrg                client->sequence++;
529f7df2e56Smrg                client->majorOp = ((xReq *) client->requestBuffer)->reqType;
530f7df2e56Smrg                client->minorOp = 0;
531f7df2e56Smrg                if (client->majorOp >= EXTENSION_BASE) {
532f7df2e56Smrg                    ExtensionEntry *ext = GetExtensionEntry(client->majorOp);
533f7df2e56Smrg
534f7df2e56Smrg                    if (ext)
535f7df2e56Smrg                        client->minorOp = ext->MinorOpcode(client);
536f7df2e56Smrg                }
53705b261ecSmrg#ifdef XSERVER_DTRACE
538f7df2e56Smrg                if (XSERVER_REQUEST_START_ENABLED())
539f7df2e56Smrg                    XSERVER_REQUEST_START(LookupMajorName(client->majorOp),
540f7df2e56Smrg                                          client->majorOp,
541f7df2e56Smrg                                          ((xReq *) client->requestBuffer)->length,
542f7df2e56Smrg                                          client->index,
543f7df2e56Smrg                                          client->requestBuffer);
54405b261ecSmrg#endif
5452f76b07dSmrg                if (result < 0 || result > (maxBigRequestSize << 2))
546f7df2e56Smrg                    result = BadLength;
547f7df2e56Smrg                else {
548f7df2e56Smrg                    result = XaceHookDispatch(client, client->majorOp);
5495a112b11Smrg                    if (result == Success) {
5505a112b11Smrg                        currentClient = client;
551f7df2e56Smrg                        result =
552f7df2e56Smrg                            (*client->requestVector[client->majorOp]) (client);
5535a112b11Smrg                        currentClient = NULL;
5545a112b11Smrg                    }
555f7df2e56Smrg                }
5567e31ba66Smrg                if (!SmartScheduleSignalEnable)
5577e31ba66Smrg                    SmartScheduleTime = GetTimeInMillis();
5587e31ba66Smrg
55905b261ecSmrg#ifdef XSERVER_DTRACE
560f7df2e56Smrg                if (XSERVER_REQUEST_DONE_ENABLED())
561f7df2e56Smrg                    XSERVER_REQUEST_DONE(LookupMajorName(client->majorOp),
562f7df2e56Smrg                                         client->majorOp, client->sequence,
563f7df2e56Smrg                                         client->index, result);
56405b261ecSmrg#endif
56505b261ecSmrg
566f7df2e56Smrg                if (client->noClientException != Success) {
567f7df2e56Smrg                    CloseDownClient(client);
568f7df2e56Smrg                    break;
569f7df2e56Smrg                }
570f7df2e56Smrg                else if (result != Success) {
571f7df2e56Smrg                    SendErrorToClient(client, client->majorOp,
572f7df2e56Smrg                                      client->minorOp,
573f7df2e56Smrg                                      client->errorValue, result);
574f7df2e56Smrg                    break;
575f7df2e56Smrg                }
576f7df2e56Smrg            }
577f7df2e56Smrg            FlushAllOutput();
5787e31ba66Smrg            if (client == SmartLastClient)
579f7df2e56Smrg                client->smart_stop_tick = SmartScheduleTime;
580f7df2e56Smrg        }
581f7df2e56Smrg        dispatchException &= ~DE_PRIORITYCHANGE;
58205b261ecSmrg    }
58305b261ecSmrg#if defined(DDXBEFORERESET)
584f7df2e56Smrg    ddxBeforeReset();
58505b261ecSmrg#endif
58605b261ecSmrg    KillAllClients();
58705b261ecSmrg    dispatchException &= ~DE_RESET;
588b1d344b3Smrg    SmartScheduleLatencyLimited = 0;
589f7df2e56Smrg    ResetOsBuffers();
59005b261ecSmrg}
59105b261ecSmrg
592f7df2e56Smrgstatic int VendorRelease = VENDOR_RELEASE;
5936747b715Smrg
5946747b715Smrgvoid
5956747b715SmrgSetVendorRelease(int release)
5966747b715Smrg{
5976747b715Smrg    VendorRelease = release;
5986747b715Smrg}
5996747b715Smrg
6006747b715SmrgBool
6016747b715SmrgCreateConnectionBlock(void)
6026747b715Smrg{
6036747b715Smrg    xConnSetup setup;
6046747b715Smrg    xWindowRoot root;
605f7df2e56Smrg    xDepth depth;
6066747b715Smrg    xVisualType visual;
6076747b715Smrg    xPixmapFormat format;
6086747b715Smrg    unsigned long vid;
609f7df2e56Smrg    int i, j, k, lenofblock, sizesofar = 0;
6106747b715Smrg    char *pBuf;
6115a112b11Smrg    const char VendorString[] = VENDOR_NAME;
6126747b715Smrg
6136747b715Smrg    memset(&setup, 0, sizeof(xConnSetup));
6146747b715Smrg    /* Leave off the ridBase and ridMask, these must be sent with
6156747b715Smrg       connection */
6166747b715Smrg
6176747b715Smrg    setup.release = VendorRelease;
6186747b715Smrg    /*
6196747b715Smrg     * per-server image and bitmap parameters are defined in Xmd.h
6206747b715Smrg     */
6216747b715Smrg    setup.imageByteOrder = screenInfo.imageByteOrder;
6226747b715Smrg
6236747b715Smrg    setup.bitmapScanlineUnit = screenInfo.bitmapScanlineUnit;
6246747b715Smrg    setup.bitmapScanlinePad = screenInfo.bitmapScanlinePad;
6256747b715Smrg
6266747b715Smrg    setup.bitmapBitOrder = screenInfo.bitmapBitOrder;
6276747b715Smrg    setup.motionBufferSize = NumMotionEvents();
6286747b715Smrg    setup.numRoots = screenInfo.numScreens;
6296747b715Smrg    setup.nbytesVendor = strlen(VendorString);
6306747b715Smrg    setup.numFormats = screenInfo.numPixmapFormats;
6316747b715Smrg    setup.maxRequestSize = MAX_REQUEST_SIZE;
6326747b715Smrg    QueryMinMaxKeyCodes(&setup.minKeyCode, &setup.maxKeyCode);
6336747b715Smrg
6346747b715Smrg    lenofblock = sizeof(xConnSetup) +
635f7df2e56Smrg        pad_to_int32(setup.nbytesVendor) +
636f7df2e56Smrg        (setup.numFormats * sizeof(xPixmapFormat)) +
637f7df2e56Smrg        (setup.numRoots * sizeof(xWindowRoot));
6386747b715Smrg    ConnectionInfo = malloc(lenofblock);
6396747b715Smrg    if (!ConnectionInfo)
640f7df2e56Smrg        return FALSE;
6416747b715Smrg
642f7df2e56Smrg    memmove(ConnectionInfo, (char *) &setup, sizeof(xConnSetup));
6436747b715Smrg    sizesofar = sizeof(xConnSetup);
6446747b715Smrg    pBuf = ConnectionInfo + sizeof(xConnSetup);
6456747b715Smrg
646f7df2e56Smrg    memmove(pBuf, VendorString, (int) setup.nbytesVendor);
6476747b715Smrg    sizesofar += setup.nbytesVendor;
6486747b715Smrg    pBuf += setup.nbytesVendor;
649f7df2e56Smrg    i = padding_for_int32(setup.nbytesVendor);
6506747b715Smrg    sizesofar += i;
6516747b715Smrg    while (--i >= 0)
652f7df2e56Smrg        *pBuf++ = 0;
6536747b715Smrg
6546747b715Smrg    memset(&format, 0, sizeof(xPixmapFormat));
655f7df2e56Smrg    for (i = 0; i < screenInfo.numPixmapFormats; i++) {
656f7df2e56Smrg        format.depth = screenInfo.formats[i].depth;
657f7df2e56Smrg        format.bitsPerPixel = screenInfo.formats[i].bitsPerPixel;
658f7df2e56Smrg        format.scanLinePad = screenInfo.formats[i].scanlinePad;
659f7df2e56Smrg        memmove(pBuf, (char *) &format, sizeof(xPixmapFormat));
660f7df2e56Smrg        pBuf += sizeof(xPixmapFormat);
661f7df2e56Smrg        sizesofar += sizeof(xPixmapFormat);
6626747b715Smrg    }
6636747b715Smrg
6646747b715Smrg    connBlockScreenStart = sizesofar;
6656747b715Smrg    memset(&depth, 0, sizeof(xDepth));
6666747b715Smrg    memset(&visual, 0, sizeof(xVisualType));
667f7df2e56Smrg    for (i = 0; i < screenInfo.numScreens; i++) {
668f7df2e56Smrg        ScreenPtr pScreen;
669f7df2e56Smrg        DepthPtr pDepth;
670f7df2e56Smrg        VisualPtr pVisual;
671f7df2e56Smrg
672f7df2e56Smrg        pScreen = screenInfo.screens[i];
673f7df2e56Smrg        root.windowId = pScreen->root->drawable.id;
674f7df2e56Smrg        root.defaultColormap = pScreen->defColormap;
675f7df2e56Smrg        root.whitePixel = pScreen->whitePixel;
676f7df2e56Smrg        root.blackPixel = pScreen->blackPixel;
677f7df2e56Smrg        root.currentInputMask = 0;      /* filled in when sent */
678f7df2e56Smrg        root.pixWidth = pScreen->width;
679f7df2e56Smrg        root.pixHeight = pScreen->height;
680f7df2e56Smrg        root.mmWidth = pScreen->mmWidth;
681f7df2e56Smrg        root.mmHeight = pScreen->mmHeight;
682f7df2e56Smrg        root.minInstalledMaps = pScreen->minInstalledCmaps;
683f7df2e56Smrg        root.maxInstalledMaps = pScreen->maxInstalledCmaps;
684f7df2e56Smrg        root.rootVisualID = pScreen->rootVisual;
685f7df2e56Smrg        root.backingStore = pScreen->backingStoreSupport;
686f7df2e56Smrg        root.saveUnders = FALSE;
687f7df2e56Smrg        root.rootDepth = pScreen->rootDepth;
688f7df2e56Smrg        root.nDepths = pScreen->numDepths;
689f7df2e56Smrg        memmove(pBuf, (char *) &root, sizeof(xWindowRoot));
690f7df2e56Smrg        sizesofar += sizeof(xWindowRoot);
691f7df2e56Smrg        pBuf += sizeof(xWindowRoot);
692f7df2e56Smrg
693f7df2e56Smrg        pDepth = pScreen->allowedDepths;
694f7df2e56Smrg        for (j = 0; j < pScreen->numDepths; j++, pDepth++) {
695f7df2e56Smrg            lenofblock += sizeof(xDepth) +
696f7df2e56Smrg                (pDepth->numVids * sizeof(xVisualType));
697f7df2e56Smrg            pBuf = (char *) realloc(ConnectionInfo, lenofblock);
698f7df2e56Smrg            if (!pBuf) {
699f7df2e56Smrg                free(ConnectionInfo);
700f7df2e56Smrg                return FALSE;
701f7df2e56Smrg            }
702f7df2e56Smrg            ConnectionInfo = pBuf;
703f7df2e56Smrg            pBuf += sizesofar;
704f7df2e56Smrg            depth.depth = pDepth->depth;
705f7df2e56Smrg            depth.nVisuals = pDepth->numVids;
706f7df2e56Smrg            memmove(pBuf, (char *) &depth, sizeof(xDepth));
707f7df2e56Smrg            pBuf += sizeof(xDepth);
708f7df2e56Smrg            sizesofar += sizeof(xDepth);
709f7df2e56Smrg            for (k = 0; k < pDepth->numVids; k++) {
710f7df2e56Smrg                vid = pDepth->vids[k];
711f7df2e56Smrg                for (pVisual = pScreen->visuals;
712f7df2e56Smrg                     pVisual->vid != vid; pVisual++);
713f7df2e56Smrg                visual.visualID = vid;
714f7df2e56Smrg                visual.class = pVisual->class;
715f7df2e56Smrg                visual.bitsPerRGB = pVisual->bitsPerRGBValue;
716f7df2e56Smrg                visual.colormapEntries = pVisual->ColormapEntries;
717f7df2e56Smrg                visual.redMask = pVisual->redMask;
718f7df2e56Smrg                visual.greenMask = pVisual->greenMask;
719f7df2e56Smrg                visual.blueMask = pVisual->blueMask;
720f7df2e56Smrg                memmove(pBuf, (char *) &visual, sizeof(xVisualType));
721f7df2e56Smrg                pBuf += sizeof(xVisualType);
722f7df2e56Smrg                sizesofar += sizeof(xVisualType);
723f7df2e56Smrg            }
724f7df2e56Smrg        }
7256747b715Smrg    }
7266747b715Smrg    connSetupPrefix.success = xTrue;
727f7df2e56Smrg    connSetupPrefix.length = lenofblock / 4;
7286747b715Smrg    connSetupPrefix.majorVersion = X_PROTOCOL;
7296747b715Smrg    connSetupPrefix.minorVersion = X_PROTOCOL_REVISION;
7306747b715Smrg    return TRUE;
7316747b715Smrg}
7326747b715Smrg
7336747b715Smrgint
73405b261ecSmrgProcBadRequest(ClientPtr client)
73505b261ecSmrg{
7366747b715Smrg    return BadRequest;
73705b261ecSmrg}
73805b261ecSmrg
73905b261ecSmrgint
74005b261ecSmrgProcCreateWindow(ClientPtr client)
74105b261ecSmrg{
74205b261ecSmrg    WindowPtr pParent, pWin;
743f7df2e56Smrg
74405b261ecSmrg    REQUEST(xCreateWindowReq);
7454642e01fSmrg    int len, rc;
74605b261ecSmrg
74705b261ecSmrg    REQUEST_AT_LEAST_SIZE(xCreateWindowReq);
748f7df2e56Smrg
74905b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->wid, client);
7504642e01fSmrg    rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess);
75105b261ecSmrg    if (rc != Success)
75205b261ecSmrg        return rc;
7536747b715Smrg    len = client->req_len - bytes_to_int32(sizeof(xCreateWindowReq));
75405b261ecSmrg    if (Ones(stuff->mask) != len)
75505b261ecSmrg        return BadLength;
756f7df2e56Smrg    if (!stuff->width || !stuff->height) {
757f7df2e56Smrg        client->errorValue = 0;
75805b261ecSmrg        return BadValue;
75905b261ecSmrg    }
76005b261ecSmrg    pWin = CreateWindow(stuff->wid, pParent, stuff->x,
761f7df2e56Smrg                        stuff->y, stuff->width, stuff->height,
762f7df2e56Smrg                        stuff->borderWidth, stuff->class,
763f7df2e56Smrg                        stuff->mask, (XID *) &stuff[1],
764f7df2e56Smrg                        (int) stuff->depth, client, stuff->visual, &rc);
765f7df2e56Smrg    if (pWin) {
766f7df2e56Smrg        Mask mask = pWin->eventMask;
767f7df2e56Smrg
768f7df2e56Smrg        pWin->eventMask = 0;    /* subterfuge in case AddResource fails */
769f7df2e56Smrg        if (!AddResource(stuff->wid, RT_WINDOW, (void *) pWin))
770f7df2e56Smrg            return BadAlloc;
771f7df2e56Smrg        pWin->eventMask = mask;
77205b261ecSmrg    }
7736747b715Smrg    return rc;
77405b261ecSmrg}
77505b261ecSmrg
77605b261ecSmrgint
77705b261ecSmrgProcChangeWindowAttributes(ClientPtr client)
77805b261ecSmrg{
77905b261ecSmrg    WindowPtr pWin;
780f7df2e56Smrg
78105b261ecSmrg    REQUEST(xChangeWindowAttributesReq);
7826747b715Smrg    int len, rc;
7834642e01fSmrg    Mask access_mode = 0;
78405b261ecSmrg
78505b261ecSmrg    REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq);
7864642e01fSmrg    access_mode |= (stuff->valueMask & CWEventMask) ? DixReceiveAccess : 0;
7874642e01fSmrg    access_mode |= (stuff->valueMask & ~CWEventMask) ? DixSetAttrAccess : 0;
7884642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, access_mode);
78905b261ecSmrg    if (rc != Success)
79005b261ecSmrg        return rc;
7916747b715Smrg    len = client->req_len - bytes_to_int32(sizeof(xChangeWindowAttributesReq));
79205b261ecSmrg    if (len != Ones(stuff->valueMask))
79305b261ecSmrg        return BadLength;
7946747b715Smrg    return ChangeWindowAttributes(pWin,
795f7df2e56Smrg                                  stuff->valueMask, (XID *) &stuff[1], client);
79605b261ecSmrg}
79705b261ecSmrg
79805b261ecSmrgint
79905b261ecSmrgProcGetWindowAttributes(ClientPtr client)
80005b261ecSmrg{
80105b261ecSmrg    WindowPtr pWin;
802f7df2e56Smrg
80305b261ecSmrg    REQUEST(xResourceReq);
80405b261ecSmrg    xGetWindowAttributesReply wa;
80505b261ecSmrg    int rc;
80605b261ecSmrg
80705b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
8084642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
80905b261ecSmrg    if (rc != Success)
810f7df2e56Smrg        return rc;
8116747b715Smrg    memset(&wa, 0, sizeof(xGetWindowAttributesReply));
81205b261ecSmrg    GetWindowAttributes(pWin, client, &wa);
81305b261ecSmrg    WriteReplyToClient(client, sizeof(xGetWindowAttributesReply), &wa);
8146747b715Smrg    return Success;
81505b261ecSmrg}
81605b261ecSmrg
81705b261ecSmrgint
81805b261ecSmrgProcDestroyWindow(ClientPtr client)
81905b261ecSmrg{
82005b261ecSmrg    WindowPtr pWin;
821f7df2e56Smrg
82205b261ecSmrg    REQUEST(xResourceReq);
82305b261ecSmrg    int rc;
82405b261ecSmrg
82505b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
82605b261ecSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixDestroyAccess);
82705b261ecSmrg    if (rc != Success)
828f7df2e56Smrg        return rc;
8294642e01fSmrg    if (pWin->parent) {
830f7df2e56Smrg        rc = dixLookupWindow(&pWin, pWin->parent->drawable.id, client,
831f7df2e56Smrg                             DixRemoveAccess);
832f7df2e56Smrg        if (rc != Success)
833f7df2e56Smrg            return rc;
834f7df2e56Smrg        FreeResource(stuff->id, RT_NONE);
8354642e01fSmrg    }
8366747b715Smrg    return Success;
83705b261ecSmrg}
83805b261ecSmrg
83905b261ecSmrgint
84005b261ecSmrgProcDestroySubwindows(ClientPtr client)
84105b261ecSmrg{
84205b261ecSmrg    WindowPtr pWin;
843f7df2e56Smrg
84405b261ecSmrg    REQUEST(xResourceReq);
84505b261ecSmrg    int rc;
84605b261ecSmrg
84705b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
8484642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixRemoveAccess);
84905b261ecSmrg    if (rc != Success)
850f7df2e56Smrg        return rc;
85105b261ecSmrg    DestroySubwindows(pWin, client);
8526747b715Smrg    return Success;
85305b261ecSmrg}
85405b261ecSmrg
85505b261ecSmrgint
85605b261ecSmrgProcChangeSaveSet(ClientPtr client)
85705b261ecSmrg{
85805b261ecSmrg    WindowPtr pWin;
859f7df2e56Smrg
86005b261ecSmrg    REQUEST(xChangeSaveSetReq);
8616747b715Smrg    int rc;
862f7df2e56Smrg
86305b261ecSmrg    REQUEST_SIZE_MATCH(xChangeSaveSetReq);
8644642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
86505b261ecSmrg    if (rc != Success)
86605b261ecSmrg        return rc;
86705b261ecSmrg    if (client->clientAsMask == (CLIENT_BITS(pWin->drawable.id)))
86805b261ecSmrg        return BadMatch;
86905b261ecSmrg    if ((stuff->mode == SetModeInsert) || (stuff->mode == SetModeDelete))
8706747b715Smrg        return AlterSaveSetForClient(client, pWin, stuff->mode, FALSE, TRUE);
8716747b715Smrg    client->errorValue = stuff->mode;
8726747b715Smrg    return BadValue;
87305b261ecSmrg}
87405b261ecSmrg
87505b261ecSmrgint
87605b261ecSmrgProcReparentWindow(ClientPtr client)
87705b261ecSmrg{
87805b261ecSmrg    WindowPtr pWin, pParent;
879f7df2e56Smrg
88005b261ecSmrg    REQUEST(xReparentWindowReq);
8816747b715Smrg    int rc;
88205b261ecSmrg
88305b261ecSmrg    REQUEST_SIZE_MATCH(xReparentWindowReq);
8844642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
88505b261ecSmrg    if (rc != Success)
88605b261ecSmrg        return rc;
8874642e01fSmrg    rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess);
88805b261ecSmrg    if (rc != Success)
88905b261ecSmrg        return rc;
8906747b715Smrg    if (!SAME_SCREENS(pWin->drawable, pParent->drawable))
891f7df2e56Smrg        return BadMatch;
8926747b715Smrg    if ((pWin->backgroundState == ParentRelative) &&
893f7df2e56Smrg        (pParent->drawable.depth != pWin->drawable.depth))
894f7df2e56Smrg        return BadMatch;
8956747b715Smrg    if ((pWin->drawable.class != InputOnly) &&
896f7df2e56Smrg        (pParent->drawable.class == InputOnly))
897f7df2e56Smrg        return BadMatch;
8986747b715Smrg    return ReparentWindow(pWin, pParent,
899f7df2e56Smrg                          (short) stuff->x, (short) stuff->y, client);
90005b261ecSmrg}
90105b261ecSmrg
90205b261ecSmrgint
90305b261ecSmrgProcMapWindow(ClientPtr client)
90405b261ecSmrg{
90505b261ecSmrg    WindowPtr pWin;
906f7df2e56Smrg
90705b261ecSmrg    REQUEST(xResourceReq);
90805b261ecSmrg    int rc;
90905b261ecSmrg
91005b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
9114642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixShowAccess);
91205b261ecSmrg    if (rc != Success)
91305b261ecSmrg        return rc;
91405b261ecSmrg    MapWindow(pWin, client);
915f7df2e56Smrg    /* update cache to say it is mapped */
9166747b715Smrg    return Success;
91705b261ecSmrg}
91805b261ecSmrg
91905b261ecSmrgint
92005b261ecSmrgProcMapSubwindows(ClientPtr client)
92105b261ecSmrg{
92205b261ecSmrg    WindowPtr pWin;
923f7df2e56Smrg
92405b261ecSmrg    REQUEST(xResourceReq);
92505b261ecSmrg    int rc;
92605b261ecSmrg
92705b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
9284642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
92905b261ecSmrg    if (rc != Success)
93005b261ecSmrg        return rc;
93105b261ecSmrg    MapSubwindows(pWin, client);
932f7df2e56Smrg    /* update cache to say it is mapped */
9336747b715Smrg    return Success;
93405b261ecSmrg}
93505b261ecSmrg
93605b261ecSmrgint
93705b261ecSmrgProcUnmapWindow(ClientPtr client)
93805b261ecSmrg{
93905b261ecSmrg    WindowPtr pWin;
940f7df2e56Smrg
94105b261ecSmrg    REQUEST(xResourceReq);
94205b261ecSmrg    int rc;
94305b261ecSmrg
94405b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
9454642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixHideAccess);
94605b261ecSmrg    if (rc != Success)
94705b261ecSmrg        return rc;
94805b261ecSmrg    UnmapWindow(pWin, FALSE);
949f7df2e56Smrg    /* update cache to say it is mapped */
9506747b715Smrg    return Success;
95105b261ecSmrg}
95205b261ecSmrg
95305b261ecSmrgint
95405b261ecSmrgProcUnmapSubwindows(ClientPtr client)
95505b261ecSmrg{
95605b261ecSmrg    WindowPtr pWin;
957f7df2e56Smrg
95805b261ecSmrg    REQUEST(xResourceReq);
95905b261ecSmrg    int rc;
96005b261ecSmrg
96105b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
9624642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
96305b261ecSmrg    if (rc != Success)
96405b261ecSmrg        return rc;
96505b261ecSmrg    UnmapSubwindows(pWin);
9666747b715Smrg    return Success;
96705b261ecSmrg}
96805b261ecSmrg
96905b261ecSmrgint
97005b261ecSmrgProcConfigureWindow(ClientPtr client)
97105b261ecSmrg{
97205b261ecSmrg    WindowPtr pWin;
973f7df2e56Smrg
97405b261ecSmrg    REQUEST(xConfigureWindowReq);
97505b261ecSmrg    int len, rc;
97605b261ecSmrg
97705b261ecSmrg    REQUEST_AT_LEAST_SIZE(xConfigureWindowReq);
9784642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client,
979f7df2e56Smrg                         DixManageAccess | DixSetAttrAccess);
98005b261ecSmrg    if (rc != Success)
98105b261ecSmrg        return rc;
9826747b715Smrg    len = client->req_len - bytes_to_int32(sizeof(xConfigureWindowReq));
983f7df2e56Smrg    if (Ones((Mask) stuff->mask) != len)
98405b261ecSmrg        return BadLength;
985f7df2e56Smrg    return ConfigureWindow(pWin, (Mask) stuff->mask, (XID *) &stuff[1], client);
98605b261ecSmrg}
98705b261ecSmrg
98805b261ecSmrgint
98905b261ecSmrgProcCirculateWindow(ClientPtr client)
99005b261ecSmrg{
99105b261ecSmrg    WindowPtr pWin;
992f7df2e56Smrg
99305b261ecSmrg    REQUEST(xCirculateWindowReq);
99405b261ecSmrg    int rc;
99505b261ecSmrg
99605b261ecSmrg    REQUEST_SIZE_MATCH(xCirculateWindowReq);
997f7df2e56Smrg    if ((stuff->direction != RaiseLowest) && (stuff->direction != LowerHighest)) {
998f7df2e56Smrg        client->errorValue = stuff->direction;
99905b261ecSmrg        return BadValue;
100005b261ecSmrg    }
10014642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
100205b261ecSmrg    if (rc != Success)
100305b261ecSmrg        return rc;
1004f7df2e56Smrg    CirculateWindow(pWin, (int) stuff->direction, client);
10056747b715Smrg    return Success;
100605b261ecSmrg}
100705b261ecSmrg
100805b261ecSmrgstatic int
1009f7df2e56SmrgGetGeometry(ClientPtr client, xGetGeometryReply * rep)
101005b261ecSmrg{
101105b261ecSmrg    DrawablePtr pDraw;
101205b261ecSmrg    int rc;
1013f7df2e56Smrg
101405b261ecSmrg    REQUEST(xResourceReq);
101505b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
101605b261ecSmrg
10174642e01fSmrg    rc = dixLookupDrawable(&pDraw, stuff->id, client, M_ANY, DixGetAttrAccess);
101805b261ecSmrg    if (rc != Success)
1019f7df2e56Smrg        return rc;
102005b261ecSmrg
102105b261ecSmrg    rep->type = X_Reply;
102205b261ecSmrg    rep->length = 0;
102305b261ecSmrg    rep->sequenceNumber = client->sequence;
10246747b715Smrg    rep->root = pDraw->pScreen->root->drawable.id;
102505b261ecSmrg    rep->depth = pDraw->depth;
102605b261ecSmrg    rep->width = pDraw->width;
102705b261ecSmrg    rep->height = pDraw->height;
102805b261ecSmrg
1029f7df2e56Smrg    if (WindowDrawable(pDraw->type)) {
1030f7df2e56Smrg        WindowPtr pWin = (WindowPtr) pDraw;
1031f7df2e56Smrg
1032f7df2e56Smrg        rep->x = pWin->origin.x - wBorderWidth(pWin);
1033f7df2e56Smrg        rep->y = pWin->origin.y - wBorderWidth(pWin);
1034f7df2e56Smrg        rep->borderWidth = pWin->borderWidth;
103505b261ecSmrg    }
1036f7df2e56Smrg    else {                      /* DRAWABLE_PIXMAP */
1037f7df2e56Smrg
1038f7df2e56Smrg        rep->x = rep->y = rep->borderWidth = 0;
103905b261ecSmrg    }
104005b261ecSmrg
104105b261ecSmrg    return Success;
104205b261ecSmrg}
104305b261ecSmrg
104405b261ecSmrgint
104505b261ecSmrgProcGetGeometry(ClientPtr client)
104605b261ecSmrg{
1047f7df2e56Smrg    xGetGeometryReply rep = { .type = X_Reply };
104805b261ecSmrg    int status;
104905b261ecSmrg
105005b261ecSmrg    if ((status = GetGeometry(client, &rep)) != Success)
1051f7df2e56Smrg        return status;
105205b261ecSmrg
105305b261ecSmrg    WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep);
10546747b715Smrg    return Success;
105505b261ecSmrg}
105605b261ecSmrg
105705b261ecSmrgint
105805b261ecSmrgProcQueryTree(ClientPtr client)
105905b261ecSmrg{
106005b261ecSmrg    xQueryTreeReply reply;
106105b261ecSmrg    int rc, numChildren = 0;
106205b261ecSmrg    WindowPtr pChild, pWin, pHead;
1063f7df2e56Smrg    Window *childIDs = (Window *) NULL;
1064f7df2e56Smrg
106505b261ecSmrg    REQUEST(xResourceReq);
106605b261ecSmrg
106705b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
10684642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
106905b261ecSmrg    if (rc != Success)
107005b261ecSmrg        return rc;
1071f7df2e56Smrg
1072f7df2e56Smrg    reply = (xQueryTreeReply) {
1073f7df2e56Smrg        .type = X_Reply,
1074f7df2e56Smrg        .sequenceNumber = client->sequence,
1075f7df2e56Smrg        .root = pWin->drawable.pScreen->root->drawable.id,
1076f7df2e56Smrg        .parent = (pWin->parent) ? pWin->parent->drawable.id : (Window) None
1077f7df2e56Smrg    };
107805b261ecSmrg    pHead = RealChildHead(pWin);
107905b261ecSmrg    for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib)
1080f7df2e56Smrg        numChildren++;
1081f7df2e56Smrg    if (numChildren) {
1082f7df2e56Smrg        int curChild = 0;
108305b261ecSmrg
1084f7df2e56Smrg        childIDs = xallocarray(numChildren, sizeof(Window));
1085f7df2e56Smrg        if (!childIDs)
1086f7df2e56Smrg            return BadAlloc;
1087f7df2e56Smrg        for (pChild = pWin->lastChild; pChild != pHead;
1088f7df2e56Smrg             pChild = pChild->prevSib)
1089f7df2e56Smrg            childIDs[curChild++] = pChild->drawable.id;
109005b261ecSmrg    }
1091f7df2e56Smrg
109205b261ecSmrg    reply.nChildren = numChildren;
10936747b715Smrg    reply.length = bytes_to_int32(numChildren * sizeof(Window));
1094f7df2e56Smrg
109505b261ecSmrg    WriteReplyToClient(client, sizeof(xQueryTreeReply), &reply);
1096f7df2e56Smrg    if (numChildren) {
1097f7df2e56Smrg        client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
1098f7df2e56Smrg        WriteSwappedDataToClient(client, numChildren * sizeof(Window),
1099f7df2e56Smrg                                 childIDs);
1100f7df2e56Smrg        free(childIDs);
110105b261ecSmrg    }
110205b261ecSmrg
11036747b715Smrg    return Success;
110405b261ecSmrg}
110505b261ecSmrg
110605b261ecSmrgint
110705b261ecSmrgProcInternAtom(ClientPtr client)
110805b261ecSmrg{
110905b261ecSmrg    Atom atom;
111005b261ecSmrg    char *tchar;
1111f7df2e56Smrg
111205b261ecSmrg    REQUEST(xInternAtomReq);
111305b261ecSmrg
111405b261ecSmrg    REQUEST_FIXED_SIZE(xInternAtomReq, stuff->nbytes);
1115f7df2e56Smrg    if ((stuff->onlyIfExists != xTrue) && (stuff->onlyIfExists != xFalse)) {
1116f7df2e56Smrg        client->errorValue = stuff->onlyIfExists;
11176747b715Smrg        return BadValue;
111805b261ecSmrg    }
111905b261ecSmrg    tchar = (char *) &stuff[1];
112005b261ecSmrg    atom = MakeAtom(tchar, stuff->nbytes, !stuff->onlyIfExists);
1121f7df2e56Smrg    if (atom != BAD_RESOURCE) {
1122f7df2e56Smrg        xInternAtomReply reply = {
1123f7df2e56Smrg            .type = X_Reply,
1124f7df2e56Smrg            .sequenceNumber = client->sequence,
1125f7df2e56Smrg            .length = 0,
1126f7df2e56Smrg            .atom = atom
1127f7df2e56Smrg        };
1128f7df2e56Smrg        WriteReplyToClient(client, sizeof(xInternAtomReply), &reply);
1129f7df2e56Smrg        return Success;
113005b261ecSmrg    }
113105b261ecSmrg    else
1132f7df2e56Smrg        return BadAlloc;
113305b261ecSmrg}
113405b261ecSmrg
113505b261ecSmrgint
113605b261ecSmrgProcGetAtomName(ClientPtr client)
113705b261ecSmrg{
11386747b715Smrg    const char *str;
1139f7df2e56Smrg
114005b261ecSmrg    REQUEST(xResourceReq);
114105b261ecSmrg
114205b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
1143f7df2e56Smrg    if ((str = NameForAtom(stuff->id))) {
1144f7df2e56Smrg        int len = strlen(str);
1145f7df2e56Smrg        xGetAtomNameReply reply = {
1146f7df2e56Smrg            .type = X_Reply,
1147f7df2e56Smrg            .sequenceNumber = client->sequence,
1148f7df2e56Smrg            .length = bytes_to_int32(len),
1149f7df2e56Smrg            .nameLength = len
1150f7df2e56Smrg        };
1151f7df2e56Smrg
1152f7df2e56Smrg        WriteReplyToClient(client, sizeof(xGetAtomNameReply), &reply);
1153f7df2e56Smrg        WriteToClient(client, len, str);
1154f7df2e56Smrg        return Success;
115505b261ecSmrg    }
1156f7df2e56Smrg    else {
1157f7df2e56Smrg        client->errorValue = stuff->id;
1158f7df2e56Smrg        return BadAtom;
115905b261ecSmrg    }
116005b261ecSmrg}
116105b261ecSmrg
116205b261ecSmrgint
116305b261ecSmrgProcGrabServer(ClientPtr client)
116405b261ecSmrg{
11654642e01fSmrg    int rc;
1166f7df2e56Smrg
116705b261ecSmrg    REQUEST_SIZE_MATCH(xReq);
1168f7df2e56Smrg    if (grabState != GrabNone && client != grabClient) {
1169f7df2e56Smrg        ResetCurrentRequest(client);
1170f7df2e56Smrg        client->sequence--;
1171f7df2e56Smrg        BITSET(grabWaiters, client->index);
1172f7df2e56Smrg        IgnoreClient(client);
1173f7df2e56Smrg        return Success;
117405b261ecSmrg    }
11754642e01fSmrg    rc = OnlyListenToOneClient(client);
11764642e01fSmrg    if (rc != Success)
1177f7df2e56Smrg        return rc;
11787e31ba66Smrg    grabState = GrabActive;
117905b261ecSmrg    grabClient = client;
11807e31ba66Smrg    mark_client_grab(client);
118105b261ecSmrg
1182f7df2e56Smrg    if (ServerGrabCallback) {
1183f7df2e56Smrg        ServerGrabInfoRec grabinfo;
1184f7df2e56Smrg
1185f7df2e56Smrg        grabinfo.client = client;
1186f7df2e56Smrg        grabinfo.grabstate = SERVER_GRABBED;
1187f7df2e56Smrg        CallCallbacks(&ServerGrabCallback, (void *) &grabinfo);
118805b261ecSmrg    }
118905b261ecSmrg
11906747b715Smrg    return Success;
119105b261ecSmrg}
119205b261ecSmrg
119305b261ecSmrgstatic void
119405b261ecSmrgUngrabServer(ClientPtr client)
119505b261ecSmrg{
119605b261ecSmrg    int i;
119705b261ecSmrg
119805b261ecSmrg    grabState = GrabNone;
119905b261ecSmrg    ListenToAllClients();
12007e31ba66Smrg    mark_client_ungrab();
1201f7df2e56Smrg    for (i = mskcnt; --i >= 0 && !grabWaiters[i];);
1202f7df2e56Smrg    if (i >= 0) {
1203f7df2e56Smrg        i <<= 5;
1204f7df2e56Smrg        while (!GETBIT(grabWaiters, i))
1205f7df2e56Smrg            i++;
1206f7df2e56Smrg        BITCLEAR(grabWaiters, i);
1207f7df2e56Smrg        AttendClient(clients[i]);
120805b261ecSmrg    }
120905b261ecSmrg
1210f7df2e56Smrg    if (ServerGrabCallback) {
1211f7df2e56Smrg        ServerGrabInfoRec grabinfo;
1212f7df2e56Smrg
1213f7df2e56Smrg        grabinfo.client = client;
1214f7df2e56Smrg        grabinfo.grabstate = SERVER_UNGRABBED;
1215f7df2e56Smrg        CallCallbacks(&ServerGrabCallback, (void *) &grabinfo);
121605b261ecSmrg    }
121705b261ecSmrg}
121805b261ecSmrg
121905b261ecSmrgint
122005b261ecSmrgProcUngrabServer(ClientPtr client)
122105b261ecSmrg{
122205b261ecSmrg    REQUEST_SIZE_MATCH(xReq);
122305b261ecSmrg    UngrabServer(client);
12246747b715Smrg    return Success;
122505b261ecSmrg}
122605b261ecSmrg
122705b261ecSmrgint
122805b261ecSmrgProcTranslateCoords(ClientPtr client)
122905b261ecSmrg{
123005b261ecSmrg    REQUEST(xTranslateCoordsReq);
123105b261ecSmrg
123205b261ecSmrg    WindowPtr pWin, pDst;
123305b261ecSmrg    xTranslateCoordsReply rep;
123405b261ecSmrg    int rc;
123505b261ecSmrg
123605b261ecSmrg    REQUEST_SIZE_MATCH(xTranslateCoordsReq);
12374642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->srcWid, client, DixGetAttrAccess);
123805b261ecSmrg    if (rc != Success)
123905b261ecSmrg        return rc;
12404642e01fSmrg    rc = dixLookupWindow(&pDst, stuff->dstWid, client, DixGetAttrAccess);
124105b261ecSmrg    if (rc != Success)
124205b261ecSmrg        return rc;
1243f7df2e56Smrg
1244f7df2e56Smrg    rep = (xTranslateCoordsReply) {
1245f7df2e56Smrg        .type = X_Reply,
1246f7df2e56Smrg        .sequenceNumber = client->sequence,
1247f7df2e56Smrg        .length = 0
1248f7df2e56Smrg    };
1249f7df2e56Smrg    if (!SAME_SCREENS(pWin->drawable, pDst->drawable)) {
1250f7df2e56Smrg        rep.sameScreen = xFalse;
125105b261ecSmrg        rep.child = None;
1252f7df2e56Smrg        rep.dstX = rep.dstY = 0;
125305b261ecSmrg    }
1254f7df2e56Smrg    else {
1255f7df2e56Smrg        INT16 x, y;
1256f7df2e56Smrg
1257f7df2e56Smrg        rep.sameScreen = xTrue;
1258f7df2e56Smrg        rep.child = None;
1259f7df2e56Smrg        /* computing absolute coordinates -- adjust to destination later */
1260f7df2e56Smrg        x = pWin->drawable.x + stuff->srcX;
1261f7df2e56Smrg        y = pWin->drawable.y + stuff->srcY;
1262f7df2e56Smrg        pWin = pDst->firstChild;
1263f7df2e56Smrg        while (pWin) {
1264f7df2e56Smrg            BoxRec box;
1265f7df2e56Smrg
1266f7df2e56Smrg            if ((pWin->mapped) &&
1267f7df2e56Smrg                (x >= pWin->drawable.x - wBorderWidth(pWin)) &&
1268f7df2e56Smrg                (x < pWin->drawable.x + (int) pWin->drawable.width +
1269f7df2e56Smrg                 wBorderWidth(pWin)) &&
1270f7df2e56Smrg                (y >= pWin->drawable.y - wBorderWidth(pWin)) &&
1271f7df2e56Smrg                (y < pWin->drawable.y + (int) pWin->drawable.height +
1272f7df2e56Smrg                 wBorderWidth(pWin))
1273f7df2e56Smrg                /* When a window is shaped, a further check
1274f7df2e56Smrg                 * is made to see if the point is inside
1275f7df2e56Smrg                 * borderSize
1276f7df2e56Smrg                 */
1277f7df2e56Smrg                && (!wBoundingShape(pWin) ||
1278f7df2e56Smrg                    RegionContainsPoint(&pWin->borderSize, x, y, &box))
1279f7df2e56Smrg
1280f7df2e56Smrg                && (!wInputShape(pWin) ||
1281f7df2e56Smrg                    RegionContainsPoint(wInputShape(pWin),
1282f7df2e56Smrg                                        x - pWin->drawable.x,
1283f7df2e56Smrg                                        y - pWin->drawable.y, &box))
1284f7df2e56Smrg                ) {
1285f7df2e56Smrg                rep.child = pWin->drawable.id;
1286f7df2e56Smrg                pWin = (WindowPtr) NULL;
1287f7df2e56Smrg            }
1288f7df2e56Smrg            else
1289f7df2e56Smrg                pWin = pWin->nextSib;
1290f7df2e56Smrg        }
1291f7df2e56Smrg        /* adjust to destination coordinates */
1292f7df2e56Smrg        rep.dstX = x - pDst->drawable.x;
1293f7df2e56Smrg        rep.dstY = y - pDst->drawable.y;
129405b261ecSmrg    }
129505b261ecSmrg    WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep);
12966747b715Smrg    return Success;
129705b261ecSmrg}
129805b261ecSmrg
129905b261ecSmrgint
130005b261ecSmrgProcOpenFont(ClientPtr client)
130105b261ecSmrg{
1302f7df2e56Smrg    int err;
1303f7df2e56Smrg
130405b261ecSmrg    REQUEST(xOpenFontReq);
130505b261ecSmrg
130605b261ecSmrg    REQUEST_FIXED_SIZE(xOpenFontReq, stuff->nbytes);
130705b261ecSmrg    client->errorValue = stuff->fid;
130805b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->fid, client);
130905b261ecSmrg    err = OpenFont(client, stuff->fid, (Mask) 0,
1310f7df2e56Smrg                   stuff->nbytes, (char *) &stuff[1]);
1311f7df2e56Smrg    if (err == Success) {
1312f7df2e56Smrg        return Success;
131305b261ecSmrg    }
131405b261ecSmrg    else
1315f7df2e56Smrg        return err;
131605b261ecSmrg}
131705b261ecSmrg
131805b261ecSmrgint
131905b261ecSmrgProcCloseFont(ClientPtr client)
132005b261ecSmrg{
132105b261ecSmrg    FontPtr pFont;
13226747b715Smrg    int rc;
1323f7df2e56Smrg
132405b261ecSmrg    REQUEST(xResourceReq);
132505b261ecSmrg
132605b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
1327f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pFont, stuff->id, RT_FONT,
1328f7df2e56Smrg                                 client, DixDestroyAccess);
1329f7df2e56Smrg    if (rc == Success) {
133005b261ecSmrg        FreeResource(stuff->id, RT_NONE);
1331f7df2e56Smrg        return Success;
133205b261ecSmrg    }
1333f7df2e56Smrg    else {
1334f7df2e56Smrg        client->errorValue = stuff->id;
13356747b715Smrg        return rc;
133605b261ecSmrg    }
133705b261ecSmrg}
133805b261ecSmrg
133905b261ecSmrgint
134005b261ecSmrgProcQueryFont(ClientPtr client)
134105b261ecSmrg{
1342f7df2e56Smrg    xQueryFontReply *reply;
134305b261ecSmrg    FontPtr pFont;
13444642e01fSmrg    int rc;
1345f7df2e56Smrg
134605b261ecSmrg    REQUEST(xResourceReq);
134705b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
13484642e01fSmrg
13496747b715Smrg    rc = dixLookupFontable(&pFont, stuff->id, client, DixGetAttrAccess);
13504642e01fSmrg    if (rc != Success)
1351f7df2e56Smrg        return rc;
135205b261ecSmrg
135305b261ecSmrg    {
1354f7df2e56Smrg        xCharInfo *pmax = FONTINKMAX(pFont);
1355f7df2e56Smrg        xCharInfo *pmin = FONTINKMIN(pFont);
1356f7df2e56Smrg        int nprotoxcistructs;
1357f7df2e56Smrg        int rlength;
1358f7df2e56Smrg
1359f7df2e56Smrg        nprotoxcistructs = (pmax->rightSideBearing == pmin->rightSideBearing &&
1360f7df2e56Smrg                            pmax->leftSideBearing == pmin->leftSideBearing &&
1361f7df2e56Smrg                            pmax->descent == pmin->descent &&
1362f7df2e56Smrg                            pmax->ascent == pmin->ascent &&
1363f7df2e56Smrg                            pmax->characterWidth == pmin->characterWidth) ?
1364f7df2e56Smrg            0 : N2dChars(pFont);
1365f7df2e56Smrg
1366f7df2e56Smrg        rlength = sizeof(xQueryFontReply) +
1367f7df2e56Smrg            FONTINFONPROPS(FONTCHARSET(pFont)) * sizeof(xFontProp) +
1368f7df2e56Smrg            nprotoxcistructs * sizeof(xCharInfo);
1369f7df2e56Smrg        reply = calloc(1, rlength);
1370f7df2e56Smrg        if (!reply) {
1371f7df2e56Smrg            return BadAlloc;
1372f7df2e56Smrg        }
1373f7df2e56Smrg
1374f7df2e56Smrg        reply->type = X_Reply;
1375f7df2e56Smrg        reply->length = bytes_to_int32(rlength - sizeof(xGenericReply));
1376f7df2e56Smrg        reply->sequenceNumber = client->sequence;
1377f7df2e56Smrg        QueryFont(pFont, reply, nprotoxcistructs);
137805b261ecSmrg
137905b261ecSmrg        WriteReplyToClient(client, rlength, reply);
1380f7df2e56Smrg        free(reply);
1381f7df2e56Smrg        return Success;
138205b261ecSmrg    }
138305b261ecSmrg}
138405b261ecSmrg
138505b261ecSmrgint
138605b261ecSmrgProcQueryTextExtents(ClientPtr client)
138705b261ecSmrg{
138805b261ecSmrg    xQueryTextExtentsReply reply;
138905b261ecSmrg    FontPtr pFont;
139005b261ecSmrg    ExtentInfoRec info;
139105b261ecSmrg    unsigned long length;
13924642e01fSmrg    int rc;
1393f7df2e56Smrg
13944642e01fSmrg    REQUEST(xQueryTextExtentsReq);
139505b261ecSmrg    REQUEST_AT_LEAST_SIZE(xQueryTextExtentsReq);
1396f7df2e56Smrg
13976747b715Smrg    rc = dixLookupFontable(&pFont, stuff->fid, client, DixGetAttrAccess);
13984642e01fSmrg    if (rc != Success)
1399f7df2e56Smrg        return rc;
14004642e01fSmrg
14016747b715Smrg    length = client->req_len - bytes_to_int32(sizeof(xQueryTextExtentsReq));
140205b261ecSmrg    length = length << 1;
1403f7df2e56Smrg    if (stuff->oddLength) {
1404f7df2e56Smrg        if (length == 0)
1405f7df2e56Smrg            return BadLength;
140605b261ecSmrg        length--;
140705b261ecSmrg    }
14087e31ba66Smrg    if (!xfont2_query_text_extents(pFont, length, (unsigned char *) &stuff[1], &info))
1409f7df2e56Smrg        return BadAlloc;
1410f7df2e56Smrg    reply = (xQueryTextExtentsReply) {
1411f7df2e56Smrg        .type = X_Reply,
1412f7df2e56Smrg        .drawDirection = info.drawDirection,
1413f7df2e56Smrg        .sequenceNumber = client->sequence,
1414f7df2e56Smrg        .length = 0,
1415f7df2e56Smrg        .fontAscent = info.fontAscent,
1416f7df2e56Smrg        .fontDescent = info.fontDescent,
1417f7df2e56Smrg        .overallAscent = info.overallAscent,
1418f7df2e56Smrg        .overallDescent = info.overallDescent,
1419f7df2e56Smrg        .overallWidth = info.overallWidth,
1420f7df2e56Smrg        .overallLeft = info.overallLeft,
1421f7df2e56Smrg        .overallRight = info.overallRight
1422f7df2e56Smrg    };
142305b261ecSmrg    WriteReplyToClient(client, sizeof(xQueryTextExtentsReply), &reply);
14246747b715Smrg    return Success;
142505b261ecSmrg}
142605b261ecSmrg
142705b261ecSmrgint
142805b261ecSmrgProcListFonts(ClientPtr client)
142905b261ecSmrg{
143005b261ecSmrg    REQUEST(xListFontsReq);
143105b261ecSmrg
143205b261ecSmrg    REQUEST_FIXED_SIZE(xListFontsReq, stuff->nbytes);
143305b261ecSmrg
1434f7df2e56Smrg    return ListFonts(client, (unsigned char *) &stuff[1], stuff->nbytes,
1435f7df2e56Smrg                     stuff->maxNames);
143605b261ecSmrg}
143705b261ecSmrg
143805b261ecSmrgint
143905b261ecSmrgProcListFontsWithInfo(ClientPtr client)
144005b261ecSmrg{
144105b261ecSmrg    REQUEST(xListFontsWithInfoReq);
144205b261ecSmrg
144305b261ecSmrg    REQUEST_FIXED_SIZE(xListFontsWithInfoReq, stuff->nbytes);
144405b261ecSmrg
144505b261ecSmrg    return StartListFontsWithInfo(client, stuff->nbytes,
1446f7df2e56Smrg                                  (unsigned char *) &stuff[1], stuff->maxNames);
144705b261ecSmrg}
144805b261ecSmrg
144905b261ecSmrg/**
145005b261ecSmrg *
145105b261ecSmrg *  \param value must conform to DeleteType
145205b261ecSmrg */
145305b261ecSmrgint
1454f7df2e56SmrgdixDestroyPixmap(void *value, XID pid)
145505b261ecSmrg{
1456f7df2e56Smrg    PixmapPtr pPixmap = (PixmapPtr) value;
1457f7df2e56Smrg
1458f7df2e56Smrg    return (*pPixmap->drawable.pScreen->DestroyPixmap) (pPixmap);
145905b261ecSmrg}
146005b261ecSmrg
146105b261ecSmrgint
146205b261ecSmrgProcCreatePixmap(ClientPtr client)
146305b261ecSmrg{
146405b261ecSmrg    PixmapPtr pMap;
146505b261ecSmrg    DrawablePtr pDraw;
1466f7df2e56Smrg
146705b261ecSmrg    REQUEST(xCreatePixmapReq);
146805b261ecSmrg    DepthPtr pDepth;
146905b261ecSmrg    int i, rc;
147005b261ecSmrg
147105b261ecSmrg    REQUEST_SIZE_MATCH(xCreatePixmapReq);
147205b261ecSmrg    client->errorValue = stuff->pid;
147305b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->pid, client);
1474f7df2e56Smrg
147505b261ecSmrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
1476f7df2e56Smrg                           DixGetAttrAccess);
147705b261ecSmrg    if (rc != Success)
1478f7df2e56Smrg        return rc;
147905b261ecSmrg
1480f7df2e56Smrg    if (!stuff->width || !stuff->height) {
1481f7df2e56Smrg        client->errorValue = 0;
148205b261ecSmrg        return BadValue;
148305b261ecSmrg    }
1484f7df2e56Smrg    if (stuff->width > 32767 || stuff->height > 32767) {
1485f7df2e56Smrg        /* It is allowed to try and allocate a pixmap which is larger than
1486f7df2e56Smrg         * 32767 in either dimension. However, all of the framebuffer code
1487f7df2e56Smrg         * is buggy and does not reliably draw to such big pixmaps, basically
1488f7df2e56Smrg         * because the Region data structure operates with signed shorts
1489f7df2e56Smrg         * for the rectangles in it.
1490f7df2e56Smrg         *
1491f7df2e56Smrg         * Furthermore, several places in the X server computes the
1492f7df2e56Smrg         * size in bytes of the pixmap and tries to store it in an
1493f7df2e56Smrg         * integer. This integer can overflow and cause the allocated size
1494f7df2e56Smrg         * to be much smaller.
1495f7df2e56Smrg         *
1496f7df2e56Smrg         * So, such big pixmaps are rejected here with a BadAlloc
1497f7df2e56Smrg         */
1498f7df2e56Smrg        return BadAlloc;
1499f7df2e56Smrg    }
1500f7df2e56Smrg    if (stuff->depth != 1) {
150105b261ecSmrg        pDepth = pDraw->pScreen->allowedDepths;
1502f7df2e56Smrg        for (i = 0; i < pDraw->pScreen->numDepths; i++, pDepth++)
1503f7df2e56Smrg            if (pDepth->depth == stuff->depth)
1504f7df2e56Smrg                goto CreatePmap;
1505f7df2e56Smrg        client->errorValue = stuff->depth;
150605b261ecSmrg        return BadValue;
150705b261ecSmrg    }
1508f7df2e56Smrg CreatePmap:
1509f7df2e56Smrg    pMap = (PixmapPtr) (*pDraw->pScreen->CreatePixmap)
1510f7df2e56Smrg        (pDraw->pScreen, stuff->width, stuff->height, stuff->depth, 0);
1511f7df2e56Smrg    if (pMap) {
1512f7df2e56Smrg        pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
1513f7df2e56Smrg        pMap->drawable.id = stuff->pid;
1514f7df2e56Smrg        /* security creation/labeling check */
1515f7df2e56Smrg        rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, RT_PIXMAP,
1516f7df2e56Smrg                      pMap, RT_NONE, NULL, DixCreateAccess);
1517f7df2e56Smrg        if (rc != Success) {
1518f7df2e56Smrg            (*pDraw->pScreen->DestroyPixmap) (pMap);
1519f7df2e56Smrg            return rc;
1520f7df2e56Smrg        }
1521f7df2e56Smrg        if (AddResource(stuff->pid, RT_PIXMAP, (void *) pMap))
1522f7df2e56Smrg            return Success;
152305b261ecSmrg    }
15246747b715Smrg    return BadAlloc;
152505b261ecSmrg}
152605b261ecSmrg
152705b261ecSmrgint
152805b261ecSmrgProcFreePixmap(ClientPtr client)
152905b261ecSmrg{
153005b261ecSmrg    PixmapPtr pMap;
15314642e01fSmrg    int rc;
1532f7df2e56Smrg
153305b261ecSmrg    REQUEST(xResourceReq);
153405b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
15354642e01fSmrg
1536f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pMap, stuff->id, RT_PIXMAP,
1537f7df2e56Smrg                                 client, DixDestroyAccess);
1538f7df2e56Smrg    if (rc == Success) {
1539f7df2e56Smrg        FreeResource(stuff->id, RT_NONE);
1540f7df2e56Smrg        return Success;
154105b261ecSmrg    }
1542f7df2e56Smrg    else {
1543f7df2e56Smrg        client->errorValue = stuff->id;
1544f7df2e56Smrg        return rc;
154505b261ecSmrg    }
154605b261ecSmrg}
154705b261ecSmrg
154805b261ecSmrgint
154905b261ecSmrgProcCreateGC(ClientPtr client)
155005b261ecSmrg{
155105b261ecSmrg    int error, rc;
155205b261ecSmrg    GC *pGC;
155305b261ecSmrg    DrawablePtr pDraw;
155405b261ecSmrg    unsigned len;
1555f7df2e56Smrg
155605b261ecSmrg    REQUEST(xCreateGCReq);
155705b261ecSmrg
155805b261ecSmrg    REQUEST_AT_LEAST_SIZE(xCreateGCReq);
155905b261ecSmrg    client->errorValue = stuff->gc;
156005b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->gc, client);
15614642e01fSmrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
1562f7df2e56Smrg                           DixGetAttrAccess);
156305b261ecSmrg    if (rc != Success)
1564f7df2e56Smrg        return rc;
156505b261ecSmrg
1566f7df2e56Smrg    len = client->req_len - bytes_to_int32(sizeof(xCreateGCReq));
156705b261ecSmrg    if (len != Ones(stuff->mask))
156805b261ecSmrg        return BadLength;
1569f7df2e56Smrg    pGC = (GC *) CreateGC(pDraw, stuff->mask, (XID *) &stuff[1], &error,
1570f7df2e56Smrg                          stuff->gc, client);
157105b261ecSmrg    if (error != Success)
157205b261ecSmrg        return error;
1573f7df2e56Smrg    if (!AddResource(stuff->gc, RT_GC, (void *) pGC))
1574f7df2e56Smrg        return BadAlloc;
15756747b715Smrg    return Success;
157605b261ecSmrg}
157705b261ecSmrg
157805b261ecSmrgint
157905b261ecSmrgProcChangeGC(ClientPtr client)
158005b261ecSmrg{
158105b261ecSmrg    GC *pGC;
158205b261ecSmrg    int result;
158305b261ecSmrg    unsigned len;
1584f7df2e56Smrg
158505b261ecSmrg    REQUEST(xChangeGCReq);
158605b261ecSmrg    REQUEST_AT_LEAST_SIZE(xChangeGCReq);
158705b261ecSmrg
15884642e01fSmrg    result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess);
158905b261ecSmrg    if (result != Success)
1590f7df2e56Smrg        return result;
159105b261ecSmrg
1592f7df2e56Smrg    len = client->req_len - bytes_to_int32(sizeof(xChangeGCReq));
159305b261ecSmrg    if (len != Ones(stuff->mask))
159405b261ecSmrg        return BadLength;
159505b261ecSmrg
15966747b715Smrg    return ChangeGCXIDs(client, pGC, stuff->mask, (CARD32 *) &stuff[1]);
159705b261ecSmrg}
159805b261ecSmrg
159905b261ecSmrgint
160005b261ecSmrgProcCopyGC(ClientPtr client)
160105b261ecSmrg{
160205b261ecSmrg    GC *dstGC;
160305b261ecSmrg    GC *pGC;
160405b261ecSmrg    int result;
1605f7df2e56Smrg
160605b261ecSmrg    REQUEST(xCopyGCReq);
160705b261ecSmrg    REQUEST_SIZE_MATCH(xCopyGCReq);
160805b261ecSmrg
16094642e01fSmrg    result = dixLookupGC(&pGC, stuff->srcGC, client, DixGetAttrAccess);
161005b261ecSmrg    if (result != Success)
1611f7df2e56Smrg        return result;
16124642e01fSmrg    result = dixLookupGC(&dstGC, stuff->dstGC, client, DixSetAttrAccess);
161305b261ecSmrg    if (result != Success)
1614f7df2e56Smrg        return result;
161505b261ecSmrg    if ((dstGC->pScreen != pGC->pScreen) || (dstGC->depth != pGC->depth))
16166747b715Smrg        return BadMatch;
1617f7df2e56Smrg    if (stuff->mask & ~GCAllBits) {
1618f7df2e56Smrg        client->errorValue = stuff->mask;
1619f7df2e56Smrg        return BadValue;
162005b261ecSmrg    }
16216747b715Smrg    return CopyGC(pGC, dstGC, stuff->mask);
162205b261ecSmrg}
162305b261ecSmrg
162405b261ecSmrgint
162505b261ecSmrgProcSetDashes(ClientPtr client)
162605b261ecSmrg{
162705b261ecSmrg    GC *pGC;
162805b261ecSmrg    int result;
1629f7df2e56Smrg
163005b261ecSmrg    REQUEST(xSetDashesReq);
163105b261ecSmrg
163205b261ecSmrg    REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes);
1633f7df2e56Smrg    if (stuff->nDashes == 0) {
1634f7df2e56Smrg        client->errorValue = 0;
1635f7df2e56Smrg        return BadValue;
163605b261ecSmrg    }
163705b261ecSmrg
1638f7df2e56Smrg    result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess);
163905b261ecSmrg    if (result != Success)
1640f7df2e56Smrg        return result;
164105b261ecSmrg
16426747b715Smrg    /* If there's an error, either there's no sensible errorValue,
16436747b715Smrg     * or there was a dash segment of 0. */
16446747b715Smrg    client->errorValue = 0;
16456747b715Smrg    return SetDashes(pGC, stuff->dashOffset, stuff->nDashes,
1646f7df2e56Smrg                     (unsigned char *) &stuff[1]);
164705b261ecSmrg}
164805b261ecSmrg
164905b261ecSmrgint
165005b261ecSmrgProcSetClipRectangles(ClientPtr client)
165105b261ecSmrg{
1652f7df2e56Smrg    int nr, result;
165305b261ecSmrg    GC *pGC;
1654f7df2e56Smrg
165505b261ecSmrg    REQUEST(xSetClipRectanglesReq);
165605b261ecSmrg
165705b261ecSmrg    REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq);
165805b261ecSmrg    if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) &&
1659f7df2e56Smrg        (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded)) {
1660f7df2e56Smrg        client->errorValue = stuff->ordering;
166105b261ecSmrg        return BadValue;
166205b261ecSmrg    }
1663f7df2e56Smrg    result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess);
166405b261ecSmrg    if (result != Success)
1665f7df2e56Smrg        return result;
1666f7df2e56Smrg
166705b261ecSmrg    nr = (client->req_len << 2) - sizeof(xSetClipRectanglesReq);
166805b261ecSmrg    if (nr & 4)
1669f7df2e56Smrg        return BadLength;
167005b261ecSmrg    nr >>= 3;
16716747b715Smrg    return SetClipRects(pGC, stuff->xOrigin, stuff->yOrigin,
1672f7df2e56Smrg                        nr, (xRectangle *) &stuff[1], (int) stuff->ordering);
167305b261ecSmrg}
167405b261ecSmrg
167505b261ecSmrgint
167605b261ecSmrgProcFreeGC(ClientPtr client)
167705b261ecSmrg{
167805b261ecSmrg    GC *pGC;
167905b261ecSmrg    int rc;
1680f7df2e56Smrg
168105b261ecSmrg    REQUEST(xResourceReq);
168205b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
168305b261ecSmrg
168405b261ecSmrg    rc = dixLookupGC(&pGC, stuff->id, client, DixDestroyAccess);
168505b261ecSmrg    if (rc != Success)
1686f7df2e56Smrg        return rc;
168705b261ecSmrg
168805b261ecSmrg    FreeResource(stuff->id, RT_NONE);
16896747b715Smrg    return Success;
169005b261ecSmrg}
169105b261ecSmrg
169205b261ecSmrgint
169305b261ecSmrgProcClearToBackground(ClientPtr client)
169405b261ecSmrg{
169505b261ecSmrg    REQUEST(xClearAreaReq);
169605b261ecSmrg    WindowPtr pWin;
169705b261ecSmrg    int rc;
169805b261ecSmrg
169905b261ecSmrg    REQUEST_SIZE_MATCH(xClearAreaReq);
170005b261ecSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess);
170105b261ecSmrg    if (rc != Success)
170205b261ecSmrg        return rc;
1703f7df2e56Smrg    if (pWin->drawable.class == InputOnly) {
1704f7df2e56Smrg        client->errorValue = stuff->window;
1705f7df2e56Smrg        return BadMatch;
1706f7df2e56Smrg    }
1707f7df2e56Smrg    if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse)) {
1708f7df2e56Smrg        client->errorValue = stuff->exposures;
17096747b715Smrg        return BadValue;
171005b261ecSmrg    }
1711f7df2e56Smrg    (*pWin->drawable.pScreen->ClearToBackground) (pWin, stuff->x, stuff->y,
1712f7df2e56Smrg                                                  stuff->width, stuff->height,
1713f7df2e56Smrg                                                  (Bool) stuff->exposures);
17146747b715Smrg    return Success;
171505b261ecSmrg}
171605b261ecSmrg
1717f7df2e56Smrg/* send GraphicsExpose events, or a NoExpose event, based on the region */
1718f7df2e56Smrgvoid
1719f7df2e56SmrgSendGraphicsExpose(ClientPtr client, RegionPtr pRgn, XID drawable,
1720f7df2e56Smrg                     int major, int minor)
1721f7df2e56Smrg{
1722f7df2e56Smrg    if (pRgn && !RegionNil(pRgn)) {
1723f7df2e56Smrg        xEvent *pEvent;
1724f7df2e56Smrg        xEvent *pe;
1725f7df2e56Smrg        BoxPtr pBox;
1726f7df2e56Smrg        int i;
1727f7df2e56Smrg        int numRects;
1728f7df2e56Smrg
1729f7df2e56Smrg        numRects = RegionNumRects(pRgn);
1730f7df2e56Smrg        pBox = RegionRects(pRgn);
1731f7df2e56Smrg        if (!(pEvent = calloc(numRects, sizeof(xEvent))))
1732f7df2e56Smrg            return;
1733f7df2e56Smrg        pe = pEvent;
1734f7df2e56Smrg
1735f7df2e56Smrg        for (i = 1; i <= numRects; i++, pe++, pBox++) {
1736f7df2e56Smrg            pe->u.u.type = GraphicsExpose;
1737f7df2e56Smrg            pe->u.graphicsExposure.drawable = drawable;
1738f7df2e56Smrg            pe->u.graphicsExposure.x = pBox->x1;
1739f7df2e56Smrg            pe->u.graphicsExposure.y = pBox->y1;
1740f7df2e56Smrg            pe->u.graphicsExposure.width = pBox->x2 - pBox->x1;
1741f7df2e56Smrg            pe->u.graphicsExposure.height = pBox->y2 - pBox->y1;
1742f7df2e56Smrg            pe->u.graphicsExposure.count = numRects - i;
1743f7df2e56Smrg            pe->u.graphicsExposure.majorEvent = major;
1744f7df2e56Smrg            pe->u.graphicsExposure.minorEvent = minor;
1745f7df2e56Smrg        }
1746f7df2e56Smrg        /* GraphicsExpose is a "critical event", which TryClientEvents
1747f7df2e56Smrg         * handles specially. */
1748f7df2e56Smrg        TryClientEvents(client, NULL, pEvent, numRects,
1749f7df2e56Smrg                        (Mask) 0, NoEventMask, NullGrab);
1750f7df2e56Smrg        free(pEvent);
1751f7df2e56Smrg    }
1752f7df2e56Smrg    else {
1753f7df2e56Smrg        xEvent event = {
1754f7df2e56Smrg            .u.noExposure.drawable = drawable,
1755f7df2e56Smrg            .u.noExposure.majorEvent = major,
1756f7df2e56Smrg            .u.noExposure.minorEvent = minor
1757f7df2e56Smrg        };
1758f7df2e56Smrg        event.u.u.type = NoExpose;
1759f7df2e56Smrg        WriteEventsToClient(client, 1, &event);
1760f7df2e56Smrg    }
1761f7df2e56Smrg}
1762f7df2e56Smrg
176305b261ecSmrgint
176405b261ecSmrgProcCopyArea(ClientPtr client)
176505b261ecSmrg{
176605b261ecSmrg    DrawablePtr pDst;
176705b261ecSmrg    DrawablePtr pSrc;
176805b261ecSmrg    GC *pGC;
1769f7df2e56Smrg
177005b261ecSmrg    REQUEST(xCopyAreaReq);
177105b261ecSmrg    RegionPtr pRgn;
177205b261ecSmrg    int rc;
177305b261ecSmrg
177405b261ecSmrg    REQUEST_SIZE_MATCH(xCopyAreaReq);
177505b261ecSmrg
1776f7df2e56Smrg    VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, DixWriteAccess);
1777f7df2e56Smrg    if (stuff->dstDrawable != stuff->srcDrawable) {
1778f7df2e56Smrg        rc = dixLookupDrawable(&pSrc, stuff->srcDrawable, client, 0,
1779f7df2e56Smrg                               DixReadAccess);
1780f7df2e56Smrg        if (rc != Success)
1781f7df2e56Smrg            return rc;
1782f7df2e56Smrg        if ((pDst->pScreen != pSrc->pScreen) || (pDst->depth != pSrc->depth)) {
1783f7df2e56Smrg            client->errorValue = stuff->dstDrawable;
1784f7df2e56Smrg            return BadMatch;
1785f7df2e56Smrg        }
178605b261ecSmrg    }
178705b261ecSmrg    else
178805b261ecSmrg        pSrc = pDst;
178905b261ecSmrg
1790f7df2e56Smrg    pRgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, stuff->srcX, stuff->srcY,
1791f7df2e56Smrg                                  stuff->width, stuff->height,
1792f7df2e56Smrg                                  stuff->dstX, stuff->dstY);
1793f7df2e56Smrg    if (pGC->graphicsExposures) {
1794f7df2e56Smrg        SendGraphicsExpose(client, pRgn, stuff->dstDrawable, X_CopyArea, 0);
1795f7df2e56Smrg        if (pRgn)
1796f7df2e56Smrg            RegionDestroy(pRgn);
179705b261ecSmrg    }
179805b261ecSmrg
17996747b715Smrg    return Success;
180005b261ecSmrg}
180105b261ecSmrg
180205b261ecSmrgint
180305b261ecSmrgProcCopyPlane(ClientPtr client)
180405b261ecSmrg{
180505b261ecSmrg    DrawablePtr psrcDraw, pdstDraw;
180605b261ecSmrg    GC *pGC;
1807f7df2e56Smrg
180805b261ecSmrg    REQUEST(xCopyPlaneReq);
180905b261ecSmrg    RegionPtr pRgn;
181005b261ecSmrg    int rc;
181105b261ecSmrg
181205b261ecSmrg    REQUEST_SIZE_MATCH(xCopyPlaneReq);
181305b261ecSmrg
18144642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pdstDraw, DixWriteAccess);
1815f7df2e56Smrg    if (stuff->dstDrawable != stuff->srcDrawable) {
1816f7df2e56Smrg        rc = dixLookupDrawable(&psrcDraw, stuff->srcDrawable, client, 0,
1817f7df2e56Smrg                               DixReadAccess);
1818f7df2e56Smrg        if (rc != Success)
1819f7df2e56Smrg            return rc;
1820f7df2e56Smrg
1821f7df2e56Smrg        if (pdstDraw->pScreen != psrcDraw->pScreen) {
1822f7df2e56Smrg            client->errorValue = stuff->dstDrawable;
1823f7df2e56Smrg            return BadMatch;
1824f7df2e56Smrg        }
182505b261ecSmrg    }
182605b261ecSmrg    else
182705b261ecSmrg        psrcDraw = pdstDraw;
182805b261ecSmrg
182905b261ecSmrg    /* Check to see if stuff->bitPlane has exactly ONE good bit set */
1830f7df2e56Smrg    if (stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) ||
1831f7df2e56Smrg        (stuff->bitPlane > (1L << (psrcDraw->depth - 1)))) {
1832f7df2e56Smrg        client->errorValue = stuff->bitPlane;
1833f7df2e56Smrg        return BadValue;
183405b261ecSmrg    }
183505b261ecSmrg
1836f7df2e56Smrg    pRgn =
1837f7df2e56Smrg        (*pGC->ops->CopyPlane) (psrcDraw, pdstDraw, pGC, stuff->srcX,
1838f7df2e56Smrg                                stuff->srcY, stuff->width, stuff->height,
1839f7df2e56Smrg                                stuff->dstX, stuff->dstY, stuff->bitPlane);
1840f7df2e56Smrg    if (pGC->graphicsExposures) {
1841f7df2e56Smrg        SendGraphicsExpose(client, pRgn, stuff->dstDrawable, X_CopyPlane, 0);
1842f7df2e56Smrg        if (pRgn)
1843f7df2e56Smrg            RegionDestroy(pRgn);
184405b261ecSmrg    }
18456747b715Smrg    return Success;
184605b261ecSmrg}
184705b261ecSmrg
184805b261ecSmrgint
184905b261ecSmrgProcPolyPoint(ClientPtr client)
185005b261ecSmrg{
185105b261ecSmrg    int npoint;
185205b261ecSmrg    GC *pGC;
185305b261ecSmrg    DrawablePtr pDraw;
1854f7df2e56Smrg
185505b261ecSmrg    REQUEST(xPolyPointReq);
185605b261ecSmrg
185705b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolyPointReq);
1858f7df2e56Smrg    if ((stuff->coordMode != CoordModeOrigin) &&
1859f7df2e56Smrg        (stuff->coordMode != CoordModePrevious)) {
1860f7df2e56Smrg        client->errorValue = stuff->coordMode;
186105b261ecSmrg        return BadValue;
186205b261ecSmrg    }
1863f7df2e56Smrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
18646747b715Smrg    npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyPointReq));
186505b261ecSmrg    if (npoint)
1866f7df2e56Smrg        (*pGC->ops->PolyPoint) (pDraw, pGC, stuff->coordMode, npoint,
1867f7df2e56Smrg                                (xPoint *) &stuff[1]);
18686747b715Smrg    return Success;
186905b261ecSmrg}
187005b261ecSmrg
187105b261ecSmrgint
187205b261ecSmrgProcPolyLine(ClientPtr client)
187305b261ecSmrg{
187405b261ecSmrg    int npoint;
187505b261ecSmrg    GC *pGC;
187605b261ecSmrg    DrawablePtr pDraw;
1877f7df2e56Smrg
187805b261ecSmrg    REQUEST(xPolyLineReq);
187905b261ecSmrg
188005b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolyLineReq);
1881f7df2e56Smrg    if ((stuff->coordMode != CoordModeOrigin) &&
1882f7df2e56Smrg        (stuff->coordMode != CoordModePrevious)) {
1883f7df2e56Smrg        client->errorValue = stuff->coordMode;
188405b261ecSmrg        return BadValue;
188505b261ecSmrg    }
18864642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
18876747b715Smrg    npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyLineReq));
188805b261ecSmrg    if (npoint > 1)
1889f7df2e56Smrg        (*pGC->ops->Polylines) (pDraw, pGC, stuff->coordMode, npoint,
1890f7df2e56Smrg                                (DDXPointPtr) &stuff[1]);
18916747b715Smrg    return Success;
189205b261ecSmrg}
189305b261ecSmrg
189405b261ecSmrgint
189505b261ecSmrgProcPolySegment(ClientPtr client)
189605b261ecSmrg{
189705b261ecSmrg    int nsegs;
189805b261ecSmrg    GC *pGC;
189905b261ecSmrg    DrawablePtr pDraw;
1900f7df2e56Smrg
190105b261ecSmrg    REQUEST(xPolySegmentReq);
190205b261ecSmrg
190305b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolySegmentReq);
19044642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
190505b261ecSmrg    nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq);
190605b261ecSmrg    if (nsegs & 4)
1907f7df2e56Smrg        return BadLength;
190805b261ecSmrg    nsegs >>= 3;
190905b261ecSmrg    if (nsegs)
1910f7df2e56Smrg        (*pGC->ops->PolySegment) (pDraw, pGC, nsegs, (xSegment *) &stuff[1]);
19116747b715Smrg    return Success;
191205b261ecSmrg}
191305b261ecSmrg
191405b261ecSmrgint
1915f7df2e56SmrgProcPolyRectangle(ClientPtr client)
191605b261ecSmrg{
191705b261ecSmrg    int nrects;
191805b261ecSmrg    GC *pGC;
191905b261ecSmrg    DrawablePtr pDraw;
1920f7df2e56Smrg
192105b261ecSmrg    REQUEST(xPolyRectangleReq);
192205b261ecSmrg
192305b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolyRectangleReq);
19244642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
192505b261ecSmrg    nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq);
192605b261ecSmrg    if (nrects & 4)
1927f7df2e56Smrg        return BadLength;
192805b261ecSmrg    nrects >>= 3;
192905b261ecSmrg    if (nrects)
1930f7df2e56Smrg        (*pGC->ops->PolyRectangle) (pDraw, pGC,
1931f7df2e56Smrg                                    nrects, (xRectangle *) &stuff[1]);
19326747b715Smrg    return Success;
193305b261ecSmrg}
193405b261ecSmrg
193505b261ecSmrgint
193605b261ecSmrgProcPolyArc(ClientPtr client)
193705b261ecSmrg{
1938f7df2e56Smrg    int narcs;
193905b261ecSmrg    GC *pGC;
194005b261ecSmrg    DrawablePtr pDraw;
1941f7df2e56Smrg
194205b261ecSmrg    REQUEST(xPolyArcReq);
194305b261ecSmrg
194405b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolyArcReq);
19454642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
194605b261ecSmrg    narcs = (client->req_len << 2) - sizeof(xPolyArcReq);
194705b261ecSmrg    if (narcs % sizeof(xArc))
1948f7df2e56Smrg        return BadLength;
194905b261ecSmrg    narcs /= sizeof(xArc);
195005b261ecSmrg    if (narcs)
1951f7df2e56Smrg        (*pGC->ops->PolyArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]);
19526747b715Smrg    return Success;
195305b261ecSmrg}
195405b261ecSmrg
195505b261ecSmrgint
195605b261ecSmrgProcFillPoly(ClientPtr client)
195705b261ecSmrg{
1958f7df2e56Smrg    int things;
195905b261ecSmrg    GC *pGC;
196005b261ecSmrg    DrawablePtr pDraw;
1961f7df2e56Smrg
196205b261ecSmrg    REQUEST(xFillPolyReq);
196305b261ecSmrg
196405b261ecSmrg    REQUEST_AT_LEAST_SIZE(xFillPolyReq);
1965f7df2e56Smrg    if ((stuff->shape != Complex) && (stuff->shape != Nonconvex) &&
1966f7df2e56Smrg        (stuff->shape != Convex)) {
1967f7df2e56Smrg        client->errorValue = stuff->shape;
196805b261ecSmrg        return BadValue;
196905b261ecSmrg    }
1970f7df2e56Smrg    if ((stuff->coordMode != CoordModeOrigin) &&
1971f7df2e56Smrg        (stuff->coordMode != CoordModePrevious)) {
1972f7df2e56Smrg        client->errorValue = stuff->coordMode;
197305b261ecSmrg        return BadValue;
197405b261ecSmrg    }
197505b261ecSmrg
19764642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
19776747b715Smrg    things = bytes_to_int32((client->req_len << 2) - sizeof(xFillPolyReq));
197805b261ecSmrg    if (things)
197905b261ecSmrg        (*pGC->ops->FillPolygon) (pDraw, pGC, stuff->shape,
1980f7df2e56Smrg                                  stuff->coordMode, things,
1981f7df2e56Smrg                                  (DDXPointPtr) &stuff[1]);
19826747b715Smrg    return Success;
198305b261ecSmrg}
198405b261ecSmrg
198505b261ecSmrgint
198605b261ecSmrgProcPolyFillRectangle(ClientPtr client)
198705b261ecSmrg{
1988f7df2e56Smrg    int things;
198905b261ecSmrg    GC *pGC;
199005b261ecSmrg    DrawablePtr pDraw;
1991f7df2e56Smrg
199205b261ecSmrg    REQUEST(xPolyFillRectangleReq);
199305b261ecSmrg
199405b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq);
19954642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
199605b261ecSmrg    things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq);
199705b261ecSmrg    if (things & 4)
1998f7df2e56Smrg        return BadLength;
199905b261ecSmrg    things >>= 3;
200005b261ecSmrg
200105b261ecSmrg    if (things)
200205b261ecSmrg        (*pGC->ops->PolyFillRect) (pDraw, pGC, things,
2003f7df2e56Smrg                                   (xRectangle *) &stuff[1]);
20046747b715Smrg    return Success;
200505b261ecSmrg}
200605b261ecSmrg
200705b261ecSmrgint
200805b261ecSmrgProcPolyFillArc(ClientPtr client)
200905b261ecSmrg{
2010f7df2e56Smrg    int narcs;
201105b261ecSmrg    GC *pGC;
201205b261ecSmrg    DrawablePtr pDraw;
2013f7df2e56Smrg
201405b261ecSmrg    REQUEST(xPolyFillArcReq);
201505b261ecSmrg
201605b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolyFillArcReq);
20174642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
201805b261ecSmrg    narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq);
201905b261ecSmrg    if (narcs % sizeof(xArc))
2020f7df2e56Smrg        return BadLength;
202105b261ecSmrg    narcs /= sizeof(xArc);
202205b261ecSmrg    if (narcs)
202305b261ecSmrg        (*pGC->ops->PolyFillArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]);
20246747b715Smrg    return Success;
202505b261ecSmrg}
202605b261ecSmrg
202705b261ecSmrg#ifdef MATCH_CLIENT_ENDIAN
202805b261ecSmrg
202905b261ecSmrgint
2030f7df2e56SmrgServerOrder(void)
203105b261ecSmrg{
2032f7df2e56Smrg    int whichbyte = 1;
203305b261ecSmrg
203405b261ecSmrg    if (*((char *) &whichbyte))
2035f7df2e56Smrg        return LSBFirst;
203605b261ecSmrg    return MSBFirst;
203705b261ecSmrg}
203805b261ecSmrg
203905b261ecSmrg#define ClientOrder(client) ((client)->swapped ? !ServerOrder() : ServerOrder())
204005b261ecSmrg
204105b261ecSmrgvoid
2042f7df2e56SmrgReformatImage(char *base, int nbytes, int bpp, int order)
204305b261ecSmrg{
204405b261ecSmrg    switch (bpp) {
2045f7df2e56Smrg    case 1:                    /* yuck */
2046f7df2e56Smrg        if (BITMAP_BIT_ORDER != order)
2047f7df2e56Smrg            BitOrderInvert((unsigned char *) base, nbytes);
204805b261ecSmrg#if IMAGE_BYTE_ORDER != BITMAP_BIT_ORDER && BITMAP_SCANLINE_UNIT != 8
2049f7df2e56Smrg        ReformatImage(base, nbytes, BITMAP_SCANLINE_UNIT, order);
205005b261ecSmrg#endif
2051f7df2e56Smrg        break;
205205b261ecSmrg    case 4:
2053f7df2e56Smrg        break;                  /* yuck */
205405b261ecSmrg    case 8:
2055f7df2e56Smrg        break;
205605b261ecSmrg    case 16:
2057f7df2e56Smrg        if (IMAGE_BYTE_ORDER != order)
2058f7df2e56Smrg            TwoByteSwap((unsigned char *) base, nbytes);
2059f7df2e56Smrg        break;
206005b261ecSmrg    case 32:
2061f7df2e56Smrg        if (IMAGE_BYTE_ORDER != order)
2062f7df2e56Smrg            FourByteSwap((unsigned char *) base, nbytes);
2063f7df2e56Smrg        break;
206405b261ecSmrg    }
206505b261ecSmrg}
206605b261ecSmrg#else
206705b261ecSmrg#define ReformatImage(b,n,bpp,o)
206805b261ecSmrg#endif
206905b261ecSmrg
207005b261ecSmrg/* 64-bit server notes: the protocol restricts padding of images to
207105b261ecSmrg * 8-, 16-, or 32-bits. We would like to have 64-bits for the server
207205b261ecSmrg * to use internally. Removes need for internal alignment checking.
207305b261ecSmrg * All of the PutImage functions could be changed individually, but
207405b261ecSmrg * as currently written, they call other routines which require things
207505b261ecSmrg * to be 64-bit padded on scanlines, so we changed things here.
207605b261ecSmrg * If an image would be padded differently for 64- versus 32-, then
207705b261ecSmrg * copy each scanline to a 64-bit padded scanline.
207805b261ecSmrg * Also, we need to make sure that the image is aligned on a 64-bit
207905b261ecSmrg * boundary, even if the scanlines are padded to our satisfaction.
208005b261ecSmrg */
208105b261ecSmrgint
208205b261ecSmrgProcPutImage(ClientPtr client)
208305b261ecSmrg{
208405b261ecSmrg    GC *pGC;
208505b261ecSmrg    DrawablePtr pDraw;
2086f7df2e56Smrg    long length;                /* length of scanline server padded */
2087f7df2e56Smrg    long lengthProto;           /* length of scanline protocol padded */
2088f7df2e56Smrg    char *tmpImage;
2089f7df2e56Smrg
209005b261ecSmrg    REQUEST(xPutImageReq);
209105b261ecSmrg
209205b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPutImageReq);
20934642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
2094f7df2e56Smrg    if (stuff->format == XYBitmap) {
209505b261ecSmrg        if ((stuff->depth != 1) ||
2096f7df2e56Smrg            (stuff->leftPad >= (unsigned int) screenInfo.bitmapScanlinePad))
209705b261ecSmrg            return BadMatch;
2098f7df2e56Smrg        length = BitmapBytePad(stuff->width + stuff->leftPad);
209905b261ecSmrg    }
2100f7df2e56Smrg    else if (stuff->format == XYPixmap) {
2101f7df2e56Smrg        if ((pDraw->depth != stuff->depth) ||
2102f7df2e56Smrg            (stuff->leftPad >= (unsigned int) screenInfo.bitmapScanlinePad))
210305b261ecSmrg            return BadMatch;
2104f7df2e56Smrg        length = BitmapBytePad(stuff->width + stuff->leftPad);
2105f7df2e56Smrg        length *= stuff->depth;
210605b261ecSmrg    }
2107f7df2e56Smrg    else if (stuff->format == ZPixmap) {
210805b261ecSmrg        if ((pDraw->depth != stuff->depth) || (stuff->leftPad != 0))
210905b261ecSmrg            return BadMatch;
2110f7df2e56Smrg        length = PixmapBytePad(stuff->width, stuff->depth);
211105b261ecSmrg    }
2112f7df2e56Smrg    else {
2113f7df2e56Smrg        client->errorValue = stuff->format;
211405b261ecSmrg        return BadValue;
211505b261ecSmrg    }
211605b261ecSmrg
2117f7df2e56Smrg    tmpImage = (char *) &stuff[1];
211805b261ecSmrg    lengthProto = length;
21190b0d8713Smrg
2120f7df2e56Smrg    if (stuff->height != 0 && lengthProto >= (INT32_MAX / stuff->height))
21210b0d8713Smrg        return BadLength;
2122f7df2e56Smrg
21236747b715Smrg    if ((bytes_to_int32(lengthProto * stuff->height) +
2124f7df2e56Smrg         bytes_to_int32(sizeof(xPutImageReq))) != client->req_len)
2125f7df2e56Smrg        return BadLength;
2126f7df2e56Smrg
2127f7df2e56Smrg    ReformatImage(tmpImage, lengthProto * stuff->height,
2128f7df2e56Smrg                  stuff->format == ZPixmap ? BitsPerPixel(stuff->depth) : 1,
2129f7df2e56Smrg                  ClientOrder(client));
213005b261ecSmrg
213105b261ecSmrg    (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, stuff->dstX, stuff->dstY,
2132f7df2e56Smrg                           stuff->width, stuff->height,
2133f7df2e56Smrg                           stuff->leftPad, stuff->format, tmpImage);
213405b261ecSmrg
2135f7df2e56Smrg    return Success;
213605b261ecSmrg}
213705b261ecSmrg
213805b261ecSmrgstatic int
2139f7df2e56SmrgDoGetImage(ClientPtr client, int format, Drawable drawable,
2140f7df2e56Smrg           int x, int y, int width, int height,
2141f7df2e56Smrg           Mask planemask)
214205b261ecSmrg{
2143f7df2e56Smrg    DrawablePtr pDraw, pBoundingDraw;
2144f7df2e56Smrg    int nlines, linesPerBuf, rc;
2145f7df2e56Smrg    int linesDone;
2146f7df2e56Smrg
21476747b715Smrg    /* coordinates relative to the bounding drawable */
2148f7df2e56Smrg    int relx, rely;
2149f7df2e56Smrg    long widthBytesLine, length;
2150f7df2e56Smrg    Mask plane = 0;
2151f7df2e56Smrg    char *pBuf;
2152f7df2e56Smrg    xGetImageReply xgi;
215305b261ecSmrg    RegionPtr pVisibleRegion = NULL;
215405b261ecSmrg
2155f7df2e56Smrg    if ((format != XYPixmap) && (format != ZPixmap)) {
2156f7df2e56Smrg        client->errorValue = format;
21576747b715Smrg        return BadValue;
215805b261ecSmrg    }
215905b261ecSmrg    rc = dixLookupDrawable(&pDraw, drawable, client, 0, DixReadAccess);
216005b261ecSmrg    if (rc != Success)
2161f7df2e56Smrg        return rc;
216205b261ecSmrg
21636747b715Smrg    memset(&xgi, 0, sizeof(xGetImageReply));
21646747b715Smrg
21656747b715Smrg    relx = x;
21666747b715Smrg    rely = y;
21676747b715Smrg
2168f7df2e56Smrg    if (pDraw->type == DRAWABLE_WINDOW) {
2169f7df2e56Smrg        WindowPtr pWin = (WindowPtr) pDraw;
2170f7df2e56Smrg
2171f7df2e56Smrg        /* "If the drawable is a window, the window must be viewable ... or a
2172f7df2e56Smrg         * BadMatch error results" */
2173f7df2e56Smrg        if (!pWin->viewable)
2174f7df2e56Smrg            return BadMatch;
21756747b715Smrg
2176f7df2e56Smrg        /* If the drawable is a window, the rectangle must be contained within
2177f7df2e56Smrg         * its bounds (including the border). */
2178f7df2e56Smrg        if (x < -wBorderWidth(pWin) ||
2179f7df2e56Smrg            x + width > wBorderWidth(pWin) + (int) pDraw->width ||
2180f7df2e56Smrg            y < -wBorderWidth(pWin) ||
2181f7df2e56Smrg            y + height > wBorderWidth(pWin) + (int) pDraw->height)
2182f7df2e56Smrg            return BadMatch;
21836747b715Smrg
2184f7df2e56Smrg        relx += pDraw->x;
2185f7df2e56Smrg        rely += pDraw->y;
21866747b715Smrg
2187f7df2e56Smrg        if (pDraw->pScreen->GetWindowPixmap) {
2188f7df2e56Smrg            PixmapPtr pPix = (*pDraw->pScreen->GetWindowPixmap) (pWin);
21896747b715Smrg
2190f7df2e56Smrg            pBoundingDraw = &pPix->drawable;
21916747b715Smrg#ifdef COMPOSITE
2192f7df2e56Smrg            relx -= pPix->screen_x;
2193f7df2e56Smrg            rely -= pPix->screen_y;
21946747b715Smrg#endif
2195f7df2e56Smrg        }
2196f7df2e56Smrg        else {
2197f7df2e56Smrg            pBoundingDraw = (DrawablePtr) pDraw->pScreen->root;
2198f7df2e56Smrg        }
21996747b715Smrg
2200f7df2e56Smrg        xgi.visual = wVisual(pWin);
220105b261ecSmrg    }
2202f7df2e56Smrg    else {
2203f7df2e56Smrg        pBoundingDraw = pDraw;
2204f7df2e56Smrg        xgi.visual = None;
220505b261ecSmrg    }
220605b261ecSmrg
22076747b715Smrg    /* "If the drawable is a pixmap, the given rectangle must be wholly
22086747b715Smrg     *  contained within the pixmap, or a BadMatch error results.  If the
22096747b715Smrg     *  drawable is a window [...] it must be the case that if there were no
22106747b715Smrg     *  inferiors or overlapping windows, the specified rectangle of the window
22116747b715Smrg     *  would be fully visible on the screen and wholly contained within the
22126747b715Smrg     *  outside edges of the window, or a BadMatch error results."
22136747b715Smrg     *
22146747b715Smrg     * We relax the window case slightly to mean that the rectangle must exist
22156747b715Smrg     * within the bounds of the window's backing pixmap.  In particular, this
22166747b715Smrg     * means that a GetImage request may succeed or fail with BadMatch depending
22176747b715Smrg     * on whether any of its ancestor windows are redirected.  */
2218f7df2e56Smrg    if (relx < 0 || relx + width > (int) pBoundingDraw->width ||
2219f7df2e56Smrg        rely < 0 || rely + height > (int) pBoundingDraw->height)
2220f7df2e56Smrg        return BadMatch;
22216747b715Smrg
222205b261ecSmrg    xgi.type = X_Reply;
222305b261ecSmrg    xgi.sequenceNumber = client->sequence;
222405b261ecSmrg    xgi.depth = pDraw->depth;
2225f7df2e56Smrg    if (format == ZPixmap) {
2226f7df2e56Smrg        widthBytesLine = PixmapBytePad(width, pDraw->depth);
2227f7df2e56Smrg        length = widthBytesLine * height;
222805b261ecSmrg
222905b261ecSmrg    }
2230f7df2e56Smrg    else {
2231f7df2e56Smrg        widthBytesLine = BitmapBytePad(width);
2232f7df2e56Smrg        plane = ((Mask) 1) << (pDraw->depth - 1);
2233f7df2e56Smrg        /* only planes asked for */
2234f7df2e56Smrg        length = widthBytesLine * height *
2235f7df2e56Smrg            Ones(planemask & (plane | (plane - 1)));
223605b261ecSmrg
223705b261ecSmrg    }
223805b261ecSmrg
223905b261ecSmrg    xgi.length = length;
224005b261ecSmrg
2241f7df2e56Smrg    xgi.length = bytes_to_int32(xgi.length);
2242f7df2e56Smrg    if (widthBytesLine == 0 || height == 0)
2243f7df2e56Smrg        linesPerBuf = 0;
2244f7df2e56Smrg    else if (widthBytesLine >= IMAGE_BUFSIZE)
2245f7df2e56Smrg        linesPerBuf = 1;
2246f7df2e56Smrg    else {
2247f7df2e56Smrg        linesPerBuf = IMAGE_BUFSIZE / widthBytesLine;
2248f7df2e56Smrg        if (linesPerBuf > height)
2249f7df2e56Smrg            linesPerBuf = height;
2250f7df2e56Smrg    }
2251f7df2e56Smrg    length = linesPerBuf * widthBytesLine;
2252f7df2e56Smrg    if (linesPerBuf < height) {
2253f7df2e56Smrg        /* we have to make sure intermediate buffers don't need padding */
2254f7df2e56Smrg        while ((linesPerBuf > 1) &&
2255f7df2e56Smrg               (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD) - 1))) {
2256f7df2e56Smrg            linesPerBuf--;
2257f7df2e56Smrg            length -= widthBytesLine;
2258f7df2e56Smrg        }
2259f7df2e56Smrg        while (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD) - 1)) {
2260f7df2e56Smrg            linesPerBuf++;
2261f7df2e56Smrg            length += widthBytesLine;
2262f7df2e56Smrg        }
226305b261ecSmrg    }
2264f7df2e56Smrg    if (!(pBuf = calloc(1, length)))
2265f7df2e56Smrg        return BadAlloc;
2266f7df2e56Smrg    WriteReplyToClient(client, sizeof(xGetImageReply), &xgi);
226705b261ecSmrg
22684e185dc0Smrg    if (pDraw->type == DRAWABLE_WINDOW) {
22697e31ba66Smrg        pVisibleRegion = &((WindowPtr) pDraw)->borderClip;
22704e185dc0Smrg        pDraw->pScreen->SourceValidate(pDraw, x, y, width, height,
22714e185dc0Smrg                                       IncludeInferiors);
22724e185dc0Smrg    }
2273f7df2e56Smrg
2274f7df2e56Smrg    if (linesPerBuf == 0) {
2275f7df2e56Smrg        /* nothing to do */
2276f7df2e56Smrg    }
2277f7df2e56Smrg    else if (format == ZPixmap) {
227805b261ecSmrg        linesDone = 0;
2279f7df2e56Smrg        while (height - linesDone > 0) {
2280f7df2e56Smrg            nlines = min(linesPerBuf, height - linesDone);
2281f7df2e56Smrg            (*pDraw->pScreen->GetImage) (pDraw,
2282f7df2e56Smrg                                         x,
2283f7df2e56Smrg                                         y + linesDone,
2284f7df2e56Smrg                                         width,
2285f7df2e56Smrg                                         nlines,
2286f7df2e56Smrg                                         format, planemask, (void *) pBuf);
2287f7df2e56Smrg            if (pVisibleRegion)
2288f7df2e56Smrg                XaceCensorImage(client, pVisibleRegion, widthBytesLine,
2289f7df2e56Smrg                                pDraw, x, y + linesDone, width,
2290f7df2e56Smrg                                nlines, format, pBuf);
2291f7df2e56Smrg
2292f7df2e56Smrg            /* Note that this is NOT a call to WriteSwappedDataToClient,
229305b261ecSmrg               as we do NOT byte swap */
2294f7df2e56Smrg            ReformatImage(pBuf, (int) (nlines * widthBytesLine),
2295f7df2e56Smrg                          BitsPerPixel(pDraw->depth), ClientOrder(client));
2296f7df2e56Smrg
2297f7df2e56Smrg            WriteToClient(client, (int) (nlines * widthBytesLine), pBuf);
2298f7df2e56Smrg            linesDone += nlines;
229905b261ecSmrg        }
230005b261ecSmrg    }
2301f7df2e56Smrg    else {                      /* XYPixmap */
2302f7df2e56Smrg
2303f7df2e56Smrg        for (; plane; plane >>= 1) {
2304f7df2e56Smrg            if (planemask & plane) {
2305f7df2e56Smrg                linesDone = 0;
2306f7df2e56Smrg                while (height - linesDone > 0) {
2307f7df2e56Smrg                    nlines = min(linesPerBuf, height - linesDone);
2308f7df2e56Smrg                    (*pDraw->pScreen->GetImage) (pDraw,
2309f7df2e56Smrg                                                 x,
2310f7df2e56Smrg                                                 y + linesDone,
2311f7df2e56Smrg                                                 width,
2312f7df2e56Smrg                                                 nlines,
2313f7df2e56Smrg                                                 format, plane, (void *) pBuf);
2314f7df2e56Smrg                    if (pVisibleRegion)
2315f7df2e56Smrg                        XaceCensorImage(client, pVisibleRegion,
2316f7df2e56Smrg                                        widthBytesLine,
2317f7df2e56Smrg                                        pDraw, x, y + linesDone, width,
2318f7df2e56Smrg                                        nlines, format, pBuf);
2319f7df2e56Smrg
2320f7df2e56Smrg                    /* Note: NOT a call to WriteSwappedDataToClient,
2321f7df2e56Smrg                       as we do NOT byte swap */
2322f7df2e56Smrg                    ReformatImage(pBuf, (int) (nlines * widthBytesLine),
2323f7df2e56Smrg                                  1, ClientOrder(client));
2324f7df2e56Smrg
2325f7df2e56Smrg                    WriteToClient(client, (int)(nlines * widthBytesLine), pBuf);
2326f7df2e56Smrg                    linesDone += nlines;
2327f7df2e56Smrg                }
232805b261ecSmrg            }
2329f7df2e56Smrg        }
233005b261ecSmrg    }
2331f7df2e56Smrg    free(pBuf);
23326747b715Smrg    return Success;
233305b261ecSmrg}
233405b261ecSmrg
233505b261ecSmrgint
233605b261ecSmrgProcGetImage(ClientPtr client)
233705b261ecSmrg{
233805b261ecSmrg    REQUEST(xGetImageReq);
233905b261ecSmrg
234005b261ecSmrg    REQUEST_SIZE_MATCH(xGetImageReq);
234105b261ecSmrg
234205b261ecSmrg    return DoGetImage(client, stuff->format, stuff->drawable,
2343f7df2e56Smrg                      stuff->x, stuff->y,
2344f7df2e56Smrg                      (int) stuff->width, (int) stuff->height,
2345f7df2e56Smrg                      stuff->planeMask);
234605b261ecSmrg}
234705b261ecSmrg
234805b261ecSmrgint
234905b261ecSmrgProcPolyText(ClientPtr client)
235005b261ecSmrg{
2351f7df2e56Smrg    int err;
2352f7df2e56Smrg
235305b261ecSmrg    REQUEST(xPolyTextReq);
235405b261ecSmrg    DrawablePtr pDraw;
235505b261ecSmrg    GC *pGC;
235605b261ecSmrg
235705b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolyTextReq);
23584642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
235905b261ecSmrg
236005b261ecSmrg    err = PolyText(client,
2361f7df2e56Smrg                   pDraw,
2362f7df2e56Smrg                   pGC,
2363f7df2e56Smrg                   (unsigned char *) &stuff[1],
2364f7df2e56Smrg                   ((unsigned char *) stuff) + (client->req_len << 2),
2365f7df2e56Smrg                   stuff->x, stuff->y, stuff->reqType, stuff->drawable);
2366f7df2e56Smrg
2367f7df2e56Smrg    if (err == Success) {
2368f7df2e56Smrg        return Success;
236905b261ecSmrg    }
237005b261ecSmrg    else
2371f7df2e56Smrg        return err;
237205b261ecSmrg}
237305b261ecSmrg
237405b261ecSmrgint
237505b261ecSmrgProcImageText8(ClientPtr client)
237605b261ecSmrg{
2377f7df2e56Smrg    int err;
237805b261ecSmrg    DrawablePtr pDraw;
237905b261ecSmrg    GC *pGC;
238005b261ecSmrg
238105b261ecSmrg    REQUEST(xImageTextReq);
238205b261ecSmrg
238305b261ecSmrg    REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars);
23844642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
238505b261ecSmrg
238605b261ecSmrg    err = ImageText(client,
2387f7df2e56Smrg                    pDraw,
2388f7df2e56Smrg                    pGC,
2389f7df2e56Smrg                    stuff->nChars,
2390f7df2e56Smrg                    (unsigned char *) &stuff[1],
2391f7df2e56Smrg                    stuff->x, stuff->y, stuff->reqType, stuff->drawable);
2392f7df2e56Smrg
2393f7df2e56Smrg    if (err == Success) {
2394f7df2e56Smrg        return Success;
239505b261ecSmrg    }
239605b261ecSmrg    else
2397f7df2e56Smrg        return err;
239805b261ecSmrg}
239905b261ecSmrg
240005b261ecSmrgint
240105b261ecSmrgProcImageText16(ClientPtr client)
240205b261ecSmrg{
2403f7df2e56Smrg    int err;
240405b261ecSmrg    DrawablePtr pDraw;
240505b261ecSmrg    GC *pGC;
240605b261ecSmrg
240705b261ecSmrg    REQUEST(xImageTextReq);
240805b261ecSmrg
240905b261ecSmrg    REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars << 1);
24104642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
241105b261ecSmrg
241205b261ecSmrg    err = ImageText(client,
2413f7df2e56Smrg                    pDraw,
2414f7df2e56Smrg                    pGC,
2415f7df2e56Smrg                    stuff->nChars,
2416f7df2e56Smrg                    (unsigned char *) &stuff[1],
2417f7df2e56Smrg                    stuff->x, stuff->y, stuff->reqType, stuff->drawable);
2418f7df2e56Smrg
2419f7df2e56Smrg    if (err == Success) {
2420f7df2e56Smrg        return Success;
242105b261ecSmrg    }
242205b261ecSmrg    else
2423f7df2e56Smrg        return err;
242405b261ecSmrg}
242505b261ecSmrg
242605b261ecSmrgint
242705b261ecSmrgProcCreateColormap(ClientPtr client)
242805b261ecSmrg{
2429f7df2e56Smrg    VisualPtr pVisual;
2430f7df2e56Smrg    ColormapPtr pmap;
2431f7df2e56Smrg    Colormap mid;
2432f7df2e56Smrg    WindowPtr pWin;
243305b261ecSmrg    ScreenPtr pScreen;
2434f7df2e56Smrg
243505b261ecSmrg    REQUEST(xCreateColormapReq);
243605b261ecSmrg    int i, result;
243705b261ecSmrg
243805b261ecSmrg    REQUEST_SIZE_MATCH(xCreateColormapReq);
243905b261ecSmrg
2440f7df2e56Smrg    if ((stuff->alloc != AllocNone) && (stuff->alloc != AllocAll)) {
2441f7df2e56Smrg        client->errorValue = stuff->alloc;
24426747b715Smrg        return BadValue;
244305b261ecSmrg    }
244405b261ecSmrg    mid = stuff->mid;
244505b261ecSmrg    LEGAL_NEW_RESOURCE(mid, client);
24464642e01fSmrg    result = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
244705b261ecSmrg    if (result != Success)
244805b261ecSmrg        return result;
244905b261ecSmrg
245005b261ecSmrg    pScreen = pWin->drawable.pScreen;
245105b261ecSmrg    for (i = 0, pVisual = pScreen->visuals;
2452f7df2e56Smrg         i < pScreen->numVisuals; i++, pVisual++) {
2453f7df2e56Smrg        if (pVisual->vid != stuff->visual)
2454f7df2e56Smrg            continue;
2455f7df2e56Smrg        return CreateColormap(mid, pScreen, pVisual, &pmap,
2456f7df2e56Smrg                              (int) stuff->alloc, client->index);
245705b261ecSmrg    }
245805b261ecSmrg    client->errorValue = stuff->visual;
24596747b715Smrg    return BadMatch;
246005b261ecSmrg}
246105b261ecSmrg
246205b261ecSmrgint
246305b261ecSmrgProcFreeColormap(ClientPtr client)
246405b261ecSmrg{
246505b261ecSmrg    ColormapPtr pmap;
24664642e01fSmrg    int rc;
2467f7df2e56Smrg
246805b261ecSmrg    REQUEST(xResourceReq);
246905b261ecSmrg
247005b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
2471f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pmap, stuff->id, RT_COLORMAP,
2472f7df2e56Smrg                                 client, DixDestroyAccess);
2473f7df2e56Smrg    if (rc == Success) {
2474f7df2e56Smrg        /* Freeing a default colormap is a no-op */
2475f7df2e56Smrg        if (!(pmap->flags & IsDefault))
2476f7df2e56Smrg            FreeResource(stuff->id, RT_NONE);
2477f7df2e56Smrg        return Success;
247805b261ecSmrg    }
2479f7df2e56Smrg    else {
2480f7df2e56Smrg        client->errorValue = stuff->id;
2481f7df2e56Smrg        return rc;
248205b261ecSmrg    }
248305b261ecSmrg}
248405b261ecSmrg
248505b261ecSmrgint
248605b261ecSmrgProcCopyColormapAndFree(ClientPtr client)
248705b261ecSmrg{
2488f7df2e56Smrg    Colormap mid;
2489f7df2e56Smrg    ColormapPtr pSrcMap;
2490f7df2e56Smrg
249105b261ecSmrg    REQUEST(xCopyColormapAndFreeReq);
24924642e01fSmrg    int rc;
249305b261ecSmrg
249405b261ecSmrg    REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq);
249505b261ecSmrg    mid = stuff->mid;
249605b261ecSmrg    LEGAL_NEW_RESOURCE(mid, client);
2497f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pSrcMap, stuff->srcCmap,
2498f7df2e56Smrg                                 RT_COLORMAP, client,
2499f7df2e56Smrg                                 DixReadAccess | DixRemoveAccess);
25004642e01fSmrg    if (rc == Success)
2501f7df2e56Smrg        return CopyColormapAndFree(mid, pSrcMap, client->index);
25026747b715Smrg    client->errorValue = stuff->srcCmap;
25036747b715Smrg    return rc;
250405b261ecSmrg}
250505b261ecSmrg
250605b261ecSmrgint
250705b261ecSmrgProcInstallColormap(ClientPtr client)
250805b261ecSmrg{
250905b261ecSmrg    ColormapPtr pcmp;
25104642e01fSmrg    int rc;
2511f7df2e56Smrg
251205b261ecSmrg    REQUEST(xResourceReq);
251305b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
25144642e01fSmrg
2515f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->id, RT_COLORMAP,
2516f7df2e56Smrg                                 client, DixInstallAccess);
25174642e01fSmrg    if (rc != Success)
2518f7df2e56Smrg        goto out;
25194642e01fSmrg
25204642e01fSmrg    rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess);
25216747b715Smrg    if (rc != Success) {
2522f7df2e56Smrg        if (rc == BadValue)
2523f7df2e56Smrg            rc = BadColor;
2524f7df2e56Smrg        goto out;
25256747b715Smrg    }
25264642e01fSmrg
25274642e01fSmrg    (*(pcmp->pScreen->InstallColormap)) (pcmp);
25286747b715Smrg    return Success;
25294642e01fSmrg
2530f7df2e56Smrg out:
25314642e01fSmrg    client->errorValue = stuff->id;
25326747b715Smrg    return rc;
253305b261ecSmrg}
253405b261ecSmrg
253505b261ecSmrgint
253605b261ecSmrgProcUninstallColormap(ClientPtr client)
253705b261ecSmrg{
253805b261ecSmrg    ColormapPtr pcmp;
25394642e01fSmrg    int rc;
2540f7df2e56Smrg
254105b261ecSmrg    REQUEST(xResourceReq);
254205b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
25434642e01fSmrg
2544f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->id, RT_COLORMAP,
2545f7df2e56Smrg                                 client, DixUninstallAccess);
25464642e01fSmrg    if (rc != Success)
2547f7df2e56Smrg        goto out;
25484642e01fSmrg
25494642e01fSmrg    rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess);
25506747b715Smrg    if (rc != Success) {
2551f7df2e56Smrg        if (rc == BadValue)
2552f7df2e56Smrg            rc = BadColor;
2553f7df2e56Smrg        goto out;
25546747b715Smrg    }
25554642e01fSmrg
2556f7df2e56Smrg    if (pcmp->mid != pcmp->pScreen->defColormap)
2557f7df2e56Smrg        (*(pcmp->pScreen->UninstallColormap)) (pcmp);
25586747b715Smrg    return Success;
25594642e01fSmrg
2560f7df2e56Smrg out:
25614642e01fSmrg    client->errorValue = stuff->id;
25626747b715Smrg    return rc;
256305b261ecSmrg}
256405b261ecSmrg
256505b261ecSmrgint
256605b261ecSmrgProcListInstalledColormaps(ClientPtr client)
256705b261ecSmrg{
2568f7df2e56Smrg    xListInstalledColormapsReply *preply;
256905b261ecSmrg    int nummaps, rc;
257005b261ecSmrg    WindowPtr pWin;
2571f7df2e56Smrg
257205b261ecSmrg    REQUEST(xResourceReq);
257305b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
25744642e01fSmrg
25754642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
257605b261ecSmrg    if (rc != Success)
2577f7df2e56Smrg        return rc;
25784642e01fSmrg
25794642e01fSmrg    rc = XaceHook(XACE_SCREEN_ACCESS, client, pWin->drawable.pScreen,
2580f7df2e56Smrg                  DixGetAttrAccess);
25814642e01fSmrg    if (rc != Success)
2582f7df2e56Smrg        return rc;
258305b261ecSmrg
25846747b715Smrg    preply = malloc(sizeof(xListInstalledColormapsReply) +
2585f7df2e56Smrg                    pWin->drawable.pScreen->maxInstalledCmaps *
2586f7df2e56Smrg                    sizeof(Colormap));
2587f7df2e56Smrg    if (!preply)
25886747b715Smrg        return BadAlloc;
258905b261ecSmrg
259005b261ecSmrg    preply->type = X_Reply;
259105b261ecSmrg    preply->sequenceNumber = client->sequence;
259205b261ecSmrg    nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps)
2593f7df2e56Smrg        (pWin->drawable.pScreen, (Colormap *) &preply[1]);
259405b261ecSmrg    preply->nColormaps = nummaps;
259505b261ecSmrg    preply->length = nummaps;
2596f7df2e56Smrg    WriteReplyToClient(client, sizeof(xListInstalledColormapsReply), preply);
259705b261ecSmrg    client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
259805b261ecSmrg    WriteSwappedDataToClient(client, nummaps * sizeof(Colormap), &preply[1]);
25996747b715Smrg    free(preply);
26006747b715Smrg    return Success;
260105b261ecSmrg}
260205b261ecSmrg
260305b261ecSmrgint
2604f7df2e56SmrgProcAllocColor(ClientPtr client)
260505b261ecSmrg{
260605b261ecSmrg    ColormapPtr pmap;
26074642e01fSmrg    int rc;
2608f7df2e56Smrg
260905b261ecSmrg    REQUEST(xAllocColorReq);
261005b261ecSmrg
261105b261ecSmrg    REQUEST_SIZE_MATCH(xAllocColorReq);
2612f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pmap, stuff->cmap, RT_COLORMAP,
2613f7df2e56Smrg                                 client, DixAddAccess);
2614f7df2e56Smrg    if (rc == Success) {
2615f7df2e56Smrg        xAllocColorReply acr = {
2616f7df2e56Smrg            .type = X_Reply,
2617f7df2e56Smrg            .sequenceNumber = client->sequence,
2618f7df2e56Smrg            .length = 0,
2619f7df2e56Smrg            .red = stuff->red,
2620f7df2e56Smrg            .green = stuff->green,
2621f7df2e56Smrg            .blue = stuff->blue,
2622f7df2e56Smrg            .pixel = 0
2623f7df2e56Smrg        };
2624f7df2e56Smrg        if ((rc = AllocColor(pmap, &acr.red, &acr.green, &acr.blue,
2625f7df2e56Smrg                             &acr.pixel, client->index)))
2626f7df2e56Smrg            return rc;
262705b261ecSmrg#ifdef PANORAMIX
2628f7df2e56Smrg        if (noPanoramiXExtension || !pmap->pScreen->myNum)
262905b261ecSmrg#endif
2630f7df2e56Smrg            WriteReplyToClient(client, sizeof(xAllocColorReply), &acr);
2631f7df2e56Smrg        return Success;
263205b261ecSmrg
263305b261ecSmrg    }
2634f7df2e56Smrg    else {
263505b261ecSmrg        client->errorValue = stuff->cmap;
26366747b715Smrg        return rc;
263705b261ecSmrg    }
263805b261ecSmrg}
263905b261ecSmrg
264005b261ecSmrgint
2641f7df2e56SmrgProcAllocNamedColor(ClientPtr client)
264205b261ecSmrg{
264305b261ecSmrg    ColormapPtr pcmp;
26444642e01fSmrg    int rc;
2645f7df2e56Smrg
264605b261ecSmrg    REQUEST(xAllocNamedColorReq);
264705b261ecSmrg
264805b261ecSmrg    REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes);
2649f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2650f7df2e56Smrg                                 client, DixAddAccess);
2651f7df2e56Smrg    if (rc == Success) {
2652f7df2e56Smrg        xAllocNamedColorReply ancr = {
2653f7df2e56Smrg            .type = X_Reply,
2654f7df2e56Smrg            .sequenceNumber = client->sequence,
2655f7df2e56Smrg            .length = 0
2656f7df2e56Smrg        };
2657f7df2e56Smrg        if (OsLookupColor
2658f7df2e56Smrg            (pcmp->pScreen->myNum, (char *) &stuff[1], stuff->nbytes,
2659f7df2e56Smrg             &ancr.exactRed, &ancr.exactGreen, &ancr.exactBlue)) {
2660f7df2e56Smrg            ancr.screenRed = ancr.exactRed;
2661f7df2e56Smrg            ancr.screenGreen = ancr.exactGreen;
2662f7df2e56Smrg            ancr.screenBlue = ancr.exactBlue;
2663f7df2e56Smrg            ancr.pixel = 0;
2664f7df2e56Smrg            if ((rc = AllocColor(pcmp,
2665f7df2e56Smrg                                 &ancr.screenRed, &ancr.screenGreen,
2666f7df2e56Smrg                                 &ancr.screenBlue, &ancr.pixel, client->index)))
2667f7df2e56Smrg                return rc;
266805b261ecSmrg#ifdef PANORAMIX
2669f7df2e56Smrg            if (noPanoramiXExtension || !pcmp->pScreen->myNum)
267005b261ecSmrg#endif
2671f7df2e56Smrg                WriteReplyToClient(client, sizeof(xAllocNamedColorReply),
2672f7df2e56Smrg                                   &ancr);
2673f7df2e56Smrg            return Success;
2674f7df2e56Smrg        }
2675f7df2e56Smrg        else
2676f7df2e56Smrg            return BadName;
2677f7df2e56Smrg
267805b261ecSmrg    }
2679f7df2e56Smrg    else {
268005b261ecSmrg        client->errorValue = stuff->cmap;
26816747b715Smrg        return rc;
268205b261ecSmrg    }
268305b261ecSmrg}
268405b261ecSmrg
268505b261ecSmrgint
2686f7df2e56SmrgProcAllocColorCells(ClientPtr client)
268705b261ecSmrg{
268805b261ecSmrg    ColormapPtr pcmp;
26894642e01fSmrg    int rc;
2690f7df2e56Smrg
269105b261ecSmrg    REQUEST(xAllocColorCellsReq);
269205b261ecSmrg
269305b261ecSmrg    REQUEST_SIZE_MATCH(xAllocColorCellsReq);
2694f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2695f7df2e56Smrg                                 client, DixAddAccess);
2696f7df2e56Smrg    if (rc == Success) {
2697f7df2e56Smrg        int npixels, nmasks;
2698f7df2e56Smrg        long length;
2699f7df2e56Smrg        Pixel *ppixels, *pmasks;
2700f7df2e56Smrg
2701f7df2e56Smrg        npixels = stuff->colors;
2702f7df2e56Smrg        if (!npixels) {
2703f7df2e56Smrg            client->errorValue = npixels;
2704f7df2e56Smrg            return BadValue;
2705f7df2e56Smrg        }
2706f7df2e56Smrg        if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) {
2707f7df2e56Smrg            client->errorValue = stuff->contiguous;
2708f7df2e56Smrg            return BadValue;
2709f7df2e56Smrg        }
2710f7df2e56Smrg        nmasks = stuff->planes;
2711f7df2e56Smrg        length = ((long) npixels + (long) nmasks) * sizeof(Pixel);
2712f7df2e56Smrg        ppixels = malloc(length);
2713f7df2e56Smrg        if (!ppixels)
27146747b715Smrg            return BadAlloc;
2715f7df2e56Smrg        pmasks = ppixels + npixels;
2716f7df2e56Smrg
2717f7df2e56Smrg        if ((rc = AllocColorCells(client->index, pcmp, npixels, nmasks,
2718f7df2e56Smrg                                  (Bool) stuff->contiguous, ppixels, pmasks))) {
2719f7df2e56Smrg            free(ppixels);
2720f7df2e56Smrg            return rc;
2721f7df2e56Smrg        }
272205b261ecSmrg#ifdef PANORAMIX
2723f7df2e56Smrg        if (noPanoramiXExtension || !pcmp->pScreen->myNum)
272405b261ecSmrg#endif
2725f7df2e56Smrg        {
2726f7df2e56Smrg            xAllocColorCellsReply accr = {
2727f7df2e56Smrg                .type = X_Reply,
2728f7df2e56Smrg                .sequenceNumber = client->sequence,
2729f7df2e56Smrg                .length = bytes_to_int32(length),
2730f7df2e56Smrg                .nPixels = npixels,
2731f7df2e56Smrg                .nMasks = nmasks
2732f7df2e56Smrg            };
2733f7df2e56Smrg            WriteReplyToClient(client, sizeof(xAllocColorCellsReply), &accr);
2734f7df2e56Smrg            client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
2735f7df2e56Smrg            WriteSwappedDataToClient(client, length, ppixels);
2736f7df2e56Smrg        }
2737f7df2e56Smrg        free(ppixels);
27386747b715Smrg        return Success;
273905b261ecSmrg    }
2740f7df2e56Smrg    else {
274105b261ecSmrg        client->errorValue = stuff->cmap;
27426747b715Smrg        return rc;
274305b261ecSmrg    }
274405b261ecSmrg}
274505b261ecSmrg
274605b261ecSmrgint
274705b261ecSmrgProcAllocColorPlanes(ClientPtr client)
274805b261ecSmrg{
274905b261ecSmrg    ColormapPtr pcmp;
27504642e01fSmrg    int rc;
2751f7df2e56Smrg
275205b261ecSmrg    REQUEST(xAllocColorPlanesReq);
275305b261ecSmrg
275405b261ecSmrg    REQUEST_SIZE_MATCH(xAllocColorPlanesReq);
2755f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2756f7df2e56Smrg                                 client, DixAddAccess);
2757f7df2e56Smrg    if (rc == Success) {
2758f7df2e56Smrg        xAllocColorPlanesReply acpr;
2759f7df2e56Smrg        int npixels;
2760f7df2e56Smrg        long length;
2761f7df2e56Smrg        Pixel *ppixels;
2762f7df2e56Smrg
2763f7df2e56Smrg        npixels = stuff->colors;
2764f7df2e56Smrg        if (!npixels) {
2765f7df2e56Smrg            client->errorValue = npixels;
2766f7df2e56Smrg            return BadValue;
2767f7df2e56Smrg        }
2768f7df2e56Smrg        if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) {
2769f7df2e56Smrg            client->errorValue = stuff->contiguous;
2770f7df2e56Smrg            return BadValue;
2771f7df2e56Smrg        }
2772f7df2e56Smrg        acpr = (xAllocColorPlanesReply) {
2773f7df2e56Smrg            .type = X_Reply,
2774f7df2e56Smrg            .sequenceNumber = client->sequence,
2775f7df2e56Smrg            .nPixels = npixels
2776f7df2e56Smrg        };
2777f7df2e56Smrg        length = (long) npixels *sizeof(Pixel);
2778f7df2e56Smrg
2779f7df2e56Smrg        ppixels = malloc(length);
2780f7df2e56Smrg        if (!ppixels)
27816747b715Smrg            return BadAlloc;
2782f7df2e56Smrg        if ((rc = AllocColorPlanes(client->index, pcmp, npixels,
2783f7df2e56Smrg                                   (int) stuff->red, (int) stuff->green,
2784f7df2e56Smrg                                   (int) stuff->blue, (Bool) stuff->contiguous,
2785f7df2e56Smrg                                   ppixels, &acpr.redMask, &acpr.greenMask,
2786f7df2e56Smrg                                   &acpr.blueMask))) {
27876747b715Smrg            free(ppixels);
2788f7df2e56Smrg            return rc;
2789f7df2e56Smrg        }
2790f7df2e56Smrg        acpr.length = bytes_to_int32(length);
279105b261ecSmrg#ifdef PANORAMIX
2792f7df2e56Smrg        if (noPanoramiXExtension || !pcmp->pScreen->myNum)
279305b261ecSmrg#endif
2794f7df2e56Smrg        {
2795f7df2e56Smrg            WriteReplyToClient(client, sizeof(xAllocColorPlanesReply), &acpr);
2796f7df2e56Smrg            client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
2797f7df2e56Smrg            WriteSwappedDataToClient(client, length, ppixels);
2798f7df2e56Smrg        }
2799f7df2e56Smrg        free(ppixels);
28006747b715Smrg        return Success;
280105b261ecSmrg    }
2802f7df2e56Smrg    else {
280305b261ecSmrg        client->errorValue = stuff->cmap;
28046747b715Smrg        return rc;
280505b261ecSmrg    }
280605b261ecSmrg}
280705b261ecSmrg
280805b261ecSmrgint
280905b261ecSmrgProcFreeColors(ClientPtr client)
281005b261ecSmrg{
281105b261ecSmrg    ColormapPtr pcmp;
28124642e01fSmrg    int rc;
2813f7df2e56Smrg
281405b261ecSmrg    REQUEST(xFreeColorsReq);
281505b261ecSmrg
281605b261ecSmrg    REQUEST_AT_LEAST_SIZE(xFreeColorsReq);
2817f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2818f7df2e56Smrg                                 client, DixRemoveAccess);
2819f7df2e56Smrg    if (rc == Success) {
2820f7df2e56Smrg        int count;
282105b261ecSmrg
2822f7df2e56Smrg        if (pcmp->flags & AllAllocated)
2823f7df2e56Smrg            return BadAccess;
2824f7df2e56Smrg        count = bytes_to_int32((client->req_len << 2) - sizeof(xFreeColorsReq));
2825f7df2e56Smrg        return FreeColors(pcmp, client->index, count,
2826f7df2e56Smrg                          (Pixel *) &stuff[1], (Pixel) stuff->planeMask);
282705b261ecSmrg    }
2828f7df2e56Smrg    else {
282905b261ecSmrg        client->errorValue = stuff->cmap;
28306747b715Smrg        return rc;
283105b261ecSmrg    }
283205b261ecSmrg}
283305b261ecSmrg
283405b261ecSmrgint
2835f7df2e56SmrgProcStoreColors(ClientPtr client)
283605b261ecSmrg{
283705b261ecSmrg    ColormapPtr pcmp;
28384642e01fSmrg    int rc;
2839f7df2e56Smrg
284005b261ecSmrg    REQUEST(xStoreColorsReq);
284105b261ecSmrg
284205b261ecSmrg    REQUEST_AT_LEAST_SIZE(xStoreColorsReq);
2843f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2844f7df2e56Smrg                                 client, DixWriteAccess);
2845f7df2e56Smrg    if (rc == Success) {
2846f7df2e56Smrg        int count;
284705b261ecSmrg
284805b261ecSmrg        count = (client->req_len << 2) - sizeof(xStoreColorsReq);
2849f7df2e56Smrg        if (count % sizeof(xColorItem))
2850f7df2e56Smrg            return BadLength;
2851f7df2e56Smrg        count /= sizeof(xColorItem);
2852f7df2e56Smrg        return StoreColors(pcmp, count, (xColorItem *) &stuff[1], client);
285305b261ecSmrg    }
2854f7df2e56Smrg    else {
285505b261ecSmrg        client->errorValue = stuff->cmap;
28566747b715Smrg        return rc;
285705b261ecSmrg    }
285805b261ecSmrg}
285905b261ecSmrg
286005b261ecSmrgint
2861f7df2e56SmrgProcStoreNamedColor(ClientPtr client)
286205b261ecSmrg{
286305b261ecSmrg    ColormapPtr pcmp;
28644642e01fSmrg    int rc;
2865f7df2e56Smrg
286605b261ecSmrg    REQUEST(xStoreNamedColorReq);
286705b261ecSmrg
286805b261ecSmrg    REQUEST_FIXED_SIZE(xStoreNamedColorReq, stuff->nbytes);
2869f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2870f7df2e56Smrg                                 client, DixWriteAccess);
2871f7df2e56Smrg    if (rc == Success) {
2872f7df2e56Smrg        xColorItem def;
2873f7df2e56Smrg
2874f7df2e56Smrg        if (OsLookupColor(pcmp->pScreen->myNum, (char *) &stuff[1],
2875f7df2e56Smrg                          stuff->nbytes, &def.red, &def.green, &def.blue)) {
2876f7df2e56Smrg            def.flags = stuff->flags;
2877f7df2e56Smrg            def.pixel = stuff->pixel;
2878f7df2e56Smrg            return StoreColors(pcmp, 1, &def, client);
2879f7df2e56Smrg        }
28806747b715Smrg        return BadName;
288105b261ecSmrg    }
2882f7df2e56Smrg    else {
288305b261ecSmrg        client->errorValue = stuff->cmap;
28846747b715Smrg        return rc;
288505b261ecSmrg    }
288605b261ecSmrg}
288705b261ecSmrg
288805b261ecSmrgint
288905b261ecSmrgProcQueryColors(ClientPtr client)
289005b261ecSmrg{
289105b261ecSmrg    ColormapPtr pcmp;
28924642e01fSmrg    int rc;
2893f7df2e56Smrg
289405b261ecSmrg    REQUEST(xQueryColorsReq);
289505b261ecSmrg
289605b261ecSmrg    REQUEST_AT_LEAST_SIZE(xQueryColorsReq);
2897f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2898f7df2e56Smrg                                 client, DixReadAccess);
2899f7df2e56Smrg    if (rc == Success) {
2900f7df2e56Smrg        int count;
2901f7df2e56Smrg        xrgb *prgbs;
2902f7df2e56Smrg        xQueryColorsReply qcr;
2903f7df2e56Smrg
2904f7df2e56Smrg        count =
2905f7df2e56Smrg            bytes_to_int32((client->req_len << 2) - sizeof(xQueryColorsReq));
2906f7df2e56Smrg        prgbs = calloc(count, sizeof(xrgb));
2907f7df2e56Smrg        if (!prgbs && count)
29086747b715Smrg            return BadAlloc;
2909f7df2e56Smrg        if ((rc =
2910f7df2e56Smrg             QueryColors(pcmp, count, (Pixel *) &stuff[1], prgbs, client))) {
2911f7df2e56Smrg            free(prgbs);
2912f7df2e56Smrg            return rc;
2913f7df2e56Smrg        }
2914f7df2e56Smrg        qcr = (xQueryColorsReply) {
2915f7df2e56Smrg            .type = X_Reply,
2916f7df2e56Smrg            .sequenceNumber = client->sequence,
2917f7df2e56Smrg            .length = bytes_to_int32(count * sizeof(xrgb)),
2918f7df2e56Smrg            .nColors = count
2919f7df2e56Smrg        };
2920f7df2e56Smrg        WriteReplyToClient(client, sizeof(xQueryColorsReply), &qcr);
2921f7df2e56Smrg        if (count) {
2922f7df2e56Smrg            client->pSwapReplyFunc = (ReplySwapPtr) SQColorsExtend;
2923f7df2e56Smrg            WriteSwappedDataToClient(client, count * sizeof(xrgb), prgbs);
2924f7df2e56Smrg        }
2925f7df2e56Smrg        free(prgbs);
2926f7df2e56Smrg        return Success;
2927f7df2e56Smrg
292805b261ecSmrg    }
2929f7df2e56Smrg    else {
293005b261ecSmrg        client->errorValue = stuff->cmap;
29316747b715Smrg        return rc;
293205b261ecSmrg    }
2933f7df2e56Smrg}
293405b261ecSmrg
293505b261ecSmrgint
293605b261ecSmrgProcLookupColor(ClientPtr client)
293705b261ecSmrg{
293805b261ecSmrg    ColormapPtr pcmp;
29394642e01fSmrg    int rc;
2940f7df2e56Smrg
294105b261ecSmrg    REQUEST(xLookupColorReq);
294205b261ecSmrg
294305b261ecSmrg    REQUEST_FIXED_SIZE(xLookupColorReq, stuff->nbytes);
2944f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2945f7df2e56Smrg                                 client, DixReadAccess);
2946f7df2e56Smrg    if (rc == Success) {
2947f7df2e56Smrg        CARD16 exactRed, exactGreen, exactBlue;
2948f7df2e56Smrg
2949f7df2e56Smrg        if (OsLookupColor
2950f7df2e56Smrg            (pcmp->pScreen->myNum, (char *) &stuff[1], stuff->nbytes,
2951f7df2e56Smrg             &exactRed, &exactGreen, &exactBlue)) {
2952f7df2e56Smrg            xLookupColorReply lcr = {
2953f7df2e56Smrg                .type = X_Reply,
2954f7df2e56Smrg                .sequenceNumber = client->sequence,
2955f7df2e56Smrg                .length = 0,
2956f7df2e56Smrg                .exactRed = exactRed,
2957f7df2e56Smrg                .exactGreen = exactGreen,
2958f7df2e56Smrg                .exactBlue = exactBlue,
2959f7df2e56Smrg                .screenRed = exactRed,
2960f7df2e56Smrg                .screenGreen = exactGreen,
2961f7df2e56Smrg                .screenBlue = exactBlue
2962f7df2e56Smrg            };
2963f7df2e56Smrg            (*pcmp->pScreen->ResolveColor) (&lcr.screenRed,
2964f7df2e56Smrg                                            &lcr.screenGreen,
2965f7df2e56Smrg                                            &lcr.screenBlue, pcmp->pVisual);
2966f7df2e56Smrg            WriteReplyToClient(client, sizeof(xLookupColorReply), &lcr);
2967f7df2e56Smrg            return Success;
2968f7df2e56Smrg        }
29696747b715Smrg        return BadName;
297005b261ecSmrg    }
2971f7df2e56Smrg    else {
297205b261ecSmrg        client->errorValue = stuff->cmap;
29736747b715Smrg        return rc;
297405b261ecSmrg    }
297505b261ecSmrg}
297605b261ecSmrg
297705b261ecSmrgint
2978f7df2e56SmrgProcCreateCursor(ClientPtr client)
297905b261ecSmrg{
2980f7df2e56Smrg    CursorPtr pCursor;
2981f7df2e56Smrg    PixmapPtr src;
2982f7df2e56Smrg    PixmapPtr msk;
2983f7df2e56Smrg    unsigned char *srcbits;
2984f7df2e56Smrg    unsigned char *mskbits;
2985f7df2e56Smrg    unsigned short width, height;
2986f7df2e56Smrg    long n;
2987f7df2e56Smrg    CursorMetricRec cm;
29884642e01fSmrg    int rc;
298905b261ecSmrg
299005b261ecSmrg    REQUEST(xCreateCursorReq);
299105b261ecSmrg
299205b261ecSmrg    REQUEST_SIZE_MATCH(xCreateCursorReq);
299305b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->cid, client);
299405b261ecSmrg
2995f7df2e56Smrg    rc = dixLookupResourceByType((void **) &src, stuff->source, RT_PIXMAP,
2996f7df2e56Smrg                                 client, DixReadAccess);
29974642e01fSmrg    if (rc != Success) {
2998f7df2e56Smrg        client->errorValue = stuff->source;
2999f7df2e56Smrg        return rc;
300005b261ecSmrg    }
30014642e01fSmrg
3002f7df2e56Smrg    if (src->drawable.depth != 1)
3003f7df2e56Smrg        return (BadMatch);
3004f7df2e56Smrg
3005f7df2e56Smrg    /* Find and validate cursor mask pixmap, if one is provided */
3006f7df2e56Smrg    if (stuff->mask != None) {
3007f7df2e56Smrg        rc = dixLookupResourceByType((void **) &msk, stuff->mask, RT_PIXMAP,
3008f7df2e56Smrg                                     client, DixReadAccess);
3009f7df2e56Smrg        if (rc != Success) {
3010f7df2e56Smrg            client->errorValue = stuff->mask;
3011f7df2e56Smrg            return rc;
3012f7df2e56Smrg        }
3013f7df2e56Smrg
3014f7df2e56Smrg        if (src->drawable.width != msk->drawable.width
3015f7df2e56Smrg            || src->drawable.height != msk->drawable.height
3016f7df2e56Smrg            || src->drawable.depth != 1 || msk->drawable.depth != 1)
3017f7df2e56Smrg            return BadMatch;
3018f7df2e56Smrg    }
3019f7df2e56Smrg    else
3020f7df2e56Smrg        msk = NULL;
302105b261ecSmrg
302205b261ecSmrg    width = src->drawable.width;
302305b261ecSmrg    height = src->drawable.height;
302405b261ecSmrg
3025f7df2e56Smrg    if (stuff->x > width || stuff->y > height)
3026f7df2e56Smrg        return BadMatch;
302705b261ecSmrg
3028f7df2e56Smrg    srcbits = calloc(BitmapBytePad(width), height);
302905b261ecSmrg    if (!srcbits)
3030f7df2e56Smrg        return BadAlloc;
3031f7df2e56Smrg    n = BitmapBytePad(width) * height;
30326747b715Smrg    mskbits = malloc(n);
3033f7df2e56Smrg    if (!mskbits) {
3034f7df2e56Smrg        free(srcbits);
3035f7df2e56Smrg        return BadAlloc;
303605b261ecSmrg    }
303705b261ecSmrg
3038f7df2e56Smrg    (*src->drawable.pScreen->GetImage) ((DrawablePtr) src, 0, 0, width, height,
3039f7df2e56Smrg                                        XYPixmap, 1, (void *) srcbits);
3040f7df2e56Smrg    if (msk == (PixmapPtr) NULL) {
3041f7df2e56Smrg        unsigned char *bits = mskbits;
3042f7df2e56Smrg
3043f7df2e56Smrg        while (--n >= 0)
3044f7df2e56Smrg            *bits++ = ~0;
304505b261ecSmrg    }
3046f7df2e56Smrg    else {
3047f7df2e56Smrg        /* zeroing the (pad) bits helps some ddx cursor handling */
3048f7df2e56Smrg        memset((char *) mskbits, 0, n);
3049f7df2e56Smrg        (*msk->drawable.pScreen->GetImage) ((DrawablePtr) msk, 0, 0, width,
3050f7df2e56Smrg                                            height, XYPixmap, 1,
3051f7df2e56Smrg                                            (void *) mskbits);
305205b261ecSmrg    }
305305b261ecSmrg    cm.width = width;
305405b261ecSmrg    cm.height = height;
305505b261ecSmrg    cm.xhot = stuff->x;
305605b261ecSmrg    cm.yhot = stuff->y;
30574642e01fSmrg    rc = AllocARGBCursor(srcbits, mskbits, NULL, &cm,
3058f7df2e56Smrg                         stuff->foreRed, stuff->foreGreen, stuff->foreBlue,
3059f7df2e56Smrg                         stuff->backRed, stuff->backGreen, stuff->backBlue,
3060f7df2e56Smrg                         &pCursor, client, stuff->cid);
306105b261ecSmrg
30624642e01fSmrg    if (rc != Success)
3063f7df2e56Smrg        goto bail;
3064f7df2e56Smrg    if (!AddResource(stuff->cid, RT_CURSOR, (void *) pCursor)) {
3065f7df2e56Smrg        rc = BadAlloc;
3066f7df2e56Smrg        goto bail;
3067f7df2e56Smrg    }
30684642e01fSmrg
30696747b715Smrg    return Success;
3070f7df2e56Smrg bail:
3071f7df2e56Smrg    free(srcbits);
3072f7df2e56Smrg    free(mskbits);
3073f7df2e56Smrg    return rc;
307405b261ecSmrg}
307505b261ecSmrg
307605b261ecSmrgint
3077f7df2e56SmrgProcCreateGlyphCursor(ClientPtr client)
307805b261ecSmrg{
307905b261ecSmrg    CursorPtr pCursor;
308005b261ecSmrg    int res;
308105b261ecSmrg
308205b261ecSmrg    REQUEST(xCreateGlyphCursorReq);
308305b261ecSmrg
308405b261ecSmrg    REQUEST_SIZE_MATCH(xCreateGlyphCursorReq);
308505b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->cid, client);
308605b261ecSmrg
308705b261ecSmrg    res = AllocGlyphCursor(stuff->source, stuff->sourceChar,
3088f7df2e56Smrg                           stuff->mask, stuff->maskChar,
3089f7df2e56Smrg                           stuff->foreRed, stuff->foreGreen, stuff->foreBlue,
3090f7df2e56Smrg                           stuff->backRed, stuff->backGreen, stuff->backBlue,
3091f7df2e56Smrg                           &pCursor, client, stuff->cid);
309205b261ecSmrg    if (res != Success)
3093f7df2e56Smrg        return res;
3094f7df2e56Smrg    if (AddResource(stuff->cid, RT_CURSOR, (void *) pCursor))
3095f7df2e56Smrg        return Success;
309605b261ecSmrg    return BadAlloc;
309705b261ecSmrg}
309805b261ecSmrg
309905b261ecSmrgint
3100f7df2e56SmrgProcFreeCursor(ClientPtr client)
310105b261ecSmrg{
310205b261ecSmrg    CursorPtr pCursor;
31034642e01fSmrg    int rc;
3104f7df2e56Smrg
310505b261ecSmrg    REQUEST(xResourceReq);
310605b261ecSmrg
310705b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
3108f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pCursor, stuff->id, RT_CURSOR,
3109f7df2e56Smrg                                 client, DixDestroyAccess);
3110f7df2e56Smrg    if (rc == Success) {
3111d566a54bSmrg        if (pCursor == rootCursor) {
3112d566a54bSmrg            client->errorValue = stuff->id;
3113d566a54bSmrg            return BadCursor;
3114d566a54bSmrg        }
3115f7df2e56Smrg        FreeResource(stuff->id, RT_NONE);
3116f7df2e56Smrg        return Success;
311705b261ecSmrg    }
3118f7df2e56Smrg    else {
3119f7df2e56Smrg        client->errorValue = stuff->id;
3120f7df2e56Smrg        return rc;
312105b261ecSmrg    }
312205b261ecSmrg}
312305b261ecSmrg
312405b261ecSmrgint
3125f7df2e56SmrgProcQueryBestSize(ClientPtr client)
312605b261ecSmrg{
3127f7df2e56Smrg    xQueryBestSizeReply reply;
312805b261ecSmrg    DrawablePtr pDraw;
312905b261ecSmrg    ScreenPtr pScreen;
313005b261ecSmrg    int rc;
3131f7df2e56Smrg
313205b261ecSmrg    REQUEST(xQueryBestSizeReq);
313305b261ecSmrg    REQUEST_SIZE_MATCH(xQueryBestSizeReq);
313405b261ecSmrg
3135f7df2e56Smrg    if ((stuff->class != CursorShape) &&
3136f7df2e56Smrg        (stuff->class != TileShape) && (stuff->class != StippleShape)) {
3137f7df2e56Smrg        client->errorValue = stuff->class;
31386747b715Smrg        return BadValue;
313905b261ecSmrg    }
314005b261ecSmrg
314105b261ecSmrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
3142f7df2e56Smrg                           DixGetAttrAccess);
314305b261ecSmrg    if (rc != Success)
3144f7df2e56Smrg        return rc;
314505b261ecSmrg    if (stuff->class != CursorShape && pDraw->type == UNDRAWABLE_WINDOW)
3146f7df2e56Smrg        return BadMatch;
314705b261ecSmrg    pScreen = pDraw->pScreen;
31484642e01fSmrg    rc = XaceHook(XACE_SCREEN_ACCESS, client, pScreen, DixGetAttrAccess);
31494642e01fSmrg    if (rc != Success)
3150f7df2e56Smrg        return rc;
3151f7df2e56Smrg    (*pScreen->QueryBestSize) (stuff->class, &stuff->width,
3152f7df2e56Smrg                               &stuff->height, pScreen);
3153f7df2e56Smrg    reply = (xQueryBestSizeReply) {
3154f7df2e56Smrg        .type = X_Reply,
3155f7df2e56Smrg        .sequenceNumber = client->sequence,
3156f7df2e56Smrg        .length = 0,
3157f7df2e56Smrg        .width = stuff->width,
3158f7df2e56Smrg        .height = stuff->height
3159f7df2e56Smrg    };
316005b261ecSmrg    WriteReplyToClient(client, sizeof(xQueryBestSizeReply), &reply);
31616747b715Smrg    return Success;
316205b261ecSmrg}
316305b261ecSmrg
316405b261ecSmrgint
3165f7df2e56SmrgProcSetScreenSaver(ClientPtr client)
316605b261ecSmrg{
31674642e01fSmrg    int rc, i, blankingOption, exposureOption;
3168f7df2e56Smrg
316905b261ecSmrg    REQUEST(xSetScreenSaverReq);
317005b261ecSmrg    REQUEST_SIZE_MATCH(xSetScreenSaverReq);
31714642e01fSmrg
31724642e01fSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
3173f7df2e56Smrg        rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i],
3174f7df2e56Smrg                      DixSetAttrAccess);
3175f7df2e56Smrg        if (rc != Success)
3176f7df2e56Smrg            return rc;
31774642e01fSmrg    }
31784642e01fSmrg
317905b261ecSmrg    blankingOption = stuff->preferBlank;
318005b261ecSmrg    if ((blankingOption != DontPreferBlanking) &&
318105b261ecSmrg        (blankingOption != PreferBlanking) &&
3182f7df2e56Smrg        (blankingOption != DefaultBlanking)) {
3183f7df2e56Smrg        client->errorValue = blankingOption;
318405b261ecSmrg        return BadValue;
318505b261ecSmrg    }
318605b261ecSmrg    exposureOption = stuff->allowExpose;
318705b261ecSmrg    if ((exposureOption != DontAllowExposures) &&
318805b261ecSmrg        (exposureOption != AllowExposures) &&
3189f7df2e56Smrg        (exposureOption != DefaultExposures)) {
3190f7df2e56Smrg        client->errorValue = exposureOption;
319105b261ecSmrg        return BadValue;
319205b261ecSmrg    }
3193f7df2e56Smrg    if (stuff->timeout < -1) {
3194f7df2e56Smrg        client->errorValue = stuff->timeout;
319505b261ecSmrg        return BadValue;
319605b261ecSmrg    }
3197f7df2e56Smrg    if (stuff->interval < -1) {
3198f7df2e56Smrg        client->errorValue = stuff->interval;
319905b261ecSmrg        return BadValue;
320005b261ecSmrg    }
320105b261ecSmrg
320205b261ecSmrg    if (blankingOption == DefaultBlanking)
3203f7df2e56Smrg        ScreenSaverBlanking = defaultScreenSaverBlanking;
320405b261ecSmrg    else
3205f7df2e56Smrg        ScreenSaverBlanking = blankingOption;
320605b261ecSmrg    if (exposureOption == DefaultExposures)
3207f7df2e56Smrg        ScreenSaverAllowExposures = defaultScreenSaverAllowExposures;
320805b261ecSmrg    else
3209f7df2e56Smrg        ScreenSaverAllowExposures = exposureOption;
321005b261ecSmrg
321105b261ecSmrg    if (stuff->timeout >= 0)
3212f7df2e56Smrg        ScreenSaverTime = stuff->timeout * MILLI_PER_SECOND;
3213f7df2e56Smrg    else
3214f7df2e56Smrg        ScreenSaverTime = defaultScreenSaverTime;
321505b261ecSmrg    if (stuff->interval >= 0)
3216f7df2e56Smrg        ScreenSaverInterval = stuff->interval * MILLI_PER_SECOND;
321705b261ecSmrg    else
3218f7df2e56Smrg        ScreenSaverInterval = defaultScreenSaverInterval;
321905b261ecSmrg
322005b261ecSmrg    SetScreenSaverTimer();
32216747b715Smrg    return Success;
322205b261ecSmrg}
322305b261ecSmrg
322405b261ecSmrgint
322505b261ecSmrgProcGetScreenSaver(ClientPtr client)
322605b261ecSmrg{
322705b261ecSmrg    xGetScreenSaverReply rep;
32284642e01fSmrg    int rc, i;
3229f7df2e56Smrg
323005b261ecSmrg    REQUEST_SIZE_MATCH(xReq);
32314642e01fSmrg
32324642e01fSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
3233f7df2e56Smrg        rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i],
3234f7df2e56Smrg                      DixGetAttrAccess);
3235f7df2e56Smrg        if (rc != Success)
3236f7df2e56Smrg            return rc;
3237f7df2e56Smrg    }
3238f7df2e56Smrg
3239f7df2e56Smrg    rep = (xGetScreenSaverReply) {
3240f7df2e56Smrg        .type = X_Reply,
3241f7df2e56Smrg        .sequenceNumber = client->sequence,
3242f7df2e56Smrg        .length = 0,
3243f7df2e56Smrg        .timeout = ScreenSaverTime / MILLI_PER_SECOND,
3244f7df2e56Smrg        .interval = ScreenSaverInterval / MILLI_PER_SECOND,
3245f7df2e56Smrg        .preferBlanking = ScreenSaverBlanking,
3246f7df2e56Smrg        .allowExposures = ScreenSaverAllowExposures
3247f7df2e56Smrg    };
324805b261ecSmrg    WriteReplyToClient(client, sizeof(xGetScreenSaverReply), &rep);
32496747b715Smrg    return Success;
325005b261ecSmrg}
325105b261ecSmrg
325205b261ecSmrgint
325305b261ecSmrgProcChangeHosts(ClientPtr client)
325405b261ecSmrg{
325505b261ecSmrg    REQUEST(xChangeHostsReq);
325605b261ecSmrg
325705b261ecSmrg    REQUEST_FIXED_SIZE(xChangeHostsReq, stuff->hostLength);
325805b261ecSmrg
3259f7df2e56Smrg    if (stuff->mode == HostInsert)
3260f7df2e56Smrg        return AddHost(client, (int) stuff->hostFamily,
3261f7df2e56Smrg                       stuff->hostLength, (void *) &stuff[1]);
32626747b715Smrg    if (stuff->mode == HostDelete)
3263f7df2e56Smrg        return RemoveHost(client, (int) stuff->hostFamily,
3264f7df2e56Smrg                          stuff->hostLength, (void *) &stuff[1]);
32656747b715Smrg    client->errorValue = stuff->mode;
32666747b715Smrg    return BadValue;
326705b261ecSmrg}
326805b261ecSmrg
326905b261ecSmrgint
327005b261ecSmrgProcListHosts(ClientPtr client)
327105b261ecSmrg{
327205b261ecSmrg    xListHostsReply reply;
3273f7df2e56Smrg    int len, nHosts, result;
3274f7df2e56Smrg    BOOL enabled;
3275f7df2e56Smrg    void *pdata;
3276f7df2e56Smrg
327705b261ecSmrg    /* REQUEST(xListHostsReq); */
327805b261ecSmrg
327905b261ecSmrg    REQUEST_SIZE_MATCH(xListHostsReq);
328005b261ecSmrg
328105b261ecSmrg    /* untrusted clients can't list hosts */
32824642e01fSmrg    result = XaceHook(XACE_SERVER_ACCESS, client, DixReadAccess);
32834642e01fSmrg    if (result != Success)
3284f7df2e56Smrg        return result;
328505b261ecSmrg
3286f7df2e56Smrg    result = GetHosts(&pdata, &nHosts, &len, &enabled);
328705b261ecSmrg    if (result != Success)
3288f7df2e56Smrg        return result;
3289f7df2e56Smrg
3290f7df2e56Smrg    reply = (xListHostsReply) {
3291f7df2e56Smrg        .type = X_Reply,
3292f7df2e56Smrg        .enabled = enabled,
3293f7df2e56Smrg        .sequenceNumber = client->sequence,
3294f7df2e56Smrg        .length = bytes_to_int32(len),
3295f7df2e56Smrg        .nHosts = nHosts
3296f7df2e56Smrg    };
329705b261ecSmrg    WriteReplyToClient(client, sizeof(xListHostsReply), &reply);
3298f7df2e56Smrg    if (nHosts) {
3299f7df2e56Smrg        client->pSwapReplyFunc = (ReplySwapPtr) SLHostsExtend;
3300f7df2e56Smrg        WriteSwappedDataToClient(client, len, pdata);
330105b261ecSmrg    }
33026747b715Smrg    free(pdata);
33036747b715Smrg    return Success;
330405b261ecSmrg}
330505b261ecSmrg
330605b261ecSmrgint
330705b261ecSmrgProcChangeAccessControl(ClientPtr client)
330805b261ecSmrg{
330905b261ecSmrg    REQUEST(xSetAccessControlReq);
331005b261ecSmrg
331105b261ecSmrg    REQUEST_SIZE_MATCH(xSetAccessControlReq);
3312f7df2e56Smrg    if ((stuff->mode != EnableAccess) && (stuff->mode != DisableAccess)) {
3313f7df2e56Smrg        client->errorValue = stuff->mode;
331405b261ecSmrg        return BadValue;
331505b261ecSmrg    }
33166747b715Smrg    return ChangeAccessControl(client, stuff->mode == EnableAccess);
331705b261ecSmrg}
331805b261ecSmrg
331905b261ecSmrg/*********************
332005b261ecSmrg * CloseDownRetainedResources
332105b261ecSmrg *
3322f7df2e56Smrg *    Find all clients that are gone and have terminated in RetainTemporary
332305b261ecSmrg *    and destroy their resources.
332405b261ecSmrg *********************/
332505b261ecSmrg
332605b261ecSmrgstatic void
332705b261ecSmrgCloseDownRetainedResources(void)
332805b261ecSmrg{
332905b261ecSmrg    int i;
333005b261ecSmrg    ClientPtr client;
333105b261ecSmrg
3332f7df2e56Smrg    for (i = 1; i < currentMaxClients; i++) {
333305b261ecSmrg        client = clients[i];
333405b261ecSmrg        if (client && (client->closeDownMode == RetainTemporary)
3335f7df2e56Smrg            && (client->clientGone))
3336f7df2e56Smrg            CloseDownClient(client);
333705b261ecSmrg    }
333805b261ecSmrg}
333905b261ecSmrg
334005b261ecSmrgint
334105b261ecSmrgProcKillClient(ClientPtr client)
334205b261ecSmrg{
334305b261ecSmrg    REQUEST(xResourceReq);
334405b261ecSmrg    ClientPtr killclient;
334505b261ecSmrg    int rc;
334605b261ecSmrg
334705b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
3348f7df2e56Smrg    if (stuff->id == AllTemporary) {
3349f7df2e56Smrg        CloseDownRetainedResources();
33506747b715Smrg        return Success;
335105b261ecSmrg    }
335205b261ecSmrg
335305b261ecSmrg    rc = dixLookupClient(&killclient, stuff->id, client, DixDestroyAccess);
335405b261ecSmrg    if (rc == Success) {
3355f7df2e56Smrg        CloseDownClient(killclient);
3356f7df2e56Smrg        if (client == killclient) {
3357f7df2e56Smrg            /* force yield and return Success, so that Dispatch()
3358f7df2e56Smrg             * doesn't try to touch client
3359f7df2e56Smrg             */
3360f7df2e56Smrg            isItTimeToYield = TRUE;
3361f7df2e56Smrg        }
3362f7df2e56Smrg        return Success;
336305b261ecSmrg    }
336405b261ecSmrg    else
3365f7df2e56Smrg        return rc;
336605b261ecSmrg}
336705b261ecSmrg
336805b261ecSmrgint
336905b261ecSmrgProcSetFontPath(ClientPtr client)
337005b261ecSmrg{
337105b261ecSmrg    unsigned char *ptr;
337205b261ecSmrg    unsigned long nbytes, total;
337305b261ecSmrg    long nfonts;
33746747b715Smrg    int n;
3375f7df2e56Smrg
337605b261ecSmrg    REQUEST(xSetFontPathReq);
3377f7df2e56Smrg
337805b261ecSmrg    REQUEST_AT_LEAST_SIZE(xSetFontPathReq);
3379f7df2e56Smrg
338005b261ecSmrg    nbytes = (client->req_len << 2) - sizeof(xSetFontPathReq);
338105b261ecSmrg    total = nbytes;
3382f7df2e56Smrg    ptr = (unsigned char *) &stuff[1];
338305b261ecSmrg    nfonts = stuff->nFonts;
3384f7df2e56Smrg    while (--nfonts >= 0) {
3385f7df2e56Smrg        if ((total == 0) || (total < (n = (*ptr + 1))))
3386f7df2e56Smrg            return BadLength;
3387f7df2e56Smrg        total -= n;
3388f7df2e56Smrg        ptr += n;
338905b261ecSmrg    }
339005b261ecSmrg    if (total >= 4)
3391f7df2e56Smrg        return BadLength;
3392f7df2e56Smrg    return SetFontPath(client, stuff->nFonts, (unsigned char *) &stuff[1]);
339305b261ecSmrg}
339405b261ecSmrg
339505b261ecSmrgint
339605b261ecSmrgProcGetFontPath(ClientPtr client)
339705b261ecSmrg{
339805b261ecSmrg    xGetFontPathReply reply;
33994642e01fSmrg    int rc, stringLens, numpaths;
340005b261ecSmrg    unsigned char *bufferStart;
3401f7df2e56Smrg
340205b261ecSmrg    /* REQUEST (xReq); */
340305b261ecSmrg
340405b261ecSmrg    REQUEST_SIZE_MATCH(xReq);
34054642e01fSmrg    rc = GetFontPath(client, &numpaths, &stringLens, &bufferStart);
34064642e01fSmrg    if (rc != Success)
3407f7df2e56Smrg        return rc;
340805b261ecSmrg
3409f7df2e56Smrg    reply = (xGetFontPathReply) {
3410f7df2e56Smrg        .type = X_Reply,
3411f7df2e56Smrg        .sequenceNumber = client->sequence,
3412f7df2e56Smrg        .length = bytes_to_int32(stringLens + numpaths),
3413f7df2e56Smrg        .nPaths = numpaths
3414f7df2e56Smrg    };
341505b261ecSmrg
341605b261ecSmrg    WriteReplyToClient(client, sizeof(xGetFontPathReply), &reply);
341705b261ecSmrg    if (stringLens || numpaths)
3418f7df2e56Smrg        WriteToClient(client, stringLens + numpaths, bufferStart);
34196747b715Smrg    return Success;
342005b261ecSmrg}
342105b261ecSmrg
342205b261ecSmrgint
342305b261ecSmrgProcChangeCloseDownMode(ClientPtr client)
342405b261ecSmrg{
34254642e01fSmrg    int rc;
3426f7df2e56Smrg
342705b261ecSmrg    REQUEST(xSetCloseDownModeReq);
342805b261ecSmrg    REQUEST_SIZE_MATCH(xSetCloseDownModeReq);
34294642e01fSmrg
34304642e01fSmrg    rc = XaceHook(XACE_CLIENT_ACCESS, client, client, DixManageAccess);
34314642e01fSmrg    if (rc != Success)
3432f7df2e56Smrg        return rc;
34334642e01fSmrg
343405b261ecSmrg    if ((stuff->mode == AllTemporary) ||
3435f7df2e56Smrg        (stuff->mode == RetainPermanent) || (stuff->mode == RetainTemporary)) {
3436f7df2e56Smrg        client->closeDownMode = stuff->mode;
3437f7df2e56Smrg        return Success;
343805b261ecSmrg    }
3439f7df2e56Smrg    else {
3440f7df2e56Smrg        client->errorValue = stuff->mode;
3441f7df2e56Smrg        return BadValue;
344205b261ecSmrg    }
344305b261ecSmrg}
344405b261ecSmrg
3445f7df2e56Smrgint
3446f7df2e56SmrgProcForceScreenSaver(ClientPtr client)
3447f7df2e56Smrg{
34484642e01fSmrg    int rc;
3449f7df2e56Smrg
345005b261ecSmrg    REQUEST(xForceScreenSaverReq);
345105b261ecSmrg
345205b261ecSmrg    REQUEST_SIZE_MATCH(xForceScreenSaverReq);
3453f7df2e56Smrg
3454f7df2e56Smrg    if ((stuff->mode != ScreenSaverReset) && (stuff->mode != ScreenSaverActive)) {
3455f7df2e56Smrg        client->errorValue = stuff->mode;
345605b261ecSmrg        return BadValue;
345705b261ecSmrg    }
3458f7df2e56Smrg    rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, (int) stuff->mode);
34594642e01fSmrg    if (rc != Success)
3460f7df2e56Smrg        return rc;
34616747b715Smrg    return Success;
346205b261ecSmrg}
346305b261ecSmrg
3464f7df2e56Smrgint
3465f7df2e56SmrgProcNoOperation(ClientPtr client)
346605b261ecSmrg{
346705b261ecSmrg    REQUEST_AT_LEAST_SIZE(xReq);
3468f7df2e56Smrg
346905b261ecSmrg    /* noop -- don't do anything */
34706747b715Smrg    return Success;
347105b261ecSmrg}
347205b261ecSmrg
347305b261ecSmrg/**********************
347405b261ecSmrg * CloseDownClient
347505b261ecSmrg *
347605b261ecSmrg *  Client can either mark his resources destroy or retain.  If retained and
347705b261ecSmrg *  then killed again, the client is really destroyed.
347805b261ecSmrg *********************/
347905b261ecSmrg
348005b261ecSmrgchar dispatchExceptionAtReset = DE_RESET;
34815a112b11Smrgint terminateDelay = 0;
348205b261ecSmrg
348305b261ecSmrgvoid
348405b261ecSmrgCloseDownClient(ClientPtr client)
348505b261ecSmrg{
348605b261ecSmrg    Bool really_close_down = client->clientGone ||
3487f7df2e56Smrg        client->closeDownMode == DestroyAll;
348805b261ecSmrg
3489f7df2e56Smrg    if (!client->clientGone) {
3490f7df2e56Smrg        /* ungrab server if grabbing client dies */
3491f7df2e56Smrg        if (grabState != GrabNone && grabClient == client) {
3492f7df2e56Smrg            UngrabServer(client);
3493f7df2e56Smrg        }
3494f7df2e56Smrg        BITCLEAR(grabWaiters, client->index);
3495f7df2e56Smrg        DeleteClientFromAnySelections(client);
3496f7df2e56Smrg        ReleaseActiveGrabs(client);
3497f7df2e56Smrg        DeleteClientFontStuff(client);
3498f7df2e56Smrg        if (!really_close_down) {
3499f7df2e56Smrg            /*  This frees resources that should never be retained
3500f7df2e56Smrg             *  no matter what the close down mode is.  Actually we
3501f7df2e56Smrg             *  could do this unconditionally, but it's probably
3502f7df2e56Smrg             *  better not to traverse all the client's resources
3503f7df2e56Smrg             *  twice (once here, once a few lines down in
3504f7df2e56Smrg             *  FreeClientResources) in the common case of
3505f7df2e56Smrg             *  really_close_down == TRUE.
3506f7df2e56Smrg             */
3507f7df2e56Smrg            FreeClientNeverRetainResources(client);
3508f7df2e56Smrg            client->clientState = ClientStateRetained;
3509f7df2e56Smrg            if (ClientStateCallback) {
3510f7df2e56Smrg                NewClientInfoRec clientinfo;
3511f7df2e56Smrg
3512f7df2e56Smrg                clientinfo.client = client;
3513f7df2e56Smrg                clientinfo.prefix = (xConnSetupPrefix *) NULL;
3514f7df2e56Smrg                clientinfo.setup = (xConnSetup *) NULL;
3515f7df2e56Smrg                CallCallbacks((&ClientStateCallback), (void *) &clientinfo);
3516f7df2e56Smrg            }
3517f7df2e56Smrg        }
3518f7df2e56Smrg        client->clientGone = TRUE;      /* so events aren't sent to client */
3519f7df2e56Smrg        if (ClientIsAsleep(client))
3520f7df2e56Smrg            ClientSignal(client);
3521f7df2e56Smrg        ProcessWorkQueueZombies();
3522f7df2e56Smrg        CloseDownConnection(client);
35237e31ba66Smrg        output_pending_clear(client);
35247e31ba66Smrg        mark_client_not_ready(client);
3525f7df2e56Smrg
3526f7df2e56Smrg        /* If the client made it to the Running stage, nClients has
3527f7df2e56Smrg         * been incremented on its behalf, so we need to decrement it
3528f7df2e56Smrg         * now.  If it hasn't gotten to Running, nClients has *not*
3529f7df2e56Smrg         * been incremented, so *don't* decrement it.
3530f7df2e56Smrg         */
3531f7df2e56Smrg        if (client->clientState != ClientStateInitial) {
3532f7df2e56Smrg            --nClients;
3533f7df2e56Smrg        }
3534f7df2e56Smrg    }
3535f7df2e56Smrg
3536f7df2e56Smrg    if (really_close_down) {
3537f7df2e56Smrg        if (client->clientState == ClientStateRunning && nClients == 0)
35385a112b11Smrg            SetDispatchExceptionTimer();
3539f7df2e56Smrg
3540f7df2e56Smrg        client->clientState = ClientStateGone;
3541f7df2e56Smrg        if (ClientStateCallback) {
3542f7df2e56Smrg            NewClientInfoRec clientinfo;
3543f7df2e56Smrg
3544f7df2e56Smrg            clientinfo.client = client;
3545f7df2e56Smrg            clientinfo.prefix = (xConnSetupPrefix *) NULL;
3546f7df2e56Smrg            clientinfo.setup = (xConnSetup *) NULL;
3547f7df2e56Smrg            CallCallbacks((&ClientStateCallback), (void *) &clientinfo);
3548f7df2e56Smrg        }
3549f7df2e56Smrg        TouchListenerGone(client->clientAsMask);
35505a112b11Smrg        GestureListenerGone(client->clientAsMask);
3551f7df2e56Smrg        FreeClientResources(client);
3552f7df2e56Smrg        /* Disable client ID tracking. This must be done after
3553f7df2e56Smrg         * ClientStateCallback. */
3554f7df2e56Smrg        ReleaseClientIds(client);
355505b261ecSmrg#ifdef XSERVER_DTRACE
3556f7df2e56Smrg        XSERVER_CLIENT_DISCONNECT(client->index);
3557f7df2e56Smrg#endif
3558f7df2e56Smrg        if (client->index < nextFreeClientID)
3559f7df2e56Smrg            nextFreeClientID = client->index;
3560f7df2e56Smrg        clients[client->index] = NullClient;
3561f7df2e56Smrg        SmartLastClient = NullClient;
3562f7df2e56Smrg        dixFreeObjectWithPrivates(client, PRIVATE_CLIENT);
356305b261ecSmrg
3564f7df2e56Smrg        while (!clients[currentMaxClients - 1])
3565f7df2e56Smrg            currentMaxClients--;
356605b261ecSmrg    }
35675a112b11Smrg
35685a112b11Smrg    if (ShouldDisconnectRemainingClients())
35695a112b11Smrg        SetDispatchExceptionTimer();
357005b261ecSmrg}
357105b261ecSmrg
357205b261ecSmrgstatic void
357305b261ecSmrgKillAllClients(void)
357405b261ecSmrg{
357505b261ecSmrg    int i;
3576f7df2e56Smrg
3577f7df2e56Smrg    for (i = 1; i < currentMaxClients; i++)
357805b261ecSmrg        if (clients[i]) {
357905b261ecSmrg            /* Make sure Retained clients are released. */
358005b261ecSmrg            clients[i]->closeDownMode = DestroyAll;
3581f7df2e56Smrg            CloseDownClient(clients[i]);
358205b261ecSmrg        }
358305b261ecSmrg}
358405b261ecSmrg
3585f7df2e56Smrgvoid
3586f7df2e56SmrgInitClient(ClientPtr client, int i, void *ospriv)
358705b261ecSmrg{
358805b261ecSmrg    client->index = i;
35897e31ba66Smrg    xorg_list_init(&client->ready);
35907e31ba66Smrg    xorg_list_init(&client->output_pending);
3591f7df2e56Smrg    client->clientAsMask = ((Mask) i) << CLIENTOFFSET;
35924642e01fSmrg    client->closeDownMode = i ? DestroyAll : RetainPermanent;
359305b261ecSmrg    client->requestVector = InitialVector;
359405b261ecSmrg    client->osPrivate = ospriv;
3595f7df2e56Smrg    QueryMinMaxKeyCodes(&client->minKC, &client->maxKC);
359605b261ecSmrg    client->smart_start_tick = SmartScheduleTime;
359705b261ecSmrg    client->smart_stop_tick = SmartScheduleTime;
3598f7df2e56Smrg    client->clientIds = NULL;
359905b261ecSmrg}
360005b261ecSmrg
360105b261ecSmrg/************************
360205b261ecSmrg * int NextAvailableClient(ospriv)
360305b261ecSmrg *
360405b261ecSmrg * OS dependent portion can't assign client id's because of CloseDownModes.
360505b261ecSmrg * Returns NULL if there are no free clients.
360605b261ecSmrg *************************/
360705b261ecSmrg
3608f7df2e56SmrgClientPtr
3609f7df2e56SmrgNextAvailableClient(void *ospriv)
361005b261ecSmrg{
361105b261ecSmrg    int i;
361205b261ecSmrg    ClientPtr client;
361305b261ecSmrg    xReq data;
361405b261ecSmrg
361505b261ecSmrg    i = nextFreeClientID;
3616f7df2e56Smrg    if (i == LimitClients)
3617f7df2e56Smrg        return (ClientPtr) NULL;
3618f7df2e56Smrg    clients[i] = client =
3619f7df2e56Smrg        dixAllocateObjectWithPrivates(ClientRec, PRIVATE_CLIENT);
362005b261ecSmrg    if (!client)
3621f7df2e56Smrg        return (ClientPtr) NULL;
362205b261ecSmrg    InitClient(client, i, ospriv);
3623f7df2e56Smrg    if (!InitClientResources(client)) {
3624f7df2e56Smrg        dixFreeObjectWithPrivates(client, PRIVATE_CLIENT);
3625f7df2e56Smrg        return (ClientPtr) NULL;
362605b261ecSmrg    }
362705b261ecSmrg    data.reqType = 1;
36286747b715Smrg    data.length = bytes_to_int32(sz_xReq + sz_xConnClientPrefix);
3629f7df2e56Smrg    if (!InsertFakeRequest(client, (char *) &data, sz_xReq)) {
3630f7df2e56Smrg        FreeClientResources(client);
3631f7df2e56Smrg        dixFreeObjectWithPrivates(client, PRIVATE_CLIENT);
3632f7df2e56Smrg        return (ClientPtr) NULL;
363305b261ecSmrg    }
363405b261ecSmrg    if (i == currentMaxClients)
3635f7df2e56Smrg        currentMaxClients++;
3636f7df2e56Smrg    while ((nextFreeClientID < LimitClients) && clients[nextFreeClientID])
3637f7df2e56Smrg        nextFreeClientID++;
3638f7df2e56Smrg
3639f7df2e56Smrg    /* Enable client ID tracking. This must be done before
3640f7df2e56Smrg     * ClientStateCallback. */
3641f7df2e56Smrg    ReserveClientIds(client);
3642f7df2e56Smrg
3643f7df2e56Smrg    if (ClientStateCallback) {
3644f7df2e56Smrg        NewClientInfoRec clientinfo;
364505b261ecSmrg
3646f7df2e56Smrg        clientinfo.client = client;
3647f7df2e56Smrg        clientinfo.prefix = (xConnSetupPrefix *) NULL;
364805b261ecSmrg        clientinfo.setup = (xConnSetup *) NULL;
3649f7df2e56Smrg        CallCallbacks((&ClientStateCallback), (void *) &clientinfo);
3650f7df2e56Smrg    }
36516747b715Smrg    return client;
365205b261ecSmrg}
365305b261ecSmrg
365405b261ecSmrgint
365505b261ecSmrgProcInitialConnection(ClientPtr client)
365605b261ecSmrg{
365705b261ecSmrg    REQUEST(xReq);
365805b261ecSmrg    xConnClientPrefix *prefix;
365905b261ecSmrg    int whichbyte = 1;
3660f7df2e56Smrg    char order;
366105b261ecSmrg
3662f7df2e56Smrg    prefix = (xConnClientPrefix *) ((char *)stuff + sz_xReq);
3663f7df2e56Smrg    order = prefix->byteOrder;
3664f7df2e56Smrg    if (order != 'l' && order != 'B' && order != 'r' && order != 'R')
36656747b715Smrg	return client->noClientException = -1;
3666f7df2e56Smrg    if (((*(char *) &whichbyte) && (order == 'B' || order == 'R')) ||
3667f7df2e56Smrg	(!(*(char *) &whichbyte) && (order == 'l' || order == 'r'))) {
366805b261ecSmrg	client->swapped = TRUE;
366905b261ecSmrg	SwapConnClientPrefix(prefix);
367005b261ecSmrg    }
367105b261ecSmrg    stuff->reqType = 2;
36726747b715Smrg    stuff->length += bytes_to_int32(prefix->nbytesAuthProto) +
3673f7df2e56Smrg        bytes_to_int32(prefix->nbytesAuthString);
3674f7df2e56Smrg    if (client->swapped) {
3675f7df2e56Smrg        swaps(&stuff->length);
3676f7df2e56Smrg    }
3677f7df2e56Smrg    if (order == 'r' || order == 'R') {
3678f7df2e56Smrg	client->local = FALSE;
367905b261ecSmrg    }
368005b261ecSmrg    ResetCurrentRequest(client);
36816747b715Smrg    return Success;
368205b261ecSmrg}
368305b261ecSmrg
36844642e01fSmrgstatic int
3685f7df2e56SmrgSendConnSetup(ClientPtr client, const char *reason)
368605b261ecSmrg{
368705b261ecSmrg    xWindowRoot *root;
368805b261ecSmrg    int i;
368905b261ecSmrg    int numScreens;
3690f7df2e56Smrg    char *lConnectionInfo;
3691f7df2e56Smrg    xConnSetupPrefix *lconnSetupPrefix;
369205b261ecSmrg
3693f7df2e56Smrg    if (reason) {
3694f7df2e56Smrg        xConnSetupPrefix csp;
3695f7df2e56Smrg
3696f7df2e56Smrg        csp.success = xFalse;
3697f7df2e56Smrg        csp.lengthReason = strlen(reason);
3698f7df2e56Smrg        csp.length = bytes_to_int32(csp.lengthReason);
3699f7df2e56Smrg        csp.majorVersion = X_PROTOCOL;
3700f7df2e56Smrg        csp.minorVersion = X_PROTOCOL_REVISION;
3701f7df2e56Smrg        if (client->swapped)
3702f7df2e56Smrg            WriteSConnSetupPrefix(client, &csp);
3703f7df2e56Smrg        else
3704f7df2e56Smrg            WriteToClient(client, sz_xConnSetupPrefix, &csp);
3705f7df2e56Smrg        WriteToClient(client, (int) csp.lengthReason, reason);
3706f7df2e56Smrg        return client->noClientException = -1;
370705b261ecSmrg    }
370805b261ecSmrg
370905b261ecSmrg    numScreens = screenInfo.numScreens;
371005b261ecSmrg    lConnectionInfo = ConnectionInfo;
371105b261ecSmrg    lconnSetupPrefix = &connSetupPrefix;
371205b261ecSmrg
371305b261ecSmrg    /* We're about to start speaking X protocol back to the client by
371405b261ecSmrg     * sending the connection setup info.  This means the authorization
371505b261ecSmrg     * step is complete, and we can count the client as an
371605b261ecSmrg     * authorized one.
371705b261ecSmrg     */
371805b261ecSmrg    nClients++;
371905b261ecSmrg
372005b261ecSmrg    client->requestVector = client->swapped ? SwappedProcVector : ProcVector;
372105b261ecSmrg    client->sequence = 0;
3722f7df2e56Smrg    ((xConnSetup *) lConnectionInfo)->ridBase = client->clientAsMask;
3723f7df2e56Smrg    ((xConnSetup *) lConnectionInfo)->ridMask = RESOURCE_ID_MASK;
372405b261ecSmrg#ifdef MATCH_CLIENT_ENDIAN
3725f7df2e56Smrg    ((xConnSetup *) lConnectionInfo)->imageByteOrder = ClientOrder(client);
3726f7df2e56Smrg    ((xConnSetup *) lConnectionInfo)->bitmapBitOrder = ClientOrder(client);
372705b261ecSmrg#endif
372805b261ecSmrg    /* fill in the "currentInputMask" */
3729f7df2e56Smrg    root = (xWindowRoot *) (lConnectionInfo + connBlockScreenStart);
373005b261ecSmrg#ifdef PANORAMIX
373105b261ecSmrg    if (noPanoramiXExtension)
3732f7df2e56Smrg        numScreens = screenInfo.numScreens;
3733f7df2e56Smrg    else
3734f7df2e56Smrg        numScreens = ((xConnSetup *) ConnectionInfo)->numRoots;
373505b261ecSmrg#endif
373605b261ecSmrg
3737f7df2e56Smrg    for (i = 0; i < numScreens; i++) {
3738f7df2e56Smrg        unsigned int j;
3739f7df2e56Smrg        xDepth *pDepth;
3740f7df2e56Smrg        WindowPtr pRoot = screenInfo.screens[i]->root;
374105b261ecSmrg
37426747b715Smrg        root->currentInputMask = pRoot->eventMask | wOtherEventMasks(pRoot);
3743f7df2e56Smrg        pDepth = (xDepth *) (root + 1);
3744f7df2e56Smrg        for (j = 0; j < root->nDepths; j++) {
3745f7df2e56Smrg            pDepth = (xDepth *) (((char *) (pDepth + 1)) +
3746f7df2e56Smrg                                 pDepth->nVisuals * sizeof(xVisualType));
3747f7df2e56Smrg        }
3748f7df2e56Smrg        root = (xWindowRoot *) pDepth;
374905b261ecSmrg    }
375005b261ecSmrg
3751f7df2e56Smrg    if (client->swapped) {
3752f7df2e56Smrg        WriteSConnSetupPrefix(client, lconnSetupPrefix);
3753f7df2e56Smrg        WriteSConnectionInfo(client,
3754f7df2e56Smrg                             (unsigned long) (lconnSetupPrefix->length << 2),
3755f7df2e56Smrg                             lConnectionInfo);
375605b261ecSmrg    }
3757f7df2e56Smrg    else {
3758f7df2e56Smrg        WriteToClient(client, sizeof(xConnSetupPrefix), lconnSetupPrefix);
3759f7df2e56Smrg        WriteToClient(client, (int) (lconnSetupPrefix->length << 2),
3760f7df2e56Smrg		      lConnectionInfo);
376105b261ecSmrg    }
376205b261ecSmrg    client->clientState = ClientStateRunning;
3763f7df2e56Smrg    if (ClientStateCallback) {
3764f7df2e56Smrg        NewClientInfoRec clientinfo;
376505b261ecSmrg
3766f7df2e56Smrg        clientinfo.client = client;
3767f7df2e56Smrg        clientinfo.prefix = lconnSetupPrefix;
3768f7df2e56Smrg        clientinfo.setup = (xConnSetup *) lConnectionInfo;
3769f7df2e56Smrg        CallCallbacks((&ClientStateCallback), (void *) &clientinfo);
3770f7df2e56Smrg    }
37715a112b11Smrg    CancelDispatchExceptionTimer();
37726747b715Smrg    return Success;
377305b261ecSmrg}
377405b261ecSmrg
377505b261ecSmrgint
377605b261ecSmrgProcEstablishConnection(ClientPtr client)
377705b261ecSmrg{
3778f7df2e56Smrg    const char *reason;
3779f7df2e56Smrg    char *auth_proto, *auth_string;
378005b261ecSmrg    xConnClientPrefix *prefix;
3781f7df2e56Smrg
378205b261ecSmrg    REQUEST(xReq);
378305b261ecSmrg
3784f7df2e56Smrg    prefix = (xConnClientPrefix *) ((char *) stuff + sz_xReq);
3785f7df2e56Smrg    auth_proto = (char *) prefix + sz_xConnClientPrefix;
37866747b715Smrg    auth_string = auth_proto + pad_to_int32(prefix->nbytesAuthProto);
37876e78d31fSmrg
3788875c6e4fSmrg    if (client->swapped && !AllowByteSwappedClients) {
3789875c6e4fSmrg        reason = "Prohibited client endianess, see the Xserver man page ";
3790875c6e4fSmrg    } else if ((client->req_len << 2) != sz_xReq + sz_xConnClientPrefix +
3791875c6e4fSmrg               pad_to_int32(prefix->nbytesAuthProto) +
3792875c6e4fSmrg               pad_to_int32(prefix->nbytesAuthString))
37936e78d31fSmrg        reason = "Bad length";
37946e78d31fSmrg    else if ((prefix->majorVersion != X_PROTOCOL) ||
3795f7df2e56Smrg        (prefix->minorVersion != X_PROTOCOL_REVISION))
3796f7df2e56Smrg        reason = "Protocol version mismatch";
379705b261ecSmrg    else
3798f7df2e56Smrg        reason = ClientAuthorized(client,
3799f7df2e56Smrg                                  (unsigned short) prefix->nbytesAuthProto,
3800f7df2e56Smrg                                  auth_proto,
3801f7df2e56Smrg                                  (unsigned short) prefix->nbytesAuthString,
3802f7df2e56Smrg                                  auth_string);
3803f7df2e56Smrg
3804f7df2e56Smrg    return (SendConnSetup(client, reason));
380505b261ecSmrg}
380605b261ecSmrg
38076747b715Smrgvoid
3808f7df2e56SmrgSendErrorToClient(ClientPtr client, unsigned majorCode, unsigned minorCode,
380905b261ecSmrg                  XID resId, int errorCode)
381005b261ecSmrg{
3811f7df2e56Smrg    xError rep = {
3812f7df2e56Smrg        .type = X_Error,
3813f7df2e56Smrg        .errorCode = errorCode,
3814f7df2e56Smrg        .resourceID = resId,
3815f7df2e56Smrg        .minorCode = minorCode,
3816f7df2e56Smrg        .majorCode = majorCode
3817f7df2e56Smrg    };
381805b261ecSmrg
3819f7df2e56Smrg    WriteEventsToClient(client, 1, (xEvent *) &rep);
382005b261ecSmrg}
382105b261ecSmrg
382205b261ecSmrgvoid
382305b261ecSmrgMarkClientException(ClientPtr client)
382405b261ecSmrg{
382505b261ecSmrg    client->noClientException = -1;
382605b261ecSmrg}
38276747b715Smrg
38286747b715Smrg/*
38296747b715Smrg * This array encodes the answer to the question "what is the log base 2
38306747b715Smrg * of the number of pixels that fit in a scanline pad unit?"
38316747b715Smrg * Note that ~0 is an invalid entry (mostly for the benefit of the reader).
38326747b715Smrg */
38336747b715Smrgstatic int answer[6][4] = {
3834f7df2e56Smrg    /* pad   pad   pad     pad */
3835f7df2e56Smrg    /*  8     16    32    64 */
3836f7df2e56Smrg
3837f7df2e56Smrg    {3, 4, 5, 6},               /* 1 bit per pixel */
3838f7df2e56Smrg    {1, 2, 3, 4},               /* 4 bits per pixel */
3839f7df2e56Smrg    {0, 1, 2, 3},               /* 8 bits per pixel */
3840f7df2e56Smrg    {~0, 0, 1, 2},              /* 16 bits per pixel */
3841f7df2e56Smrg    {~0, ~0, 0, 1},             /* 24 bits per pixel */
3842f7df2e56Smrg    {~0, ~0, 0, 1}              /* 32 bits per pixel */
38436747b715Smrg};
38446747b715Smrg
38456747b715Smrg/*
38466747b715Smrg * This array gives the answer to the question "what is the first index for
38476747b715Smrg * the answer array above given the number of bits per pixel?"
38486747b715Smrg * Note that ~0 is an invalid entry (mostly for the benefit of the reader).
38496747b715Smrg */
3850f7df2e56Smrgstatic int indexForBitsPerPixel[33] = {
3851f7df2e56Smrg    ~0, 0, ~0, ~0,              /* 1 bit per pixel */
3852f7df2e56Smrg    1, ~0, ~0, ~0,              /* 4 bits per pixel */
3853f7df2e56Smrg    2, ~0, ~0, ~0,              /* 8 bits per pixel */
3854f7df2e56Smrg    ~0, ~0, ~0, ~0,
3855f7df2e56Smrg    3, ~0, ~0, ~0,              /* 16 bits per pixel */
3856f7df2e56Smrg    ~0, ~0, ~0, ~0,
3857f7df2e56Smrg    4, ~0, ~0, ~0,              /* 24 bits per pixel */
3858f7df2e56Smrg    ~0, ~0, ~0, ~0,
3859f7df2e56Smrg    5                           /* 32 bits per pixel */
38606747b715Smrg};
38616747b715Smrg
38626747b715Smrg/*
38636747b715Smrg * This array gives the bytesperPixel value for cases where the number
38646747b715Smrg * of bits per pixel is a multiple of 8 but not a power of 2.
38656747b715Smrg */
3866f7df2e56Smrgstatic int answerBytesPerPixel[33] = {
3867f7df2e56Smrg    ~0, 0, ~0, ~0,              /* 1 bit per pixel */
3868f7df2e56Smrg    0, ~0, ~0, ~0,              /* 4 bits per pixel */
3869f7df2e56Smrg    0, ~0, ~0, ~0,              /* 8 bits per pixel */
3870f7df2e56Smrg    ~0, ~0, ~0, ~0,
3871f7df2e56Smrg    0, ~0, ~0, ~0,              /* 16 bits per pixel */
3872f7df2e56Smrg    ~0, ~0, ~0, ~0,
3873f7df2e56Smrg    3, ~0, ~0, ~0,              /* 24 bits per pixel */
3874f7df2e56Smrg    ~0, ~0, ~0, ~0,
3875f7df2e56Smrg    0                           /* 32 bits per pixel */
38766747b715Smrg};
38776747b715Smrg
38786747b715Smrg/*
38796747b715Smrg * This array gives the answer to the question "what is the second index for
38806747b715Smrg * the answer array above given the number of bits per scanline pad unit?"
38816747b715Smrg * Note that ~0 is an invalid entry (mostly for the benefit of the reader).
38826747b715Smrg */
3883f7df2e56Smrgstatic int indexForScanlinePad[65] = {
3884f7df2e56Smrg    ~0, ~0, ~0, ~0,
3885f7df2e56Smrg    ~0, ~0, ~0, ~0,
3886f7df2e56Smrg    0, ~0, ~0, ~0,              /* 8 bits per scanline pad unit */
3887f7df2e56Smrg    ~0, ~0, ~0, ~0,
3888f7df2e56Smrg    1, ~0, ~0, ~0,              /* 16 bits per scanline pad unit */
3889f7df2e56Smrg    ~0, ~0, ~0, ~0,
3890f7df2e56Smrg    ~0, ~0, ~0, ~0,
3891f7df2e56Smrg    ~0, ~0, ~0, ~0,
3892f7df2e56Smrg    2, ~0, ~0, ~0,              /* 32 bits per scanline pad unit */
3893f7df2e56Smrg    ~0, ~0, ~0, ~0,
3894f7df2e56Smrg    ~0, ~0, ~0, ~0,
3895f7df2e56Smrg    ~0, ~0, ~0, ~0,
3896f7df2e56Smrg    ~0, ~0, ~0, ~0,
3897f7df2e56Smrg    ~0, ~0, ~0, ~0,
3898f7df2e56Smrg    ~0, ~0, ~0, ~0,
3899f7df2e56Smrg    ~0, ~0, ~0, ~0,
3900f7df2e56Smrg    3                           /* 64 bits per scanline pad unit */
39016747b715Smrg};
39026747b715Smrg
39036747b715Smrg/*
39046747b715Smrg	grow the array of screenRecs if necessary.
39056747b715Smrg	call the device-supplied initialization procedure
39066747b715Smrgwith its screen number, a pointer to its ScreenRec, argc, and argv.
39076747b715Smrg	return the number of successfully installed screens.
39086747b715Smrg
39096747b715Smrg*/
39106747b715Smrg
3911f7df2e56Smrgstatic int init_screen(ScreenPtr pScreen, int i, Bool gpu)
39126747b715Smrg{
39136747b715Smrg    int scanlinepad, format, depth, bitsPerPixel, j, k;
39146747b715Smrg
3915f7df2e56Smrg    dixInitScreenSpecificPrivates(pScreen);
39166747b715Smrg
39176747b715Smrg    if (!dixAllocatePrivates(&pScreen->devPrivates, PRIVATE_SCREEN)) {
3918f7df2e56Smrg        return -1;
39196747b715Smrg    }
39206747b715Smrg    pScreen->myNum = i;
3921f7df2e56Smrg    if (gpu) {
3922f7df2e56Smrg        pScreen->myNum += GPU_SCREEN_OFFSET;
3923f7df2e56Smrg        pScreen->isGPU = TRUE;
3924f7df2e56Smrg    }
3925f7df2e56Smrg    pScreen->totalPixmapSize = 0;       /* computed in CreateScratchPixmapForScreen */
3926f7df2e56Smrg    pScreen->ClipNotify = 0;    /* for R4 ddx compatibility */
39276747b715Smrg    pScreen->CreateScreenResources = 0;
39286747b715Smrg
3929f7df2e56Smrg    xorg_list_init(&pScreen->pixmap_dirty_list);
39305a112b11Smrg    xorg_list_init(&pScreen->secondary_list);
3931f7df2e56Smrg
39326747b715Smrg    /*
39336747b715Smrg     * This loop gets run once for every Screen that gets added,
39345a112b11Smrg     * but that's ok.  If the ddx layer initializes the formats
39356747b715Smrg     * one at a time calling AddScreen() after each, then each
39366747b715Smrg     * iteration will make it a little more accurate.  Worst case
39376747b715Smrg     * we do this loop N * numPixmapFormats where N is # of screens.
39386747b715Smrg     * Anyway, this must be called after InitOutput and before the
39396747b715Smrg     * screen init routine is called.
39406747b715Smrg     */
3941f7df2e56Smrg    for (format = 0; format < screenInfo.numPixmapFormats; format++) {
3942f7df2e56Smrg        depth = screenInfo.formats[format].depth;
3943f7df2e56Smrg        bitsPerPixel = screenInfo.formats[format].bitsPerPixel;
3944f7df2e56Smrg        scanlinepad = screenInfo.formats[format].scanlinePad;
3945f7df2e56Smrg        j = indexForBitsPerPixel[bitsPerPixel];
3946f7df2e56Smrg        k = indexForScanlinePad[scanlinepad];
3947f7df2e56Smrg        PixmapWidthPaddingInfo[depth].padPixelsLog2 = answer[j][k];
3948f7df2e56Smrg        PixmapWidthPaddingInfo[depth].padRoundUp =
3949f7df2e56Smrg            (scanlinepad / bitsPerPixel) - 1;
3950f7df2e56Smrg        j = indexForBitsPerPixel[8];    /* bits per byte */
3951f7df2e56Smrg        PixmapWidthPaddingInfo[depth].padBytesLog2 = answer[j][k];
3952f7df2e56Smrg        PixmapWidthPaddingInfo[depth].bitsPerPixel = bitsPerPixel;
3953f7df2e56Smrg        if (answerBytesPerPixel[bitsPerPixel]) {
3954f7df2e56Smrg            PixmapWidthPaddingInfo[depth].notPower2 = 1;
3955f7df2e56Smrg            PixmapWidthPaddingInfo[depth].bytesPerPixel =
3956f7df2e56Smrg                answerBytesPerPixel[bitsPerPixel];
3957f7df2e56Smrg        }
3958f7df2e56Smrg        else {
3959f7df2e56Smrg            PixmapWidthPaddingInfo[depth].notPower2 = 0;
3960f7df2e56Smrg        }
39616747b715Smrg    }
3962f7df2e56Smrg    return 0;
3963f7df2e56Smrg}
3964f7df2e56Smrg
3965f7df2e56Smrgint
3966f7df2e56SmrgAddScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ ,
3967f7df2e56Smrg                           int /*argc */ ,
3968f7df2e56Smrg                           char **      /*argv */
3969f7df2e56Smrg          ), int argc, char **argv)
3970f7df2e56Smrg{
3971f7df2e56Smrg
3972f7df2e56Smrg    int i;
3973f7df2e56Smrg    ScreenPtr pScreen;
3974f7df2e56Smrg    Bool ret;
3975f7df2e56Smrg
3976f7df2e56Smrg    i = screenInfo.numScreens;
3977f7df2e56Smrg    if (i == MAXSCREENS)
3978f7df2e56Smrg        return -1;
3979f7df2e56Smrg
3980f7df2e56Smrg    pScreen = (ScreenPtr) calloc(1, sizeof(ScreenRec));
3981f7df2e56Smrg    if (!pScreen)
3982f7df2e56Smrg        return -1;
39836747b715Smrg
3984f7df2e56Smrg    ret = init_screen(pScreen, i, FALSE);
3985f7df2e56Smrg    if (ret != 0) {
3986f7df2e56Smrg        free(pScreen);
3987f7df2e56Smrg        return ret;
3988f7df2e56Smrg    }
39896747b715Smrg    /* This is where screen specific stuff gets initialized.  Load the
39906747b715Smrg       screen structure, call the hardware, whatever.
39916747b715Smrg       This is also where the default colormap should be allocated and
39926747b715Smrg       also pixel values for blackPixel, whitePixel, and the cursor
39936747b715Smrg       Note that InitScreen is NOT allowed to modify argc, argv, or
39946747b715Smrg       any of the strings pointed to by argv.  They may be passed to
39956747b715Smrg       multiple screens.
3996f7df2e56Smrg     */
39976747b715Smrg    screenInfo.screens[i] = pScreen;
39986747b715Smrg    screenInfo.numScreens++;
3999f7df2e56Smrg    if (!(*pfnInit) (pScreen, argc, argv)) {
4000f7df2e56Smrg        dixFreeScreenSpecificPrivates(pScreen);
4001f7df2e56Smrg        dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN);
4002f7df2e56Smrg        free(pScreen);
4003f7df2e56Smrg        screenInfo.numScreens--;
4004f7df2e56Smrg        return -1;
40056747b715Smrg    }
40066747b715Smrg
4007f7df2e56Smrg    update_desktop_dimensions();
4008f7df2e56Smrg
4009f7df2e56Smrg    dixRegisterScreenPrivateKey(&cursorScreenDevPriv, pScreen, PRIVATE_CURSOR,
4010f7df2e56Smrg                                0);
40116747b715Smrg
40126747b715Smrg    return i;
40136747b715Smrg}
4014f7df2e56Smrg
4015f7df2e56Smrgint
4016f7df2e56SmrgAddGPUScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ ,
4017f7df2e56Smrg                              int /*argc */ ,
4018f7df2e56Smrg                              char **      /*argv */
4019f7df2e56Smrg                              ),
4020f7df2e56Smrg             int argc, char **argv)
4021f7df2e56Smrg{
4022f7df2e56Smrg    int i;
4023f7df2e56Smrg    ScreenPtr pScreen;
4024f7df2e56Smrg    Bool ret;
4025f7df2e56Smrg
4026f7df2e56Smrg    i = screenInfo.numGPUScreens;
4027f7df2e56Smrg    if (i == MAXGPUSCREENS)
4028f7df2e56Smrg        return -1;
4029f7df2e56Smrg
4030f7df2e56Smrg    pScreen = (ScreenPtr) calloc(1, sizeof(ScreenRec));
4031f7df2e56Smrg    if (!pScreen)
4032f7df2e56Smrg        return -1;
4033f7df2e56Smrg
4034f7df2e56Smrg    ret = init_screen(pScreen, i, TRUE);
4035f7df2e56Smrg    if (ret != 0) {
4036f7df2e56Smrg        free(pScreen);
4037f7df2e56Smrg        return ret;
4038f7df2e56Smrg    }
4039f7df2e56Smrg
4040f7df2e56Smrg    /* This is where screen specific stuff gets initialized.  Load the
4041f7df2e56Smrg       screen structure, call the hardware, whatever.
4042f7df2e56Smrg       This is also where the default colormap should be allocated and
4043f7df2e56Smrg       also pixel values for blackPixel, whitePixel, and the cursor
4044f7df2e56Smrg       Note that InitScreen is NOT allowed to modify argc, argv, or
4045f7df2e56Smrg       any of the strings pointed to by argv.  They may be passed to
4046f7df2e56Smrg       multiple screens.
4047f7df2e56Smrg     */
4048f7df2e56Smrg    screenInfo.gpuscreens[i] = pScreen;
4049f7df2e56Smrg    screenInfo.numGPUScreens++;
4050f7df2e56Smrg    if (!(*pfnInit) (pScreen, argc, argv)) {
4051f7df2e56Smrg        dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN);
4052f7df2e56Smrg        free(pScreen);
4053f7df2e56Smrg        screenInfo.numGPUScreens--;
4054f7df2e56Smrg        return -1;
4055f7df2e56Smrg    }
4056f7df2e56Smrg
4057f7df2e56Smrg    update_desktop_dimensions();
4058f7df2e56Smrg
40597e31ba66Smrg    /*
40607e31ba66Smrg     * We cannot register the Screen PRIVATE_CURSOR key if cursors are already
40617e31ba66Smrg     * created, because dix/privates.c does not have relocation code for
40627e31ba66Smrg     * PRIVATE_CURSOR. Once this is fixed the if() can be removed and we can
40637e31ba66Smrg     * register the Screen PRIVATE_CURSOR key unconditionally.
40647e31ba66Smrg     */
40657e31ba66Smrg    if (!dixPrivatesCreated(PRIVATE_CURSOR))
40667e31ba66Smrg        dixRegisterScreenPrivateKey(&cursorScreenDevPriv, pScreen,
40677e31ba66Smrg                                    PRIVATE_CURSOR, 0);
40687e31ba66Smrg
4069f7df2e56Smrg    return i;
4070f7df2e56Smrg}
4071f7df2e56Smrg
4072f7df2e56Smrgvoid
4073f7df2e56SmrgRemoveGPUScreen(ScreenPtr pScreen)
4074f7df2e56Smrg{
4075f7df2e56Smrg    int idx, j;
4076f7df2e56Smrg    if (!pScreen->isGPU)
4077f7df2e56Smrg        return;
4078f7df2e56Smrg
4079f7df2e56Smrg    idx = pScreen->myNum - GPU_SCREEN_OFFSET;
4080f7df2e56Smrg    for (j = idx; j < screenInfo.numGPUScreens - 1; j++) {
4081f7df2e56Smrg        screenInfo.gpuscreens[j] = screenInfo.gpuscreens[j + 1];
4082f7df2e56Smrg        screenInfo.gpuscreens[j]->myNum = j + GPU_SCREEN_OFFSET;
4083f7df2e56Smrg    }
4084f7df2e56Smrg    screenInfo.numGPUScreens--;
4085f7df2e56Smrg
4086f7df2e56Smrg    /* this gets freed later in the resource list, but without
4087f7df2e56Smrg     * the screen existing it causes crashes - so remove it here */
4088f7df2e56Smrg    if (pScreen->defColormap)
4089f7df2e56Smrg        FreeResource(pScreen->defColormap, RT_COLORMAP);
4090f7df2e56Smrg    free(pScreen);
4091f7df2e56Smrg
4092f7df2e56Smrg}
4093f7df2e56Smrg
4094f7df2e56Smrgvoid
4095f7df2e56SmrgAttachUnboundGPU(ScreenPtr pScreen, ScreenPtr new)
4096f7df2e56Smrg{
4097f7df2e56Smrg    assert(new->isGPU);
40985a112b11Smrg    assert(!new->current_primary);
40995a112b11Smrg    xorg_list_add(&new->secondary_head, &pScreen->secondary_list);
41005a112b11Smrg    new->current_primary = pScreen;
4101f7df2e56Smrg}
4102f7df2e56Smrg
4103f7df2e56Smrgvoid
41045a112b11SmrgDetachUnboundGPU(ScreenPtr secondary)
4105f7df2e56Smrg{
41065a112b11Smrg    assert(secondary->isGPU);
41075a112b11Smrg    assert(!secondary->is_output_secondary);
41085a112b11Smrg    assert(!secondary->is_offload_secondary);
41095a112b11Smrg    xorg_list_del(&secondary->secondary_head);
41105a112b11Smrg    secondary->current_primary = NULL;
4111f7df2e56Smrg}
4112f7df2e56Smrg
4113f7df2e56Smrgvoid
4114f7df2e56SmrgAttachOutputGPU(ScreenPtr pScreen, ScreenPtr new)
4115f7df2e56Smrg{
4116f7df2e56Smrg    assert(new->isGPU);
41175a112b11Smrg    assert(!new->is_output_secondary);
41185a112b11Smrg    assert(new->current_primary == pScreen);
41195a112b11Smrg    new->is_output_secondary = TRUE;
41205a112b11Smrg    new->current_primary->output_secondarys++;
4121f7df2e56Smrg}
4122f7df2e56Smrg
4123f7df2e56Smrgvoid
41245a112b11SmrgDetachOutputGPU(ScreenPtr secondary)
4125f7df2e56Smrg{
41265a112b11Smrg    assert(secondary->isGPU);
41275a112b11Smrg    assert(secondary->is_output_secondary);
41285a112b11Smrg    secondary->current_primary->output_secondarys--;
41295a112b11Smrg    secondary->is_output_secondary = FALSE;
4130f7df2e56Smrg}
4131f7df2e56Smrg
4132f7df2e56Smrgvoid
4133f7df2e56SmrgAttachOffloadGPU(ScreenPtr pScreen, ScreenPtr new)
4134f7df2e56Smrg{
4135f7df2e56Smrg    assert(new->isGPU);
41365a112b11Smrg    assert(!new->is_offload_secondary);
41375a112b11Smrg    assert(new->current_primary == pScreen);
41385a112b11Smrg    new->is_offload_secondary = TRUE;
4139f7df2e56Smrg}
4140f7df2e56Smrg
4141f7df2e56Smrgvoid
41425a112b11SmrgDetachOffloadGPU(ScreenPtr secondary)
4143f7df2e56Smrg{
41445a112b11Smrg    assert(secondary->isGPU);
41455a112b11Smrg    assert(secondary->is_offload_secondary);
41465a112b11Smrg    secondary->is_offload_secondary = FALSE;
4147f7df2e56Smrg}
4148f7df2e56Smrg
4149