dispatch.c revision 4e185dc0
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"
1306747b715Smrg#include "site.h"
131f7df2e56Smrg#include "client.h"
13205b261ecSmrg
13305b261ecSmrg#ifdef XSERVER_DTRACE
1344642e01fSmrg#include "registry.h"
135f7df2e56Smrg#include "probes.h"
13605b261ecSmrg#endif
13705b261ecSmrg
13805b261ecSmrg#define mskcnt ((MAXCLIENTS + 31) / 32)
13905b261ecSmrg#define BITMASK(i) (1U << ((i) & 31))
14005b261ecSmrg#define MASKIDX(i) ((i) >> 5)
14105b261ecSmrg#define MASKWORD(buf, i) buf[MASKIDX(i)]
14205b261ecSmrg#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i)
14305b261ecSmrg#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i)
14405b261ecSmrg#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i))
14505b261ecSmrg
1466747b715SmrgxConnSetupPrefix connSetupPrefix;
1476747b715Smrg
1486747b715SmrgPaddingInfo PixmapWidthPaddingInfo[33];
14905b261ecSmrg
15005b261ecSmrgstatic ClientPtr grabClient;
151f7df2e56Smrg
15205b261ecSmrg#define GrabNone 0
15305b261ecSmrg#define GrabActive 1
15405b261ecSmrgstatic int grabState = GrabNone;
15505b261ecSmrgstatic long grabWaiters[mskcnt];
1566747b715SmrgCallbackListPtr ServerGrabCallback = NULL;
15705b261ecSmrgHWEventQueuePtr checkForInput[2];
1586747b715Smrgint connBlockScreenStart;
15905b261ecSmrg
16005b261ecSmrgstatic void KillAllClients(void);
16105b261ecSmrg
162f7df2e56Smrgstatic int nextFreeClientID;    /* always MIN free client ID */
16305b261ecSmrg
164f7df2e56Smrgstatic int nClients;            /* number of authorized clients */
16505b261ecSmrg
1666747b715SmrgCallbackListPtr ClientStateCallback;
16705b261ecSmrg
16805b261ecSmrg/* dispatchException & isItTimeToYield must be declared volatile since they
16905b261ecSmrg * are modified by signal handlers - otherwise optimizer may assume it doesn't
17005b261ecSmrg * need to actually check value in memory when used and may miss changes from
17105b261ecSmrg * signal handlers.
17205b261ecSmrg */
1736747b715Smrgvolatile char dispatchException = 0;
1746747b715Smrgvolatile char isItTimeToYield;
17505b261ecSmrg
17605b261ecSmrg#define SAME_SCREENS(a, b) (\
17705b261ecSmrg    (a.pScreen == b.pScreen))
17805b261ecSmrg
1794642e01fSmrgvoid
18005b261ecSmrgSetInputCheck(HWEventQueuePtr c0, HWEventQueuePtr c1)
18105b261ecSmrg{
18205b261ecSmrg    checkForInput[0] = c0;
18305b261ecSmrg    checkForInput[1] = c1;
18405b261ecSmrg}
18505b261ecSmrg
1866747b715Smrgvoid
18705b261ecSmrgUpdateCurrentTime(void)
18805b261ecSmrg{
18905b261ecSmrg    TimeStamp systime;
19005b261ecSmrg
19105b261ecSmrg    /* To avoid time running backwards, we must call GetTimeInMillis before
19205b261ecSmrg     * calling ProcessInputEvents.
19305b261ecSmrg     */
19405b261ecSmrg    systime.months = currentTime.months;
19505b261ecSmrg    systime.milliseconds = GetTimeInMillis();
19605b261ecSmrg    if (systime.milliseconds < currentTime.milliseconds)
197f7df2e56Smrg        systime.months++;
1987e31ba66Smrg    if (InputCheckPending())
199f7df2e56Smrg        ProcessInputEvents();
20005b261ecSmrg    if (CompareTimeStamps(systime, currentTime) == LATER)
201f7df2e56Smrg        currentTime = systime;
20205b261ecSmrg}
20305b261ecSmrg
20405b261ecSmrg/* Like UpdateCurrentTime, but can't call ProcessInputEvents */
2056747b715Smrgvoid
20605b261ecSmrgUpdateCurrentTimeIf(void)
20705b261ecSmrg{
20805b261ecSmrg    TimeStamp systime;
20905b261ecSmrg
21005b261ecSmrg    systime.months = currentTime.months;
21105b261ecSmrg    systime.milliseconds = GetTimeInMillis();
21205b261ecSmrg    if (systime.milliseconds < currentTime.milliseconds)
213f7df2e56Smrg        systime.months++;
214f7df2e56Smrg    if (CompareTimeStamps(systime, currentTime) == LATER)
215f7df2e56Smrg        currentTime = systime;
21605b261ecSmrg}
21705b261ecSmrg
21805b261ecSmrg#undef SMART_DEBUG
21905b261ecSmrg
220f7df2e56Smrg/* in milliseconds */
221f7df2e56Smrg#define SMART_SCHEDULE_DEFAULT_INTERVAL	5
222f7df2e56Smrg#define SMART_SCHEDULE_MAX_SLICE	15
22305b261ecSmrg
2247e31ba66Smrg#ifdef HAVE_SETITIMER
2257e31ba66SmrgBool SmartScheduleSignalEnable = TRUE;
226f7df2e56Smrg#endif
2277e31ba66Smrg
2286747b715Smrglong SmartScheduleSlice = SMART_SCHEDULE_DEFAULT_INTERVAL;
2296747b715Smrglong SmartScheduleInterval = SMART_SCHEDULE_DEFAULT_INTERVAL;
2306747b715Smrglong SmartScheduleMaxSlice = SMART_SCHEDULE_MAX_SLICE;
2316747b715Smrglong SmartScheduleTime;
2326747b715Smrgint SmartScheduleLatencyLimited = 0;
233f7df2e56Smrgstatic ClientPtr SmartLastClient;
234f7df2e56Smrgstatic int SmartLastIndex[SMART_MAX_PRIORITY - SMART_MIN_PRIORITY + 1];
23505b261ecSmrg
23605b261ecSmrg#ifdef SMART_DEBUG
237f7df2e56Smrglong SmartLastPrint;
23805b261ecSmrg#endif
23905b261ecSmrg
240f7df2e56Smrgvoid Dispatch(void);
24105b261ecSmrg
2427e31ba66Smrgstatic struct xorg_list ready_clients;
2437e31ba66Smrgstatic struct xorg_list saved_ready_clients;
2447e31ba66Smrgstruct xorg_list output_pending_clients;
2457e31ba66Smrg
2467e31ba66Smrgstatic void
2477e31ba66Smrginit_client_ready(void)
24805b261ecSmrg{
2497e31ba66Smrg    xorg_list_init(&ready_clients);
2507e31ba66Smrg    xorg_list_init(&saved_ready_clients);
2517e31ba66Smrg    xorg_list_init(&output_pending_clients);
2527e31ba66Smrg}
2537e31ba66Smrg
2547e31ba66SmrgBool
2557e31ba66Smrgclients_are_ready(void)
2567e31ba66Smrg{
2577e31ba66Smrg    return !xorg_list_is_empty(&ready_clients);
2587e31ba66Smrg}
2597e31ba66Smrg
2607e31ba66Smrg/* Client has requests queued or data on the network */
2617e31ba66Smrgvoid
2627e31ba66Smrgmark_client_ready(ClientPtr client)
2637e31ba66Smrg{
2647e31ba66Smrg    if (xorg_list_is_empty(&client->ready))
2657e31ba66Smrg        xorg_list_append(&client->ready, &ready_clients);
2667e31ba66Smrg}
2677e31ba66Smrg
2687e31ba66Smrg/*
2697e31ba66Smrg * Client has requests queued or data on the network, but awaits a
2707e31ba66Smrg * server grab release
2717e31ba66Smrg */
2727e31ba66Smrgvoid mark_client_saved_ready(ClientPtr client)
2737e31ba66Smrg{
2747e31ba66Smrg    if (xorg_list_is_empty(&client->ready))
2757e31ba66Smrg        xorg_list_append(&client->ready, &saved_ready_clients);
2767e31ba66Smrg}
2777e31ba66Smrg
2787e31ba66Smrg/* Client has no requests queued and no data on network */
2797e31ba66Smrgvoid
2807e31ba66Smrgmark_client_not_ready(ClientPtr client)
2817e31ba66Smrg{
2827e31ba66Smrg    xorg_list_del(&client->ready);
2837e31ba66Smrg}
2847e31ba66Smrg
2857e31ba66Smrgstatic void
2867e31ba66Smrgmark_client_grab(ClientPtr grab)
2877e31ba66Smrg{
2887e31ba66Smrg    ClientPtr   client, tmp;
2897e31ba66Smrg
2907e31ba66Smrg    xorg_list_for_each_entry_safe(client, tmp, &ready_clients, ready) {
2917e31ba66Smrg        if (client != grab) {
2927e31ba66Smrg            xorg_list_del(&client->ready);
2937e31ba66Smrg            xorg_list_append(&client->ready, &saved_ready_clients);
2947e31ba66Smrg        }
2957e31ba66Smrg    }
2967e31ba66Smrg}
2977e31ba66Smrg
2987e31ba66Smrgstatic void
2997e31ba66Smrgmark_client_ungrab(void)
3007e31ba66Smrg{
3017e31ba66Smrg    ClientPtr   client, tmp;
3027e31ba66Smrg
3037e31ba66Smrg    xorg_list_for_each_entry_safe(client, tmp, &saved_ready_clients, ready) {
3047e31ba66Smrg        xorg_list_del(&client->ready);
3057e31ba66Smrg        xorg_list_append(&client->ready, &ready_clients);
3067e31ba66Smrg    }
3077e31ba66Smrg}
3087e31ba66Smrg
3097e31ba66Smrgstatic ClientPtr
3107e31ba66SmrgSmartScheduleClient(void)
3117e31ba66Smrg{
3127e31ba66Smrg    ClientPtr pClient, best = NULL;
313f7df2e56Smrg    int bestRobin, robin;
314f7df2e56Smrg    long now = SmartScheduleTime;
315f7df2e56Smrg    long idle;
3167e31ba66Smrg    int nready = 0;
31705b261ecSmrg
31805b261ecSmrg    bestRobin = 0;
31905b261ecSmrg    idle = 2 * SmartScheduleSlice;
3207e31ba66Smrg
3217e31ba66Smrg    xorg_list_for_each_entry(pClient, &ready_clients, ready) {
3227e31ba66Smrg        nready++;
3237e31ba66Smrg
324f7df2e56Smrg        /* Praise clients which haven't run in a while */
325f7df2e56Smrg        if ((now - pClient->smart_stop_tick) >= idle) {
326f7df2e56Smrg            if (pClient->smart_priority < 0)
327f7df2e56Smrg                pClient->smart_priority++;
328f7df2e56Smrg        }
329f7df2e56Smrg
330f7df2e56Smrg        /* check priority to select best client */
331f7df2e56Smrg        robin =
332f7df2e56Smrg            (pClient->index -
333f7df2e56Smrg             SmartLastIndex[pClient->smart_priority -
334f7df2e56Smrg                            SMART_MIN_PRIORITY]) & 0xff;
3357e31ba66Smrg
3367e31ba66Smrg        /* pick the best client */
3377e31ba66Smrg        if (!best ||
3387e31ba66Smrg            pClient->priority > best->priority ||
3397e31ba66Smrg            (pClient->priority == best->priority &&
3407e31ba66Smrg             (pClient->smart_priority > best->smart_priority ||
3417e31ba66Smrg              (pClient->smart_priority == best->smart_priority && robin > bestRobin))))
3427e31ba66Smrg        {
3437e31ba66Smrg            best = pClient;
344f7df2e56Smrg            bestRobin = robin;
345f7df2e56Smrg        }
34605b261ecSmrg#ifdef SMART_DEBUG
347f7df2e56Smrg        if ((now - SmartLastPrint) >= 5000)
3487e31ba66Smrg            fprintf(stderr, " %2d: %3d", pClient->index, pClient->smart_priority);
34905b261ecSmrg#endif
35005b261ecSmrg    }
35105b261ecSmrg#ifdef SMART_DEBUG
352f7df2e56Smrg    if ((now - SmartLastPrint) >= 5000) {
3537e31ba66Smrg        fprintf(stderr, " use %2d\n", best->index);
354f7df2e56Smrg        SmartLastPrint = now;
35505b261ecSmrg    }
35605b261ecSmrg#endif
3577e31ba66Smrg    SmartLastIndex[best->smart_priority - SMART_MIN_PRIORITY] = best->index;
35805b261ecSmrg    /*
35905b261ecSmrg     * Set current client pointer
36005b261ecSmrg     */
3617e31ba66Smrg    if (SmartLastClient != best) {
3627e31ba66Smrg        best->smart_start_tick = now;
3637e31ba66Smrg        SmartLastClient = best;
36405b261ecSmrg    }
36505b261ecSmrg    /*
36605b261ecSmrg     * Adjust slice
36705b261ecSmrg     */
368f7df2e56Smrg    if (nready == 1 && SmartScheduleLatencyLimited == 0) {
369f7df2e56Smrg        /*
370f7df2e56Smrg         * If it's been a long time since another client
371f7df2e56Smrg         * has run, bump the slice up to get maximal
372f7df2e56Smrg         * performance from a single client
373f7df2e56Smrg         */
3747e31ba66Smrg        if ((now - best->smart_start_tick) > 1000 &&
375f7df2e56Smrg            SmartScheduleSlice < SmartScheduleMaxSlice) {
376f7df2e56Smrg            SmartScheduleSlice += SmartScheduleInterval;
377f7df2e56Smrg        }
37805b261ecSmrg    }
379f7df2e56Smrg    else {
380f7df2e56Smrg        SmartScheduleSlice = SmartScheduleInterval;
38105b261ecSmrg    }
38205b261ecSmrg    return best;
38305b261ecSmrg}
38405b261ecSmrg
385b1d344b3Smrgvoid
386b1d344b3SmrgEnableLimitedSchedulingLatency(void)
387b1d344b3Smrg{
388b1d344b3Smrg    ++SmartScheduleLatencyLimited;
389b1d344b3Smrg    SmartScheduleSlice = SmartScheduleInterval;
390b1d344b3Smrg}
391b1d344b3Smrg
392b1d344b3Smrgvoid
393b1d344b3SmrgDisableLimitedSchedulingLatency(void)
394b1d344b3Smrg{
395b1d344b3Smrg    --SmartScheduleLatencyLimited;
396b1d344b3Smrg
397b1d344b3Smrg    /* protect against bugs */
398b1d344b3Smrg    if (SmartScheduleLatencyLimited < 0)
399f7df2e56Smrg        SmartScheduleLatencyLimited = 0;
400b1d344b3Smrg}
401b1d344b3Smrg
40205b261ecSmrgvoid
40305b261ecSmrgDispatch(void)
40405b261ecSmrg{
405f7df2e56Smrg    int result;
406f7df2e56Smrg    ClientPtr client;
407f7df2e56Smrg    long start_tick;
40805b261ecSmrg
40905b261ecSmrg    nextFreeClientID = 1;
41005b261ecSmrg    nClients = 0;
41105b261ecSmrg
412b1d344b3Smrg    SmartScheduleSlice = SmartScheduleInterval;
4137e31ba66Smrg    init_client_ready();
4147e31ba66Smrg
415f7df2e56Smrg    while (!dispatchException) {
4167e31ba66Smrg        if (InputCheckPending()) {
417f7df2e56Smrg            ProcessInputEvents();
418f7df2e56Smrg            FlushIfCriticalOutputPending();
419f7df2e56Smrg        }
420f7df2e56Smrg
4217e31ba66Smrg        if (!WaitForSomething(clients_are_ready()))
4227e31ba66Smrg            continue;
423f7df2e56Smrg
424f7df2e56Smrg       /*****************
425f7df2e56Smrg	*  Handle events in round robin fashion, doing input between
426f7df2e56Smrg	*  each round
42705b261ecSmrg	*****************/
42805b261ecSmrg
4297e31ba66Smrg        if (!dispatchException && clients_are_ready()) {
4307e31ba66Smrg            client = SmartScheduleClient();
4317e31ba66Smrg
432f7df2e56Smrg            isItTimeToYield = FALSE;
433f7df2e56Smrg
434f7df2e56Smrg            start_tick = SmartScheduleTime;
435f7df2e56Smrg            while (!isItTimeToYield) {
4367e31ba66Smrg                if (InputCheckPending())
437f7df2e56Smrg                    ProcessInputEvents();
438f7df2e56Smrg
439f7df2e56Smrg                FlushIfCriticalOutputPending();
4407e31ba66Smrg                if ((SmartScheduleTime - start_tick) >= SmartScheduleSlice)
4417e31ba66Smrg                {
442f7df2e56Smrg                    /* Penalize clients which consume ticks */
443f7df2e56Smrg                    if (client->smart_priority > SMART_MIN_PRIORITY)
444f7df2e56Smrg                        client->smart_priority--;
445f7df2e56Smrg                    break;
446f7df2e56Smrg                }
447f7df2e56Smrg
4487e31ba66Smrg                /* now, finally, deal with client requests */
449f7df2e56Smrg                result = ReadRequestFromClient(client);
450f7df2e56Smrg                if (result <= 0) {
451f7df2e56Smrg                    if (result < 0)
452f7df2e56Smrg                        CloseDownClient(client);
453f7df2e56Smrg                    break;
454f7df2e56Smrg                }
455f7df2e56Smrg
456f7df2e56Smrg                client->sequence++;
457f7df2e56Smrg                client->majorOp = ((xReq *) client->requestBuffer)->reqType;
458f7df2e56Smrg                client->minorOp = 0;
459f7df2e56Smrg                if (client->majorOp >= EXTENSION_BASE) {
460f7df2e56Smrg                    ExtensionEntry *ext = GetExtensionEntry(client->majorOp);
461f7df2e56Smrg
462f7df2e56Smrg                    if (ext)
463f7df2e56Smrg                        client->minorOp = ext->MinorOpcode(client);
464f7df2e56Smrg                }
46505b261ecSmrg#ifdef XSERVER_DTRACE
466f7df2e56Smrg                if (XSERVER_REQUEST_START_ENABLED())
467f7df2e56Smrg                    XSERVER_REQUEST_START(LookupMajorName(client->majorOp),
468f7df2e56Smrg                                          client->majorOp,
469f7df2e56Smrg                                          ((xReq *) client->requestBuffer)->length,
470f7df2e56Smrg                                          client->index,
471f7df2e56Smrg                                          client->requestBuffer);
47205b261ecSmrg#endif
473f7df2e56Smrg                if (result > (maxBigRequestSize << 2))
474f7df2e56Smrg                    result = BadLength;
475f7df2e56Smrg                else {
476f7df2e56Smrg                    result = XaceHookDispatch(client, client->majorOp);
477f7df2e56Smrg                    if (result == Success)
478f7df2e56Smrg                        result =
479f7df2e56Smrg                            (*client->requestVector[client->majorOp]) (client);
480f7df2e56Smrg                }
4817e31ba66Smrg                if (!SmartScheduleSignalEnable)
4827e31ba66Smrg                    SmartScheduleTime = GetTimeInMillis();
4837e31ba66Smrg
48405b261ecSmrg#ifdef XSERVER_DTRACE
485f7df2e56Smrg                if (XSERVER_REQUEST_DONE_ENABLED())
486f7df2e56Smrg                    XSERVER_REQUEST_DONE(LookupMajorName(client->majorOp),
487f7df2e56Smrg                                         client->majorOp, client->sequence,
488f7df2e56Smrg                                         client->index, result);
48905b261ecSmrg#endif
49005b261ecSmrg
491f7df2e56Smrg                if (client->noClientException != Success) {
492f7df2e56Smrg                    CloseDownClient(client);
493f7df2e56Smrg                    break;
494f7df2e56Smrg                }
495f7df2e56Smrg                else if (result != Success) {
496f7df2e56Smrg                    SendErrorToClient(client, client->majorOp,
497f7df2e56Smrg                                      client->minorOp,
498f7df2e56Smrg                                      client->errorValue, result);
499f7df2e56Smrg                    break;
500f7df2e56Smrg                }
501f7df2e56Smrg            }
502f7df2e56Smrg            FlushAllOutput();
5037e31ba66Smrg            if (client == SmartLastClient)
504f7df2e56Smrg                client->smart_stop_tick = SmartScheduleTime;
505f7df2e56Smrg        }
506f7df2e56Smrg        dispatchException &= ~DE_PRIORITYCHANGE;
50705b261ecSmrg    }
50805b261ecSmrg#if defined(DDXBEFORERESET)
509f7df2e56Smrg    ddxBeforeReset();
51005b261ecSmrg#endif
51105b261ecSmrg    KillAllClients();
51205b261ecSmrg    dispatchException &= ~DE_RESET;
513b1d344b3Smrg    SmartScheduleLatencyLimited = 0;
514f7df2e56Smrg    ResetOsBuffers();
51505b261ecSmrg}
51605b261ecSmrg
517f7df2e56Smrgstatic int VendorRelease = VENDOR_RELEASE;
518f7df2e56Smrgstatic const char *VendorString = VENDOR_NAME;
5196747b715Smrg
5206747b715Smrgvoid
5216747b715SmrgSetVendorRelease(int release)
5226747b715Smrg{
5236747b715Smrg    VendorRelease = release;
5246747b715Smrg}
5256747b715Smrg
5266747b715Smrgvoid
527f7df2e56SmrgSetVendorString(const char *vendor)
5286747b715Smrg{
529f7df2e56Smrg    VendorString = vendor;
5306747b715Smrg}
5316747b715Smrg
5326747b715SmrgBool
5336747b715SmrgCreateConnectionBlock(void)
5346747b715Smrg{
5356747b715Smrg    xConnSetup setup;
5366747b715Smrg    xWindowRoot root;
537f7df2e56Smrg    xDepth depth;
5386747b715Smrg    xVisualType visual;
5396747b715Smrg    xPixmapFormat format;
5406747b715Smrg    unsigned long vid;
541f7df2e56Smrg    int i, j, k, lenofblock, sizesofar = 0;
5426747b715Smrg    char *pBuf;
5436747b715Smrg
5446747b715Smrg    memset(&setup, 0, sizeof(xConnSetup));
5456747b715Smrg    /* Leave off the ridBase and ridMask, these must be sent with
5466747b715Smrg       connection */
5476747b715Smrg
5486747b715Smrg    setup.release = VendorRelease;
5496747b715Smrg    /*
5506747b715Smrg     * per-server image and bitmap parameters are defined in Xmd.h
5516747b715Smrg     */
5526747b715Smrg    setup.imageByteOrder = screenInfo.imageByteOrder;
5536747b715Smrg
5546747b715Smrg    setup.bitmapScanlineUnit = screenInfo.bitmapScanlineUnit;
5556747b715Smrg    setup.bitmapScanlinePad = screenInfo.bitmapScanlinePad;
5566747b715Smrg
5576747b715Smrg    setup.bitmapBitOrder = screenInfo.bitmapBitOrder;
5586747b715Smrg    setup.motionBufferSize = NumMotionEvents();
5596747b715Smrg    setup.numRoots = screenInfo.numScreens;
5606747b715Smrg    setup.nbytesVendor = strlen(VendorString);
5616747b715Smrg    setup.numFormats = screenInfo.numPixmapFormats;
5626747b715Smrg    setup.maxRequestSize = MAX_REQUEST_SIZE;
5636747b715Smrg    QueryMinMaxKeyCodes(&setup.minKeyCode, &setup.maxKeyCode);
5646747b715Smrg
5656747b715Smrg    lenofblock = sizeof(xConnSetup) +
566f7df2e56Smrg        pad_to_int32(setup.nbytesVendor) +
567f7df2e56Smrg        (setup.numFormats * sizeof(xPixmapFormat)) +
568f7df2e56Smrg        (setup.numRoots * sizeof(xWindowRoot));
5696747b715Smrg    ConnectionInfo = malloc(lenofblock);
5706747b715Smrg    if (!ConnectionInfo)
571f7df2e56Smrg        return FALSE;
5726747b715Smrg
573f7df2e56Smrg    memmove(ConnectionInfo, (char *) &setup, sizeof(xConnSetup));
5746747b715Smrg    sizesofar = sizeof(xConnSetup);
5756747b715Smrg    pBuf = ConnectionInfo + sizeof(xConnSetup);
5766747b715Smrg
577f7df2e56Smrg    memmove(pBuf, VendorString, (int) setup.nbytesVendor);
5786747b715Smrg    sizesofar += setup.nbytesVendor;
5796747b715Smrg    pBuf += setup.nbytesVendor;
580f7df2e56Smrg    i = padding_for_int32(setup.nbytesVendor);
5816747b715Smrg    sizesofar += i;
5826747b715Smrg    while (--i >= 0)
583f7df2e56Smrg        *pBuf++ = 0;
5846747b715Smrg
5856747b715Smrg    memset(&format, 0, sizeof(xPixmapFormat));
586f7df2e56Smrg    for (i = 0; i < screenInfo.numPixmapFormats; i++) {
587f7df2e56Smrg        format.depth = screenInfo.formats[i].depth;
588f7df2e56Smrg        format.bitsPerPixel = screenInfo.formats[i].bitsPerPixel;
589f7df2e56Smrg        format.scanLinePad = screenInfo.formats[i].scanlinePad;
590f7df2e56Smrg        memmove(pBuf, (char *) &format, sizeof(xPixmapFormat));
591f7df2e56Smrg        pBuf += sizeof(xPixmapFormat);
592f7df2e56Smrg        sizesofar += sizeof(xPixmapFormat);
5936747b715Smrg    }
5946747b715Smrg
5956747b715Smrg    connBlockScreenStart = sizesofar;
5966747b715Smrg    memset(&depth, 0, sizeof(xDepth));
5976747b715Smrg    memset(&visual, 0, sizeof(xVisualType));
598f7df2e56Smrg    for (i = 0; i < screenInfo.numScreens; i++) {
599f7df2e56Smrg        ScreenPtr pScreen;
600f7df2e56Smrg        DepthPtr pDepth;
601f7df2e56Smrg        VisualPtr pVisual;
602f7df2e56Smrg
603f7df2e56Smrg        pScreen = screenInfo.screens[i];
604f7df2e56Smrg        root.windowId = pScreen->root->drawable.id;
605f7df2e56Smrg        root.defaultColormap = pScreen->defColormap;
606f7df2e56Smrg        root.whitePixel = pScreen->whitePixel;
607f7df2e56Smrg        root.blackPixel = pScreen->blackPixel;
608f7df2e56Smrg        root.currentInputMask = 0;      /* filled in when sent */
609f7df2e56Smrg        root.pixWidth = pScreen->width;
610f7df2e56Smrg        root.pixHeight = pScreen->height;
611f7df2e56Smrg        root.mmWidth = pScreen->mmWidth;
612f7df2e56Smrg        root.mmHeight = pScreen->mmHeight;
613f7df2e56Smrg        root.minInstalledMaps = pScreen->minInstalledCmaps;
614f7df2e56Smrg        root.maxInstalledMaps = pScreen->maxInstalledCmaps;
615f7df2e56Smrg        root.rootVisualID = pScreen->rootVisual;
616f7df2e56Smrg        root.backingStore = pScreen->backingStoreSupport;
617f7df2e56Smrg        root.saveUnders = FALSE;
618f7df2e56Smrg        root.rootDepth = pScreen->rootDepth;
619f7df2e56Smrg        root.nDepths = pScreen->numDepths;
620f7df2e56Smrg        memmove(pBuf, (char *) &root, sizeof(xWindowRoot));
621f7df2e56Smrg        sizesofar += sizeof(xWindowRoot);
622f7df2e56Smrg        pBuf += sizeof(xWindowRoot);
623f7df2e56Smrg
624f7df2e56Smrg        pDepth = pScreen->allowedDepths;
625f7df2e56Smrg        for (j = 0; j < pScreen->numDepths; j++, pDepth++) {
626f7df2e56Smrg            lenofblock += sizeof(xDepth) +
627f7df2e56Smrg                (pDepth->numVids * sizeof(xVisualType));
628f7df2e56Smrg            pBuf = (char *) realloc(ConnectionInfo, lenofblock);
629f7df2e56Smrg            if (!pBuf) {
630f7df2e56Smrg                free(ConnectionInfo);
631f7df2e56Smrg                return FALSE;
632f7df2e56Smrg            }
633f7df2e56Smrg            ConnectionInfo = pBuf;
634f7df2e56Smrg            pBuf += sizesofar;
635f7df2e56Smrg            depth.depth = pDepth->depth;
636f7df2e56Smrg            depth.nVisuals = pDepth->numVids;
637f7df2e56Smrg            memmove(pBuf, (char *) &depth, sizeof(xDepth));
638f7df2e56Smrg            pBuf += sizeof(xDepth);
639f7df2e56Smrg            sizesofar += sizeof(xDepth);
640f7df2e56Smrg            for (k = 0; k < pDepth->numVids; k++) {
641f7df2e56Smrg                vid = pDepth->vids[k];
642f7df2e56Smrg                for (pVisual = pScreen->visuals;
643f7df2e56Smrg                     pVisual->vid != vid; pVisual++);
644f7df2e56Smrg                visual.visualID = vid;
645f7df2e56Smrg                visual.class = pVisual->class;
646f7df2e56Smrg                visual.bitsPerRGB = pVisual->bitsPerRGBValue;
647f7df2e56Smrg                visual.colormapEntries = pVisual->ColormapEntries;
648f7df2e56Smrg                visual.redMask = pVisual->redMask;
649f7df2e56Smrg                visual.greenMask = pVisual->greenMask;
650f7df2e56Smrg                visual.blueMask = pVisual->blueMask;
651f7df2e56Smrg                memmove(pBuf, (char *) &visual, sizeof(xVisualType));
652f7df2e56Smrg                pBuf += sizeof(xVisualType);
653f7df2e56Smrg                sizesofar += sizeof(xVisualType);
654f7df2e56Smrg            }
655f7df2e56Smrg        }
6566747b715Smrg    }
6576747b715Smrg    connSetupPrefix.success = xTrue;
658f7df2e56Smrg    connSetupPrefix.length = lenofblock / 4;
6596747b715Smrg    connSetupPrefix.majorVersion = X_PROTOCOL;
6606747b715Smrg    connSetupPrefix.minorVersion = X_PROTOCOL_REVISION;
6616747b715Smrg    return TRUE;
6626747b715Smrg}
6636747b715Smrg
6646747b715Smrgint
66505b261ecSmrgProcBadRequest(ClientPtr client)
66605b261ecSmrg{
6676747b715Smrg    return BadRequest;
66805b261ecSmrg}
66905b261ecSmrg
67005b261ecSmrgint
67105b261ecSmrgProcCreateWindow(ClientPtr client)
67205b261ecSmrg{
67305b261ecSmrg    WindowPtr pParent, pWin;
674f7df2e56Smrg
67505b261ecSmrg    REQUEST(xCreateWindowReq);
6764642e01fSmrg    int len, rc;
67705b261ecSmrg
67805b261ecSmrg    REQUEST_AT_LEAST_SIZE(xCreateWindowReq);
679f7df2e56Smrg
68005b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->wid, client);
6814642e01fSmrg    rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess);
68205b261ecSmrg    if (rc != Success)
68305b261ecSmrg        return rc;
6846747b715Smrg    len = client->req_len - bytes_to_int32(sizeof(xCreateWindowReq));
68505b261ecSmrg    if (Ones(stuff->mask) != len)
68605b261ecSmrg        return BadLength;
687f7df2e56Smrg    if (!stuff->width || !stuff->height) {
688f7df2e56Smrg        client->errorValue = 0;
68905b261ecSmrg        return BadValue;
69005b261ecSmrg    }
69105b261ecSmrg    pWin = CreateWindow(stuff->wid, pParent, stuff->x,
692f7df2e56Smrg                        stuff->y, stuff->width, stuff->height,
693f7df2e56Smrg                        stuff->borderWidth, stuff->class,
694f7df2e56Smrg                        stuff->mask, (XID *) &stuff[1],
695f7df2e56Smrg                        (int) stuff->depth, client, stuff->visual, &rc);
696f7df2e56Smrg    if (pWin) {
697f7df2e56Smrg        Mask mask = pWin->eventMask;
698f7df2e56Smrg
699f7df2e56Smrg        pWin->eventMask = 0;    /* subterfuge in case AddResource fails */
700f7df2e56Smrg        if (!AddResource(stuff->wid, RT_WINDOW, (void *) pWin))
701f7df2e56Smrg            return BadAlloc;
702f7df2e56Smrg        pWin->eventMask = mask;
70305b261ecSmrg    }
7046747b715Smrg    return rc;
70505b261ecSmrg}
70605b261ecSmrg
70705b261ecSmrgint
70805b261ecSmrgProcChangeWindowAttributes(ClientPtr client)
70905b261ecSmrg{
71005b261ecSmrg    WindowPtr pWin;
711f7df2e56Smrg
71205b261ecSmrg    REQUEST(xChangeWindowAttributesReq);
7136747b715Smrg    int len, rc;
7144642e01fSmrg    Mask access_mode = 0;
71505b261ecSmrg
71605b261ecSmrg    REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq);
7174642e01fSmrg    access_mode |= (stuff->valueMask & CWEventMask) ? DixReceiveAccess : 0;
7184642e01fSmrg    access_mode |= (stuff->valueMask & ~CWEventMask) ? DixSetAttrAccess : 0;
7194642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, access_mode);
72005b261ecSmrg    if (rc != Success)
72105b261ecSmrg        return rc;
7226747b715Smrg    len = client->req_len - bytes_to_int32(sizeof(xChangeWindowAttributesReq));
72305b261ecSmrg    if (len != Ones(stuff->valueMask))
72405b261ecSmrg        return BadLength;
7256747b715Smrg    return ChangeWindowAttributes(pWin,
726f7df2e56Smrg                                  stuff->valueMask, (XID *) &stuff[1], client);
72705b261ecSmrg}
72805b261ecSmrg
72905b261ecSmrgint
73005b261ecSmrgProcGetWindowAttributes(ClientPtr client)
73105b261ecSmrg{
73205b261ecSmrg    WindowPtr pWin;
733f7df2e56Smrg
73405b261ecSmrg    REQUEST(xResourceReq);
73505b261ecSmrg    xGetWindowAttributesReply wa;
73605b261ecSmrg    int rc;
73705b261ecSmrg
73805b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
7394642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
74005b261ecSmrg    if (rc != Success)
741f7df2e56Smrg        return rc;
7426747b715Smrg    memset(&wa, 0, sizeof(xGetWindowAttributesReply));
74305b261ecSmrg    GetWindowAttributes(pWin, client, &wa);
74405b261ecSmrg    WriteReplyToClient(client, sizeof(xGetWindowAttributesReply), &wa);
7456747b715Smrg    return Success;
74605b261ecSmrg}
74705b261ecSmrg
74805b261ecSmrgint
74905b261ecSmrgProcDestroyWindow(ClientPtr client)
75005b261ecSmrg{
75105b261ecSmrg    WindowPtr pWin;
752f7df2e56Smrg
75305b261ecSmrg    REQUEST(xResourceReq);
75405b261ecSmrg    int rc;
75505b261ecSmrg
75605b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
75705b261ecSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixDestroyAccess);
75805b261ecSmrg    if (rc != Success)
759f7df2e56Smrg        return rc;
7604642e01fSmrg    if (pWin->parent) {
761f7df2e56Smrg        rc = dixLookupWindow(&pWin, pWin->parent->drawable.id, client,
762f7df2e56Smrg                             DixRemoveAccess);
763f7df2e56Smrg        if (rc != Success)
764f7df2e56Smrg            return rc;
765f7df2e56Smrg        FreeResource(stuff->id, RT_NONE);
7664642e01fSmrg    }
7676747b715Smrg    return Success;
76805b261ecSmrg}
76905b261ecSmrg
77005b261ecSmrgint
77105b261ecSmrgProcDestroySubwindows(ClientPtr client)
77205b261ecSmrg{
77305b261ecSmrg    WindowPtr pWin;
774f7df2e56Smrg
77505b261ecSmrg    REQUEST(xResourceReq);
77605b261ecSmrg    int rc;
77705b261ecSmrg
77805b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
7794642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixRemoveAccess);
78005b261ecSmrg    if (rc != Success)
781f7df2e56Smrg        return rc;
78205b261ecSmrg    DestroySubwindows(pWin, client);
7836747b715Smrg    return Success;
78405b261ecSmrg}
78505b261ecSmrg
78605b261ecSmrgint
78705b261ecSmrgProcChangeSaveSet(ClientPtr client)
78805b261ecSmrg{
78905b261ecSmrg    WindowPtr pWin;
790f7df2e56Smrg
79105b261ecSmrg    REQUEST(xChangeSaveSetReq);
7926747b715Smrg    int rc;
793f7df2e56Smrg
79405b261ecSmrg    REQUEST_SIZE_MATCH(xChangeSaveSetReq);
7954642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
79605b261ecSmrg    if (rc != Success)
79705b261ecSmrg        return rc;
79805b261ecSmrg    if (client->clientAsMask == (CLIENT_BITS(pWin->drawable.id)))
79905b261ecSmrg        return BadMatch;
80005b261ecSmrg    if ((stuff->mode == SetModeInsert) || (stuff->mode == SetModeDelete))
8016747b715Smrg        return AlterSaveSetForClient(client, pWin, stuff->mode, FALSE, TRUE);
8026747b715Smrg    client->errorValue = stuff->mode;
8036747b715Smrg    return BadValue;
80405b261ecSmrg}
80505b261ecSmrg
80605b261ecSmrgint
80705b261ecSmrgProcReparentWindow(ClientPtr client)
80805b261ecSmrg{
80905b261ecSmrg    WindowPtr pWin, pParent;
810f7df2e56Smrg
81105b261ecSmrg    REQUEST(xReparentWindowReq);
8126747b715Smrg    int rc;
81305b261ecSmrg
81405b261ecSmrg    REQUEST_SIZE_MATCH(xReparentWindowReq);
8154642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
81605b261ecSmrg    if (rc != Success)
81705b261ecSmrg        return rc;
8184642e01fSmrg    rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess);
81905b261ecSmrg    if (rc != Success)
82005b261ecSmrg        return rc;
8216747b715Smrg    if (!SAME_SCREENS(pWin->drawable, pParent->drawable))
822f7df2e56Smrg        return BadMatch;
8236747b715Smrg    if ((pWin->backgroundState == ParentRelative) &&
824f7df2e56Smrg        (pParent->drawable.depth != pWin->drawable.depth))
825f7df2e56Smrg        return BadMatch;
8266747b715Smrg    if ((pWin->drawable.class != InputOnly) &&
827f7df2e56Smrg        (pParent->drawable.class == InputOnly))
828f7df2e56Smrg        return BadMatch;
8296747b715Smrg    return ReparentWindow(pWin, pParent,
830f7df2e56Smrg                          (short) stuff->x, (short) stuff->y, client);
83105b261ecSmrg}
83205b261ecSmrg
83305b261ecSmrgint
83405b261ecSmrgProcMapWindow(ClientPtr client)
83505b261ecSmrg{
83605b261ecSmrg    WindowPtr pWin;
837f7df2e56Smrg
83805b261ecSmrg    REQUEST(xResourceReq);
83905b261ecSmrg    int rc;
84005b261ecSmrg
84105b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
8424642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixShowAccess);
84305b261ecSmrg    if (rc != Success)
84405b261ecSmrg        return rc;
84505b261ecSmrg    MapWindow(pWin, client);
846f7df2e56Smrg    /* update cache to say it is mapped */
8476747b715Smrg    return Success;
84805b261ecSmrg}
84905b261ecSmrg
85005b261ecSmrgint
85105b261ecSmrgProcMapSubwindows(ClientPtr client)
85205b261ecSmrg{
85305b261ecSmrg    WindowPtr pWin;
854f7df2e56Smrg
85505b261ecSmrg    REQUEST(xResourceReq);
85605b261ecSmrg    int rc;
85705b261ecSmrg
85805b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
8594642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
86005b261ecSmrg    if (rc != Success)
86105b261ecSmrg        return rc;
86205b261ecSmrg    MapSubwindows(pWin, client);
863f7df2e56Smrg    /* update cache to say it is mapped */
8646747b715Smrg    return Success;
86505b261ecSmrg}
86605b261ecSmrg
86705b261ecSmrgint
86805b261ecSmrgProcUnmapWindow(ClientPtr client)
86905b261ecSmrg{
87005b261ecSmrg    WindowPtr pWin;
871f7df2e56Smrg
87205b261ecSmrg    REQUEST(xResourceReq);
87305b261ecSmrg    int rc;
87405b261ecSmrg
87505b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
8764642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixHideAccess);
87705b261ecSmrg    if (rc != Success)
87805b261ecSmrg        return rc;
87905b261ecSmrg    UnmapWindow(pWin, FALSE);
880f7df2e56Smrg    /* update cache to say it is mapped */
8816747b715Smrg    return Success;
88205b261ecSmrg}
88305b261ecSmrg
88405b261ecSmrgint
88505b261ecSmrgProcUnmapSubwindows(ClientPtr client)
88605b261ecSmrg{
88705b261ecSmrg    WindowPtr pWin;
888f7df2e56Smrg
88905b261ecSmrg    REQUEST(xResourceReq);
89005b261ecSmrg    int rc;
89105b261ecSmrg
89205b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
8934642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
89405b261ecSmrg    if (rc != Success)
89505b261ecSmrg        return rc;
89605b261ecSmrg    UnmapSubwindows(pWin);
8976747b715Smrg    return Success;
89805b261ecSmrg}
89905b261ecSmrg
90005b261ecSmrgint
90105b261ecSmrgProcConfigureWindow(ClientPtr client)
90205b261ecSmrg{
90305b261ecSmrg    WindowPtr pWin;
904f7df2e56Smrg
90505b261ecSmrg    REQUEST(xConfigureWindowReq);
90605b261ecSmrg    int len, rc;
90705b261ecSmrg
90805b261ecSmrg    REQUEST_AT_LEAST_SIZE(xConfigureWindowReq);
9094642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client,
910f7df2e56Smrg                         DixManageAccess | DixSetAttrAccess);
91105b261ecSmrg    if (rc != Success)
91205b261ecSmrg        return rc;
9136747b715Smrg    len = client->req_len - bytes_to_int32(sizeof(xConfigureWindowReq));
914f7df2e56Smrg    if (Ones((Mask) stuff->mask) != len)
91505b261ecSmrg        return BadLength;
916f7df2e56Smrg    return ConfigureWindow(pWin, (Mask) stuff->mask, (XID *) &stuff[1], client);
91705b261ecSmrg}
91805b261ecSmrg
91905b261ecSmrgint
92005b261ecSmrgProcCirculateWindow(ClientPtr client)
92105b261ecSmrg{
92205b261ecSmrg    WindowPtr pWin;
923f7df2e56Smrg
92405b261ecSmrg    REQUEST(xCirculateWindowReq);
92505b261ecSmrg    int rc;
92605b261ecSmrg
92705b261ecSmrg    REQUEST_SIZE_MATCH(xCirculateWindowReq);
928f7df2e56Smrg    if ((stuff->direction != RaiseLowest) && (stuff->direction != LowerHighest)) {
929f7df2e56Smrg        client->errorValue = stuff->direction;
93005b261ecSmrg        return BadValue;
93105b261ecSmrg    }
9324642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
93305b261ecSmrg    if (rc != Success)
93405b261ecSmrg        return rc;
935f7df2e56Smrg    CirculateWindow(pWin, (int) stuff->direction, client);
9366747b715Smrg    return Success;
93705b261ecSmrg}
93805b261ecSmrg
93905b261ecSmrgstatic int
940f7df2e56SmrgGetGeometry(ClientPtr client, xGetGeometryReply * rep)
94105b261ecSmrg{
94205b261ecSmrg    DrawablePtr pDraw;
94305b261ecSmrg    int rc;
944f7df2e56Smrg
94505b261ecSmrg    REQUEST(xResourceReq);
94605b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
94705b261ecSmrg
9484642e01fSmrg    rc = dixLookupDrawable(&pDraw, stuff->id, client, M_ANY, DixGetAttrAccess);
94905b261ecSmrg    if (rc != Success)
950f7df2e56Smrg        return rc;
95105b261ecSmrg
95205b261ecSmrg    rep->type = X_Reply;
95305b261ecSmrg    rep->length = 0;
95405b261ecSmrg    rep->sequenceNumber = client->sequence;
9556747b715Smrg    rep->root = pDraw->pScreen->root->drawable.id;
95605b261ecSmrg    rep->depth = pDraw->depth;
95705b261ecSmrg    rep->width = pDraw->width;
95805b261ecSmrg    rep->height = pDraw->height;
95905b261ecSmrg
960f7df2e56Smrg    if (WindowDrawable(pDraw->type)) {
961f7df2e56Smrg        WindowPtr pWin = (WindowPtr) pDraw;
962f7df2e56Smrg
963f7df2e56Smrg        rep->x = pWin->origin.x - wBorderWidth(pWin);
964f7df2e56Smrg        rep->y = pWin->origin.y - wBorderWidth(pWin);
965f7df2e56Smrg        rep->borderWidth = pWin->borderWidth;
96605b261ecSmrg    }
967f7df2e56Smrg    else {                      /* DRAWABLE_PIXMAP */
968f7df2e56Smrg
969f7df2e56Smrg        rep->x = rep->y = rep->borderWidth = 0;
97005b261ecSmrg    }
97105b261ecSmrg
97205b261ecSmrg    return Success;
97305b261ecSmrg}
97405b261ecSmrg
97505b261ecSmrgint
97605b261ecSmrgProcGetGeometry(ClientPtr client)
97705b261ecSmrg{
978f7df2e56Smrg    xGetGeometryReply rep = { .type = X_Reply };
97905b261ecSmrg    int status;
98005b261ecSmrg
98105b261ecSmrg    if ((status = GetGeometry(client, &rep)) != Success)
982f7df2e56Smrg        return status;
98305b261ecSmrg
98405b261ecSmrg    WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep);
9856747b715Smrg    return Success;
98605b261ecSmrg}
98705b261ecSmrg
98805b261ecSmrgint
98905b261ecSmrgProcQueryTree(ClientPtr client)
99005b261ecSmrg{
99105b261ecSmrg    xQueryTreeReply reply;
99205b261ecSmrg    int rc, numChildren = 0;
99305b261ecSmrg    WindowPtr pChild, pWin, pHead;
994f7df2e56Smrg    Window *childIDs = (Window *) NULL;
995f7df2e56Smrg
99605b261ecSmrg    REQUEST(xResourceReq);
99705b261ecSmrg
99805b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
9994642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
100005b261ecSmrg    if (rc != Success)
100105b261ecSmrg        return rc;
1002f7df2e56Smrg
1003f7df2e56Smrg    reply = (xQueryTreeReply) {
1004f7df2e56Smrg        .type = X_Reply,
1005f7df2e56Smrg        .sequenceNumber = client->sequence,
1006f7df2e56Smrg        .root = pWin->drawable.pScreen->root->drawable.id,
1007f7df2e56Smrg        .parent = (pWin->parent) ? pWin->parent->drawable.id : (Window) None
1008f7df2e56Smrg    };
100905b261ecSmrg    pHead = RealChildHead(pWin);
101005b261ecSmrg    for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib)
1011f7df2e56Smrg        numChildren++;
1012f7df2e56Smrg    if (numChildren) {
1013f7df2e56Smrg        int curChild = 0;
101405b261ecSmrg
1015f7df2e56Smrg        childIDs = xallocarray(numChildren, sizeof(Window));
1016f7df2e56Smrg        if (!childIDs)
1017f7df2e56Smrg            return BadAlloc;
1018f7df2e56Smrg        for (pChild = pWin->lastChild; pChild != pHead;
1019f7df2e56Smrg             pChild = pChild->prevSib)
1020f7df2e56Smrg            childIDs[curChild++] = pChild->drawable.id;
102105b261ecSmrg    }
1022f7df2e56Smrg
102305b261ecSmrg    reply.nChildren = numChildren;
10246747b715Smrg    reply.length = bytes_to_int32(numChildren * sizeof(Window));
1025f7df2e56Smrg
102605b261ecSmrg    WriteReplyToClient(client, sizeof(xQueryTreeReply), &reply);
1027f7df2e56Smrg    if (numChildren) {
1028f7df2e56Smrg        client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
1029f7df2e56Smrg        WriteSwappedDataToClient(client, numChildren * sizeof(Window),
1030f7df2e56Smrg                                 childIDs);
1031f7df2e56Smrg        free(childIDs);
103205b261ecSmrg    }
103305b261ecSmrg
10346747b715Smrg    return Success;
103505b261ecSmrg}
103605b261ecSmrg
103705b261ecSmrgint
103805b261ecSmrgProcInternAtom(ClientPtr client)
103905b261ecSmrg{
104005b261ecSmrg    Atom atom;
104105b261ecSmrg    char *tchar;
1042f7df2e56Smrg
104305b261ecSmrg    REQUEST(xInternAtomReq);
104405b261ecSmrg
104505b261ecSmrg    REQUEST_FIXED_SIZE(xInternAtomReq, stuff->nbytes);
1046f7df2e56Smrg    if ((stuff->onlyIfExists != xTrue) && (stuff->onlyIfExists != xFalse)) {
1047f7df2e56Smrg        client->errorValue = stuff->onlyIfExists;
10486747b715Smrg        return BadValue;
104905b261ecSmrg    }
105005b261ecSmrg    tchar = (char *) &stuff[1];
105105b261ecSmrg    atom = MakeAtom(tchar, stuff->nbytes, !stuff->onlyIfExists);
1052f7df2e56Smrg    if (atom != BAD_RESOURCE) {
1053f7df2e56Smrg        xInternAtomReply reply = {
1054f7df2e56Smrg            .type = X_Reply,
1055f7df2e56Smrg            .sequenceNumber = client->sequence,
1056f7df2e56Smrg            .length = 0,
1057f7df2e56Smrg            .atom = atom
1058f7df2e56Smrg        };
1059f7df2e56Smrg        WriteReplyToClient(client, sizeof(xInternAtomReply), &reply);
1060f7df2e56Smrg        return Success;
106105b261ecSmrg    }
106205b261ecSmrg    else
1063f7df2e56Smrg        return BadAlloc;
106405b261ecSmrg}
106505b261ecSmrg
106605b261ecSmrgint
106705b261ecSmrgProcGetAtomName(ClientPtr client)
106805b261ecSmrg{
10696747b715Smrg    const char *str;
1070f7df2e56Smrg
107105b261ecSmrg    REQUEST(xResourceReq);
107205b261ecSmrg
107305b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
1074f7df2e56Smrg    if ((str = NameForAtom(stuff->id))) {
1075f7df2e56Smrg        int len = strlen(str);
1076f7df2e56Smrg        xGetAtomNameReply reply = {
1077f7df2e56Smrg            .type = X_Reply,
1078f7df2e56Smrg            .sequenceNumber = client->sequence,
1079f7df2e56Smrg            .length = bytes_to_int32(len),
1080f7df2e56Smrg            .nameLength = len
1081f7df2e56Smrg        };
1082f7df2e56Smrg
1083f7df2e56Smrg        WriteReplyToClient(client, sizeof(xGetAtomNameReply), &reply);
1084f7df2e56Smrg        WriteToClient(client, len, str);
1085f7df2e56Smrg        return Success;
108605b261ecSmrg    }
1087f7df2e56Smrg    else {
1088f7df2e56Smrg        client->errorValue = stuff->id;
1089f7df2e56Smrg        return BadAtom;
109005b261ecSmrg    }
109105b261ecSmrg}
109205b261ecSmrg
109305b261ecSmrgint
109405b261ecSmrgProcGrabServer(ClientPtr client)
109505b261ecSmrg{
10964642e01fSmrg    int rc;
1097f7df2e56Smrg
109805b261ecSmrg    REQUEST_SIZE_MATCH(xReq);
1099f7df2e56Smrg    if (grabState != GrabNone && client != grabClient) {
1100f7df2e56Smrg        ResetCurrentRequest(client);
1101f7df2e56Smrg        client->sequence--;
1102f7df2e56Smrg        BITSET(grabWaiters, client->index);
1103f7df2e56Smrg        IgnoreClient(client);
1104f7df2e56Smrg        return Success;
110505b261ecSmrg    }
11064642e01fSmrg    rc = OnlyListenToOneClient(client);
11074642e01fSmrg    if (rc != Success)
1108f7df2e56Smrg        return rc;
11097e31ba66Smrg    grabState = GrabActive;
111005b261ecSmrg    grabClient = client;
11117e31ba66Smrg    mark_client_grab(client);
111205b261ecSmrg
1113f7df2e56Smrg    if (ServerGrabCallback) {
1114f7df2e56Smrg        ServerGrabInfoRec grabinfo;
1115f7df2e56Smrg
1116f7df2e56Smrg        grabinfo.client = client;
1117f7df2e56Smrg        grabinfo.grabstate = SERVER_GRABBED;
1118f7df2e56Smrg        CallCallbacks(&ServerGrabCallback, (void *) &grabinfo);
111905b261ecSmrg    }
112005b261ecSmrg
11216747b715Smrg    return Success;
112205b261ecSmrg}
112305b261ecSmrg
112405b261ecSmrgstatic void
112505b261ecSmrgUngrabServer(ClientPtr client)
112605b261ecSmrg{
112705b261ecSmrg    int i;
112805b261ecSmrg
112905b261ecSmrg    grabState = GrabNone;
113005b261ecSmrg    ListenToAllClients();
11317e31ba66Smrg    mark_client_ungrab();
1132f7df2e56Smrg    for (i = mskcnt; --i >= 0 && !grabWaiters[i];);
1133f7df2e56Smrg    if (i >= 0) {
1134f7df2e56Smrg        i <<= 5;
1135f7df2e56Smrg        while (!GETBIT(grabWaiters, i))
1136f7df2e56Smrg            i++;
1137f7df2e56Smrg        BITCLEAR(grabWaiters, i);
1138f7df2e56Smrg        AttendClient(clients[i]);
113905b261ecSmrg    }
114005b261ecSmrg
1141f7df2e56Smrg    if (ServerGrabCallback) {
1142f7df2e56Smrg        ServerGrabInfoRec grabinfo;
1143f7df2e56Smrg
1144f7df2e56Smrg        grabinfo.client = client;
1145f7df2e56Smrg        grabinfo.grabstate = SERVER_UNGRABBED;
1146f7df2e56Smrg        CallCallbacks(&ServerGrabCallback, (void *) &grabinfo);
114705b261ecSmrg    }
114805b261ecSmrg}
114905b261ecSmrg
115005b261ecSmrgint
115105b261ecSmrgProcUngrabServer(ClientPtr client)
115205b261ecSmrg{
115305b261ecSmrg    REQUEST_SIZE_MATCH(xReq);
115405b261ecSmrg    UngrabServer(client);
11556747b715Smrg    return Success;
115605b261ecSmrg}
115705b261ecSmrg
115805b261ecSmrgint
115905b261ecSmrgProcTranslateCoords(ClientPtr client)
116005b261ecSmrg{
116105b261ecSmrg    REQUEST(xTranslateCoordsReq);
116205b261ecSmrg
116305b261ecSmrg    WindowPtr pWin, pDst;
116405b261ecSmrg    xTranslateCoordsReply rep;
116505b261ecSmrg    int rc;
116605b261ecSmrg
116705b261ecSmrg    REQUEST_SIZE_MATCH(xTranslateCoordsReq);
11684642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->srcWid, client, DixGetAttrAccess);
116905b261ecSmrg    if (rc != Success)
117005b261ecSmrg        return rc;
11714642e01fSmrg    rc = dixLookupWindow(&pDst, stuff->dstWid, client, DixGetAttrAccess);
117205b261ecSmrg    if (rc != Success)
117305b261ecSmrg        return rc;
1174f7df2e56Smrg
1175f7df2e56Smrg    rep = (xTranslateCoordsReply) {
1176f7df2e56Smrg        .type = X_Reply,
1177f7df2e56Smrg        .sequenceNumber = client->sequence,
1178f7df2e56Smrg        .length = 0
1179f7df2e56Smrg    };
1180f7df2e56Smrg    if (!SAME_SCREENS(pWin->drawable, pDst->drawable)) {
1181f7df2e56Smrg        rep.sameScreen = xFalse;
118205b261ecSmrg        rep.child = None;
1183f7df2e56Smrg        rep.dstX = rep.dstY = 0;
118405b261ecSmrg    }
1185f7df2e56Smrg    else {
1186f7df2e56Smrg        INT16 x, y;
1187f7df2e56Smrg
1188f7df2e56Smrg        rep.sameScreen = xTrue;
1189f7df2e56Smrg        rep.child = None;
1190f7df2e56Smrg        /* computing absolute coordinates -- adjust to destination later */
1191f7df2e56Smrg        x = pWin->drawable.x + stuff->srcX;
1192f7df2e56Smrg        y = pWin->drawable.y + stuff->srcY;
1193f7df2e56Smrg        pWin = pDst->firstChild;
1194f7df2e56Smrg        while (pWin) {
1195f7df2e56Smrg            BoxRec box;
1196f7df2e56Smrg
1197f7df2e56Smrg            if ((pWin->mapped) &&
1198f7df2e56Smrg                (x >= pWin->drawable.x - wBorderWidth(pWin)) &&
1199f7df2e56Smrg                (x < pWin->drawable.x + (int) pWin->drawable.width +
1200f7df2e56Smrg                 wBorderWidth(pWin)) &&
1201f7df2e56Smrg                (y >= pWin->drawable.y - wBorderWidth(pWin)) &&
1202f7df2e56Smrg                (y < pWin->drawable.y + (int) pWin->drawable.height +
1203f7df2e56Smrg                 wBorderWidth(pWin))
1204f7df2e56Smrg                /* When a window is shaped, a further check
1205f7df2e56Smrg                 * is made to see if the point is inside
1206f7df2e56Smrg                 * borderSize
1207f7df2e56Smrg                 */
1208f7df2e56Smrg                && (!wBoundingShape(pWin) ||
1209f7df2e56Smrg                    RegionContainsPoint(&pWin->borderSize, x, y, &box))
1210f7df2e56Smrg
1211f7df2e56Smrg                && (!wInputShape(pWin) ||
1212f7df2e56Smrg                    RegionContainsPoint(wInputShape(pWin),
1213f7df2e56Smrg                                        x - pWin->drawable.x,
1214f7df2e56Smrg                                        y - pWin->drawable.y, &box))
1215f7df2e56Smrg                ) {
1216f7df2e56Smrg                rep.child = pWin->drawable.id;
1217f7df2e56Smrg                pWin = (WindowPtr) NULL;
1218f7df2e56Smrg            }
1219f7df2e56Smrg            else
1220f7df2e56Smrg                pWin = pWin->nextSib;
1221f7df2e56Smrg        }
1222f7df2e56Smrg        /* adjust to destination coordinates */
1223f7df2e56Smrg        rep.dstX = x - pDst->drawable.x;
1224f7df2e56Smrg        rep.dstY = y - pDst->drawable.y;
122505b261ecSmrg    }
122605b261ecSmrg    WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep);
12276747b715Smrg    return Success;
122805b261ecSmrg}
122905b261ecSmrg
123005b261ecSmrgint
123105b261ecSmrgProcOpenFont(ClientPtr client)
123205b261ecSmrg{
1233f7df2e56Smrg    int err;
1234f7df2e56Smrg
123505b261ecSmrg    REQUEST(xOpenFontReq);
123605b261ecSmrg
123705b261ecSmrg    REQUEST_FIXED_SIZE(xOpenFontReq, stuff->nbytes);
123805b261ecSmrg    client->errorValue = stuff->fid;
123905b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->fid, client);
124005b261ecSmrg    err = OpenFont(client, stuff->fid, (Mask) 0,
1241f7df2e56Smrg                   stuff->nbytes, (char *) &stuff[1]);
1242f7df2e56Smrg    if (err == Success) {
1243f7df2e56Smrg        return Success;
124405b261ecSmrg    }
124505b261ecSmrg    else
1246f7df2e56Smrg        return err;
124705b261ecSmrg}
124805b261ecSmrg
124905b261ecSmrgint
125005b261ecSmrgProcCloseFont(ClientPtr client)
125105b261ecSmrg{
125205b261ecSmrg    FontPtr pFont;
12536747b715Smrg    int rc;
1254f7df2e56Smrg
125505b261ecSmrg    REQUEST(xResourceReq);
125605b261ecSmrg
125705b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
1258f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pFont, stuff->id, RT_FONT,
1259f7df2e56Smrg                                 client, DixDestroyAccess);
1260f7df2e56Smrg    if (rc == Success) {
126105b261ecSmrg        FreeResource(stuff->id, RT_NONE);
1262f7df2e56Smrg        return Success;
126305b261ecSmrg    }
1264f7df2e56Smrg    else {
1265f7df2e56Smrg        client->errorValue = stuff->id;
12666747b715Smrg        return rc;
126705b261ecSmrg    }
126805b261ecSmrg}
126905b261ecSmrg
127005b261ecSmrgint
127105b261ecSmrgProcQueryFont(ClientPtr client)
127205b261ecSmrg{
1273f7df2e56Smrg    xQueryFontReply *reply;
127405b261ecSmrg    FontPtr pFont;
12754642e01fSmrg    int rc;
1276f7df2e56Smrg
127705b261ecSmrg    REQUEST(xResourceReq);
127805b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
12794642e01fSmrg
12806747b715Smrg    rc = dixLookupFontable(&pFont, stuff->id, client, DixGetAttrAccess);
12814642e01fSmrg    if (rc != Success)
1282f7df2e56Smrg        return rc;
128305b261ecSmrg
128405b261ecSmrg    {
1285f7df2e56Smrg        xCharInfo *pmax = FONTINKMAX(pFont);
1286f7df2e56Smrg        xCharInfo *pmin = FONTINKMIN(pFont);
1287f7df2e56Smrg        int nprotoxcistructs;
1288f7df2e56Smrg        int rlength;
1289f7df2e56Smrg
1290f7df2e56Smrg        nprotoxcistructs = (pmax->rightSideBearing == pmin->rightSideBearing &&
1291f7df2e56Smrg                            pmax->leftSideBearing == pmin->leftSideBearing &&
1292f7df2e56Smrg                            pmax->descent == pmin->descent &&
1293f7df2e56Smrg                            pmax->ascent == pmin->ascent &&
1294f7df2e56Smrg                            pmax->characterWidth == pmin->characterWidth) ?
1295f7df2e56Smrg            0 : N2dChars(pFont);
1296f7df2e56Smrg
1297f7df2e56Smrg        rlength = sizeof(xQueryFontReply) +
1298f7df2e56Smrg            FONTINFONPROPS(FONTCHARSET(pFont)) * sizeof(xFontProp) +
1299f7df2e56Smrg            nprotoxcistructs * sizeof(xCharInfo);
1300f7df2e56Smrg        reply = calloc(1, rlength);
1301f7df2e56Smrg        if (!reply) {
1302f7df2e56Smrg            return BadAlloc;
1303f7df2e56Smrg        }
1304f7df2e56Smrg
1305f7df2e56Smrg        reply->type = X_Reply;
1306f7df2e56Smrg        reply->length = bytes_to_int32(rlength - sizeof(xGenericReply));
1307f7df2e56Smrg        reply->sequenceNumber = client->sequence;
1308f7df2e56Smrg        QueryFont(pFont, reply, nprotoxcistructs);
130905b261ecSmrg
131005b261ecSmrg        WriteReplyToClient(client, rlength, reply);
1311f7df2e56Smrg        free(reply);
1312f7df2e56Smrg        return Success;
131305b261ecSmrg    }
131405b261ecSmrg}
131505b261ecSmrg
131605b261ecSmrgint
131705b261ecSmrgProcQueryTextExtents(ClientPtr client)
131805b261ecSmrg{
131905b261ecSmrg    xQueryTextExtentsReply reply;
132005b261ecSmrg    FontPtr pFont;
132105b261ecSmrg    ExtentInfoRec info;
132205b261ecSmrg    unsigned long length;
13234642e01fSmrg    int rc;
1324f7df2e56Smrg
13254642e01fSmrg    REQUEST(xQueryTextExtentsReq);
132605b261ecSmrg    REQUEST_AT_LEAST_SIZE(xQueryTextExtentsReq);
1327f7df2e56Smrg
13286747b715Smrg    rc = dixLookupFontable(&pFont, stuff->fid, client, DixGetAttrAccess);
13294642e01fSmrg    if (rc != Success)
1330f7df2e56Smrg        return rc;
13314642e01fSmrg
13326747b715Smrg    length = client->req_len - bytes_to_int32(sizeof(xQueryTextExtentsReq));
133305b261ecSmrg    length = length << 1;
1334f7df2e56Smrg    if (stuff->oddLength) {
1335f7df2e56Smrg        if (length == 0)
1336f7df2e56Smrg            return BadLength;
133705b261ecSmrg        length--;
133805b261ecSmrg    }
13397e31ba66Smrg    if (!xfont2_query_text_extents(pFont, length, (unsigned char *) &stuff[1], &info))
1340f7df2e56Smrg        return BadAlloc;
1341f7df2e56Smrg    reply = (xQueryTextExtentsReply) {
1342f7df2e56Smrg        .type = X_Reply,
1343f7df2e56Smrg        .drawDirection = info.drawDirection,
1344f7df2e56Smrg        .sequenceNumber = client->sequence,
1345f7df2e56Smrg        .length = 0,
1346f7df2e56Smrg        .fontAscent = info.fontAscent,
1347f7df2e56Smrg        .fontDescent = info.fontDescent,
1348f7df2e56Smrg        .overallAscent = info.overallAscent,
1349f7df2e56Smrg        .overallDescent = info.overallDescent,
1350f7df2e56Smrg        .overallWidth = info.overallWidth,
1351f7df2e56Smrg        .overallLeft = info.overallLeft,
1352f7df2e56Smrg        .overallRight = info.overallRight
1353f7df2e56Smrg    };
135405b261ecSmrg    WriteReplyToClient(client, sizeof(xQueryTextExtentsReply), &reply);
13556747b715Smrg    return Success;
135605b261ecSmrg}
135705b261ecSmrg
135805b261ecSmrgint
135905b261ecSmrgProcListFonts(ClientPtr client)
136005b261ecSmrg{
136105b261ecSmrg    REQUEST(xListFontsReq);
136205b261ecSmrg
136305b261ecSmrg    REQUEST_FIXED_SIZE(xListFontsReq, stuff->nbytes);
136405b261ecSmrg
1365f7df2e56Smrg    return ListFonts(client, (unsigned char *) &stuff[1], stuff->nbytes,
1366f7df2e56Smrg                     stuff->maxNames);
136705b261ecSmrg}
136805b261ecSmrg
136905b261ecSmrgint
137005b261ecSmrgProcListFontsWithInfo(ClientPtr client)
137105b261ecSmrg{
137205b261ecSmrg    REQUEST(xListFontsWithInfoReq);
137305b261ecSmrg
137405b261ecSmrg    REQUEST_FIXED_SIZE(xListFontsWithInfoReq, stuff->nbytes);
137505b261ecSmrg
137605b261ecSmrg    return StartListFontsWithInfo(client, stuff->nbytes,
1377f7df2e56Smrg                                  (unsigned char *) &stuff[1], stuff->maxNames);
137805b261ecSmrg}
137905b261ecSmrg
138005b261ecSmrg/**
138105b261ecSmrg *
138205b261ecSmrg *  \param value must conform to DeleteType
138305b261ecSmrg */
138405b261ecSmrgint
1385f7df2e56SmrgdixDestroyPixmap(void *value, XID pid)
138605b261ecSmrg{
1387f7df2e56Smrg    PixmapPtr pPixmap = (PixmapPtr) value;
1388f7df2e56Smrg
1389f7df2e56Smrg    return (*pPixmap->drawable.pScreen->DestroyPixmap) (pPixmap);
139005b261ecSmrg}
139105b261ecSmrg
139205b261ecSmrgint
139305b261ecSmrgProcCreatePixmap(ClientPtr client)
139405b261ecSmrg{
139505b261ecSmrg    PixmapPtr pMap;
139605b261ecSmrg    DrawablePtr pDraw;
1397f7df2e56Smrg
139805b261ecSmrg    REQUEST(xCreatePixmapReq);
139905b261ecSmrg    DepthPtr pDepth;
140005b261ecSmrg    int i, rc;
140105b261ecSmrg
140205b261ecSmrg    REQUEST_SIZE_MATCH(xCreatePixmapReq);
140305b261ecSmrg    client->errorValue = stuff->pid;
140405b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->pid, client);
1405f7df2e56Smrg
140605b261ecSmrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
1407f7df2e56Smrg                           DixGetAttrAccess);
140805b261ecSmrg    if (rc != Success)
1409f7df2e56Smrg        return rc;
141005b261ecSmrg
1411f7df2e56Smrg    if (!stuff->width || !stuff->height) {
1412f7df2e56Smrg        client->errorValue = 0;
141305b261ecSmrg        return BadValue;
141405b261ecSmrg    }
1415f7df2e56Smrg    if (stuff->width > 32767 || stuff->height > 32767) {
1416f7df2e56Smrg        /* It is allowed to try and allocate a pixmap which is larger than
1417f7df2e56Smrg         * 32767 in either dimension. However, all of the framebuffer code
1418f7df2e56Smrg         * is buggy and does not reliably draw to such big pixmaps, basically
1419f7df2e56Smrg         * because the Region data structure operates with signed shorts
1420f7df2e56Smrg         * for the rectangles in it.
1421f7df2e56Smrg         *
1422f7df2e56Smrg         * Furthermore, several places in the X server computes the
1423f7df2e56Smrg         * size in bytes of the pixmap and tries to store it in an
1424f7df2e56Smrg         * integer. This integer can overflow and cause the allocated size
1425f7df2e56Smrg         * to be much smaller.
1426f7df2e56Smrg         *
1427f7df2e56Smrg         * So, such big pixmaps are rejected here with a BadAlloc
1428f7df2e56Smrg         */
1429f7df2e56Smrg        return BadAlloc;
1430f7df2e56Smrg    }
1431f7df2e56Smrg    if (stuff->depth != 1) {
143205b261ecSmrg        pDepth = pDraw->pScreen->allowedDepths;
1433f7df2e56Smrg        for (i = 0; i < pDraw->pScreen->numDepths; i++, pDepth++)
1434f7df2e56Smrg            if (pDepth->depth == stuff->depth)
1435f7df2e56Smrg                goto CreatePmap;
1436f7df2e56Smrg        client->errorValue = stuff->depth;
143705b261ecSmrg        return BadValue;
143805b261ecSmrg    }
1439f7df2e56Smrg CreatePmap:
1440f7df2e56Smrg    pMap = (PixmapPtr) (*pDraw->pScreen->CreatePixmap)
1441f7df2e56Smrg        (pDraw->pScreen, stuff->width, stuff->height, stuff->depth, 0);
1442f7df2e56Smrg    if (pMap) {
1443f7df2e56Smrg        pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
1444f7df2e56Smrg        pMap->drawable.id = stuff->pid;
1445f7df2e56Smrg        /* security creation/labeling check */
1446f7df2e56Smrg        rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, RT_PIXMAP,
1447f7df2e56Smrg                      pMap, RT_NONE, NULL, DixCreateAccess);
1448f7df2e56Smrg        if (rc != Success) {
1449f7df2e56Smrg            (*pDraw->pScreen->DestroyPixmap) (pMap);
1450f7df2e56Smrg            return rc;
1451f7df2e56Smrg        }
1452f7df2e56Smrg        if (AddResource(stuff->pid, RT_PIXMAP, (void *) pMap))
1453f7df2e56Smrg            return Success;
145405b261ecSmrg    }
14556747b715Smrg    return BadAlloc;
145605b261ecSmrg}
145705b261ecSmrg
145805b261ecSmrgint
145905b261ecSmrgProcFreePixmap(ClientPtr client)
146005b261ecSmrg{
146105b261ecSmrg    PixmapPtr pMap;
14624642e01fSmrg    int rc;
1463f7df2e56Smrg
146405b261ecSmrg    REQUEST(xResourceReq);
146505b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
14664642e01fSmrg
1467f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pMap, stuff->id, RT_PIXMAP,
1468f7df2e56Smrg                                 client, DixDestroyAccess);
1469f7df2e56Smrg    if (rc == Success) {
1470f7df2e56Smrg        FreeResource(stuff->id, RT_NONE);
1471f7df2e56Smrg        return Success;
147205b261ecSmrg    }
1473f7df2e56Smrg    else {
1474f7df2e56Smrg        client->errorValue = stuff->id;
1475f7df2e56Smrg        return rc;
147605b261ecSmrg    }
147705b261ecSmrg}
147805b261ecSmrg
147905b261ecSmrgint
148005b261ecSmrgProcCreateGC(ClientPtr client)
148105b261ecSmrg{
148205b261ecSmrg    int error, rc;
148305b261ecSmrg    GC *pGC;
148405b261ecSmrg    DrawablePtr pDraw;
148505b261ecSmrg    unsigned len;
1486f7df2e56Smrg
148705b261ecSmrg    REQUEST(xCreateGCReq);
148805b261ecSmrg
148905b261ecSmrg    REQUEST_AT_LEAST_SIZE(xCreateGCReq);
149005b261ecSmrg    client->errorValue = stuff->gc;
149105b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->gc, client);
14924642e01fSmrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
1493f7df2e56Smrg                           DixGetAttrAccess);
149405b261ecSmrg    if (rc != Success)
1495f7df2e56Smrg        return rc;
149605b261ecSmrg
1497f7df2e56Smrg    len = client->req_len - bytes_to_int32(sizeof(xCreateGCReq));
149805b261ecSmrg    if (len != Ones(stuff->mask))
149905b261ecSmrg        return BadLength;
1500f7df2e56Smrg    pGC = (GC *) CreateGC(pDraw, stuff->mask, (XID *) &stuff[1], &error,
1501f7df2e56Smrg                          stuff->gc, client);
150205b261ecSmrg    if (error != Success)
150305b261ecSmrg        return error;
1504f7df2e56Smrg    if (!AddResource(stuff->gc, RT_GC, (void *) pGC))
1505f7df2e56Smrg        return BadAlloc;
15066747b715Smrg    return Success;
150705b261ecSmrg}
150805b261ecSmrg
150905b261ecSmrgint
151005b261ecSmrgProcChangeGC(ClientPtr client)
151105b261ecSmrg{
151205b261ecSmrg    GC *pGC;
151305b261ecSmrg    int result;
151405b261ecSmrg    unsigned len;
1515f7df2e56Smrg
151605b261ecSmrg    REQUEST(xChangeGCReq);
151705b261ecSmrg    REQUEST_AT_LEAST_SIZE(xChangeGCReq);
151805b261ecSmrg
15194642e01fSmrg    result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess);
152005b261ecSmrg    if (result != Success)
1521f7df2e56Smrg        return result;
152205b261ecSmrg
1523f7df2e56Smrg    len = client->req_len - bytes_to_int32(sizeof(xChangeGCReq));
152405b261ecSmrg    if (len != Ones(stuff->mask))
152505b261ecSmrg        return BadLength;
152605b261ecSmrg
15276747b715Smrg    return ChangeGCXIDs(client, pGC, stuff->mask, (CARD32 *) &stuff[1]);
152805b261ecSmrg}
152905b261ecSmrg
153005b261ecSmrgint
153105b261ecSmrgProcCopyGC(ClientPtr client)
153205b261ecSmrg{
153305b261ecSmrg    GC *dstGC;
153405b261ecSmrg    GC *pGC;
153505b261ecSmrg    int result;
1536f7df2e56Smrg
153705b261ecSmrg    REQUEST(xCopyGCReq);
153805b261ecSmrg    REQUEST_SIZE_MATCH(xCopyGCReq);
153905b261ecSmrg
15404642e01fSmrg    result = dixLookupGC(&pGC, stuff->srcGC, client, DixGetAttrAccess);
154105b261ecSmrg    if (result != Success)
1542f7df2e56Smrg        return result;
15434642e01fSmrg    result = dixLookupGC(&dstGC, stuff->dstGC, client, DixSetAttrAccess);
154405b261ecSmrg    if (result != Success)
1545f7df2e56Smrg        return result;
154605b261ecSmrg    if ((dstGC->pScreen != pGC->pScreen) || (dstGC->depth != pGC->depth))
15476747b715Smrg        return BadMatch;
1548f7df2e56Smrg    if (stuff->mask & ~GCAllBits) {
1549f7df2e56Smrg        client->errorValue = stuff->mask;
1550f7df2e56Smrg        return BadValue;
155105b261ecSmrg    }
15526747b715Smrg    return CopyGC(pGC, dstGC, stuff->mask);
155305b261ecSmrg}
155405b261ecSmrg
155505b261ecSmrgint
155605b261ecSmrgProcSetDashes(ClientPtr client)
155705b261ecSmrg{
155805b261ecSmrg    GC *pGC;
155905b261ecSmrg    int result;
1560f7df2e56Smrg
156105b261ecSmrg    REQUEST(xSetDashesReq);
156205b261ecSmrg
156305b261ecSmrg    REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes);
1564f7df2e56Smrg    if (stuff->nDashes == 0) {
1565f7df2e56Smrg        client->errorValue = 0;
1566f7df2e56Smrg        return BadValue;
156705b261ecSmrg    }
156805b261ecSmrg
1569f7df2e56Smrg    result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess);
157005b261ecSmrg    if (result != Success)
1571f7df2e56Smrg        return result;
157205b261ecSmrg
15736747b715Smrg    /* If there's an error, either there's no sensible errorValue,
15746747b715Smrg     * or there was a dash segment of 0. */
15756747b715Smrg    client->errorValue = 0;
15766747b715Smrg    return SetDashes(pGC, stuff->dashOffset, stuff->nDashes,
1577f7df2e56Smrg                     (unsigned char *) &stuff[1]);
157805b261ecSmrg}
157905b261ecSmrg
158005b261ecSmrgint
158105b261ecSmrgProcSetClipRectangles(ClientPtr client)
158205b261ecSmrg{
1583f7df2e56Smrg    int nr, result;
158405b261ecSmrg    GC *pGC;
1585f7df2e56Smrg
158605b261ecSmrg    REQUEST(xSetClipRectanglesReq);
158705b261ecSmrg
158805b261ecSmrg    REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq);
158905b261ecSmrg    if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) &&
1590f7df2e56Smrg        (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded)) {
1591f7df2e56Smrg        client->errorValue = stuff->ordering;
159205b261ecSmrg        return BadValue;
159305b261ecSmrg    }
1594f7df2e56Smrg    result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess);
159505b261ecSmrg    if (result != Success)
1596f7df2e56Smrg        return result;
1597f7df2e56Smrg
159805b261ecSmrg    nr = (client->req_len << 2) - sizeof(xSetClipRectanglesReq);
159905b261ecSmrg    if (nr & 4)
1600f7df2e56Smrg        return BadLength;
160105b261ecSmrg    nr >>= 3;
16026747b715Smrg    return SetClipRects(pGC, stuff->xOrigin, stuff->yOrigin,
1603f7df2e56Smrg                        nr, (xRectangle *) &stuff[1], (int) stuff->ordering);
160405b261ecSmrg}
160505b261ecSmrg
160605b261ecSmrgint
160705b261ecSmrgProcFreeGC(ClientPtr client)
160805b261ecSmrg{
160905b261ecSmrg    GC *pGC;
161005b261ecSmrg    int rc;
1611f7df2e56Smrg
161205b261ecSmrg    REQUEST(xResourceReq);
161305b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
161405b261ecSmrg
161505b261ecSmrg    rc = dixLookupGC(&pGC, stuff->id, client, DixDestroyAccess);
161605b261ecSmrg    if (rc != Success)
1617f7df2e56Smrg        return rc;
161805b261ecSmrg
161905b261ecSmrg    FreeResource(stuff->id, RT_NONE);
16206747b715Smrg    return Success;
162105b261ecSmrg}
162205b261ecSmrg
162305b261ecSmrgint
162405b261ecSmrgProcClearToBackground(ClientPtr client)
162505b261ecSmrg{
162605b261ecSmrg    REQUEST(xClearAreaReq);
162705b261ecSmrg    WindowPtr pWin;
162805b261ecSmrg    int rc;
162905b261ecSmrg
163005b261ecSmrg    REQUEST_SIZE_MATCH(xClearAreaReq);
163105b261ecSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess);
163205b261ecSmrg    if (rc != Success)
163305b261ecSmrg        return rc;
1634f7df2e56Smrg    if (pWin->drawable.class == InputOnly) {
1635f7df2e56Smrg        client->errorValue = stuff->window;
1636f7df2e56Smrg        return BadMatch;
1637f7df2e56Smrg    }
1638f7df2e56Smrg    if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse)) {
1639f7df2e56Smrg        client->errorValue = stuff->exposures;
16406747b715Smrg        return BadValue;
164105b261ecSmrg    }
1642f7df2e56Smrg    (*pWin->drawable.pScreen->ClearToBackground) (pWin, stuff->x, stuff->y,
1643f7df2e56Smrg                                                  stuff->width, stuff->height,
1644f7df2e56Smrg                                                  (Bool) stuff->exposures);
16456747b715Smrg    return Success;
164605b261ecSmrg}
164705b261ecSmrg
1648f7df2e56Smrg/* send GraphicsExpose events, or a NoExpose event, based on the region */
1649f7df2e56Smrgvoid
1650f7df2e56SmrgSendGraphicsExpose(ClientPtr client, RegionPtr pRgn, XID drawable,
1651f7df2e56Smrg                     int major, int minor)
1652f7df2e56Smrg{
1653f7df2e56Smrg    if (pRgn && !RegionNil(pRgn)) {
1654f7df2e56Smrg        xEvent *pEvent;
1655f7df2e56Smrg        xEvent *pe;
1656f7df2e56Smrg        BoxPtr pBox;
1657f7df2e56Smrg        int i;
1658f7df2e56Smrg        int numRects;
1659f7df2e56Smrg
1660f7df2e56Smrg        numRects = RegionNumRects(pRgn);
1661f7df2e56Smrg        pBox = RegionRects(pRgn);
1662f7df2e56Smrg        if (!(pEvent = calloc(numRects, sizeof(xEvent))))
1663f7df2e56Smrg            return;
1664f7df2e56Smrg        pe = pEvent;
1665f7df2e56Smrg
1666f7df2e56Smrg        for (i = 1; i <= numRects; i++, pe++, pBox++) {
1667f7df2e56Smrg            pe->u.u.type = GraphicsExpose;
1668f7df2e56Smrg            pe->u.graphicsExposure.drawable = drawable;
1669f7df2e56Smrg            pe->u.graphicsExposure.x = pBox->x1;
1670f7df2e56Smrg            pe->u.graphicsExposure.y = pBox->y1;
1671f7df2e56Smrg            pe->u.graphicsExposure.width = pBox->x2 - pBox->x1;
1672f7df2e56Smrg            pe->u.graphicsExposure.height = pBox->y2 - pBox->y1;
1673f7df2e56Smrg            pe->u.graphicsExposure.count = numRects - i;
1674f7df2e56Smrg            pe->u.graphicsExposure.majorEvent = major;
1675f7df2e56Smrg            pe->u.graphicsExposure.minorEvent = minor;
1676f7df2e56Smrg        }
1677f7df2e56Smrg        /* GraphicsExpose is a "critical event", which TryClientEvents
1678f7df2e56Smrg         * handles specially. */
1679f7df2e56Smrg        TryClientEvents(client, NULL, pEvent, numRects,
1680f7df2e56Smrg                        (Mask) 0, NoEventMask, NullGrab);
1681f7df2e56Smrg        free(pEvent);
1682f7df2e56Smrg    }
1683f7df2e56Smrg    else {
1684f7df2e56Smrg        xEvent event = {
1685f7df2e56Smrg            .u.noExposure.drawable = drawable,
1686f7df2e56Smrg            .u.noExposure.majorEvent = major,
1687f7df2e56Smrg            .u.noExposure.minorEvent = minor
1688f7df2e56Smrg        };
1689f7df2e56Smrg        event.u.u.type = NoExpose;
1690f7df2e56Smrg        WriteEventsToClient(client, 1, &event);
1691f7df2e56Smrg    }
1692f7df2e56Smrg}
1693f7df2e56Smrg
169405b261ecSmrgint
169505b261ecSmrgProcCopyArea(ClientPtr client)
169605b261ecSmrg{
169705b261ecSmrg    DrawablePtr pDst;
169805b261ecSmrg    DrawablePtr pSrc;
169905b261ecSmrg    GC *pGC;
1700f7df2e56Smrg
170105b261ecSmrg    REQUEST(xCopyAreaReq);
170205b261ecSmrg    RegionPtr pRgn;
170305b261ecSmrg    int rc;
170405b261ecSmrg
170505b261ecSmrg    REQUEST_SIZE_MATCH(xCopyAreaReq);
170605b261ecSmrg
1707f7df2e56Smrg    VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, DixWriteAccess);
1708f7df2e56Smrg    if (stuff->dstDrawable != stuff->srcDrawable) {
1709f7df2e56Smrg        rc = dixLookupDrawable(&pSrc, stuff->srcDrawable, client, 0,
1710f7df2e56Smrg                               DixReadAccess);
1711f7df2e56Smrg        if (rc != Success)
1712f7df2e56Smrg            return rc;
1713f7df2e56Smrg        if ((pDst->pScreen != pSrc->pScreen) || (pDst->depth != pSrc->depth)) {
1714f7df2e56Smrg            client->errorValue = stuff->dstDrawable;
1715f7df2e56Smrg            return BadMatch;
1716f7df2e56Smrg        }
171705b261ecSmrg    }
171805b261ecSmrg    else
171905b261ecSmrg        pSrc = pDst;
172005b261ecSmrg
1721f7df2e56Smrg    pRgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, stuff->srcX, stuff->srcY,
1722f7df2e56Smrg                                  stuff->width, stuff->height,
1723f7df2e56Smrg                                  stuff->dstX, stuff->dstY);
1724f7df2e56Smrg    if (pGC->graphicsExposures) {
1725f7df2e56Smrg        SendGraphicsExpose(client, pRgn, stuff->dstDrawable, X_CopyArea, 0);
1726f7df2e56Smrg        if (pRgn)
1727f7df2e56Smrg            RegionDestroy(pRgn);
172805b261ecSmrg    }
172905b261ecSmrg
17306747b715Smrg    return Success;
173105b261ecSmrg}
173205b261ecSmrg
173305b261ecSmrgint
173405b261ecSmrgProcCopyPlane(ClientPtr client)
173505b261ecSmrg{
173605b261ecSmrg    DrawablePtr psrcDraw, pdstDraw;
173705b261ecSmrg    GC *pGC;
1738f7df2e56Smrg
173905b261ecSmrg    REQUEST(xCopyPlaneReq);
174005b261ecSmrg    RegionPtr pRgn;
174105b261ecSmrg    int rc;
174205b261ecSmrg
174305b261ecSmrg    REQUEST_SIZE_MATCH(xCopyPlaneReq);
174405b261ecSmrg
17454642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pdstDraw, DixWriteAccess);
1746f7df2e56Smrg    if (stuff->dstDrawable != stuff->srcDrawable) {
1747f7df2e56Smrg        rc = dixLookupDrawable(&psrcDraw, stuff->srcDrawable, client, 0,
1748f7df2e56Smrg                               DixReadAccess);
1749f7df2e56Smrg        if (rc != Success)
1750f7df2e56Smrg            return rc;
1751f7df2e56Smrg
1752f7df2e56Smrg        if (pdstDraw->pScreen != psrcDraw->pScreen) {
1753f7df2e56Smrg            client->errorValue = stuff->dstDrawable;
1754f7df2e56Smrg            return BadMatch;
1755f7df2e56Smrg        }
175605b261ecSmrg    }
175705b261ecSmrg    else
175805b261ecSmrg        psrcDraw = pdstDraw;
175905b261ecSmrg
176005b261ecSmrg    /* Check to see if stuff->bitPlane has exactly ONE good bit set */
1761f7df2e56Smrg    if (stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) ||
1762f7df2e56Smrg        (stuff->bitPlane > (1L << (psrcDraw->depth - 1)))) {
1763f7df2e56Smrg        client->errorValue = stuff->bitPlane;
1764f7df2e56Smrg        return BadValue;
176505b261ecSmrg    }
176605b261ecSmrg
1767f7df2e56Smrg    pRgn =
1768f7df2e56Smrg        (*pGC->ops->CopyPlane) (psrcDraw, pdstDraw, pGC, stuff->srcX,
1769f7df2e56Smrg                                stuff->srcY, stuff->width, stuff->height,
1770f7df2e56Smrg                                stuff->dstX, stuff->dstY, stuff->bitPlane);
1771f7df2e56Smrg    if (pGC->graphicsExposures) {
1772f7df2e56Smrg        SendGraphicsExpose(client, pRgn, stuff->dstDrawable, X_CopyPlane, 0);
1773f7df2e56Smrg        if (pRgn)
1774f7df2e56Smrg            RegionDestroy(pRgn);
177505b261ecSmrg    }
17766747b715Smrg    return Success;
177705b261ecSmrg}
177805b261ecSmrg
177905b261ecSmrgint
178005b261ecSmrgProcPolyPoint(ClientPtr client)
178105b261ecSmrg{
178205b261ecSmrg    int npoint;
178305b261ecSmrg    GC *pGC;
178405b261ecSmrg    DrawablePtr pDraw;
1785f7df2e56Smrg
178605b261ecSmrg    REQUEST(xPolyPointReq);
178705b261ecSmrg
178805b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolyPointReq);
1789f7df2e56Smrg    if ((stuff->coordMode != CoordModeOrigin) &&
1790f7df2e56Smrg        (stuff->coordMode != CoordModePrevious)) {
1791f7df2e56Smrg        client->errorValue = stuff->coordMode;
179205b261ecSmrg        return BadValue;
179305b261ecSmrg    }
1794f7df2e56Smrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
17956747b715Smrg    npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyPointReq));
179605b261ecSmrg    if (npoint)
1797f7df2e56Smrg        (*pGC->ops->PolyPoint) (pDraw, pGC, stuff->coordMode, npoint,
1798f7df2e56Smrg                                (xPoint *) &stuff[1]);
17996747b715Smrg    return Success;
180005b261ecSmrg}
180105b261ecSmrg
180205b261ecSmrgint
180305b261ecSmrgProcPolyLine(ClientPtr client)
180405b261ecSmrg{
180505b261ecSmrg    int npoint;
180605b261ecSmrg    GC *pGC;
180705b261ecSmrg    DrawablePtr pDraw;
1808f7df2e56Smrg
180905b261ecSmrg    REQUEST(xPolyLineReq);
181005b261ecSmrg
181105b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolyLineReq);
1812f7df2e56Smrg    if ((stuff->coordMode != CoordModeOrigin) &&
1813f7df2e56Smrg        (stuff->coordMode != CoordModePrevious)) {
1814f7df2e56Smrg        client->errorValue = stuff->coordMode;
181505b261ecSmrg        return BadValue;
181605b261ecSmrg    }
18174642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
18186747b715Smrg    npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyLineReq));
181905b261ecSmrg    if (npoint > 1)
1820f7df2e56Smrg        (*pGC->ops->Polylines) (pDraw, pGC, stuff->coordMode, npoint,
1821f7df2e56Smrg                                (DDXPointPtr) &stuff[1]);
18226747b715Smrg    return Success;
182305b261ecSmrg}
182405b261ecSmrg
182505b261ecSmrgint
182605b261ecSmrgProcPolySegment(ClientPtr client)
182705b261ecSmrg{
182805b261ecSmrg    int nsegs;
182905b261ecSmrg    GC *pGC;
183005b261ecSmrg    DrawablePtr pDraw;
1831f7df2e56Smrg
183205b261ecSmrg    REQUEST(xPolySegmentReq);
183305b261ecSmrg
183405b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolySegmentReq);
18354642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
183605b261ecSmrg    nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq);
183705b261ecSmrg    if (nsegs & 4)
1838f7df2e56Smrg        return BadLength;
183905b261ecSmrg    nsegs >>= 3;
184005b261ecSmrg    if (nsegs)
1841f7df2e56Smrg        (*pGC->ops->PolySegment) (pDraw, pGC, nsegs, (xSegment *) &stuff[1]);
18426747b715Smrg    return Success;
184305b261ecSmrg}
184405b261ecSmrg
184505b261ecSmrgint
1846f7df2e56SmrgProcPolyRectangle(ClientPtr client)
184705b261ecSmrg{
184805b261ecSmrg    int nrects;
184905b261ecSmrg    GC *pGC;
185005b261ecSmrg    DrawablePtr pDraw;
1851f7df2e56Smrg
185205b261ecSmrg    REQUEST(xPolyRectangleReq);
185305b261ecSmrg
185405b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolyRectangleReq);
18554642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
185605b261ecSmrg    nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq);
185705b261ecSmrg    if (nrects & 4)
1858f7df2e56Smrg        return BadLength;
185905b261ecSmrg    nrects >>= 3;
186005b261ecSmrg    if (nrects)
1861f7df2e56Smrg        (*pGC->ops->PolyRectangle) (pDraw, pGC,
1862f7df2e56Smrg                                    nrects, (xRectangle *) &stuff[1]);
18636747b715Smrg    return Success;
186405b261ecSmrg}
186505b261ecSmrg
186605b261ecSmrgint
186705b261ecSmrgProcPolyArc(ClientPtr client)
186805b261ecSmrg{
1869f7df2e56Smrg    int narcs;
187005b261ecSmrg    GC *pGC;
187105b261ecSmrg    DrawablePtr pDraw;
1872f7df2e56Smrg
187305b261ecSmrg    REQUEST(xPolyArcReq);
187405b261ecSmrg
187505b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolyArcReq);
18764642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
187705b261ecSmrg    narcs = (client->req_len << 2) - sizeof(xPolyArcReq);
187805b261ecSmrg    if (narcs % sizeof(xArc))
1879f7df2e56Smrg        return BadLength;
188005b261ecSmrg    narcs /= sizeof(xArc);
188105b261ecSmrg    if (narcs)
1882f7df2e56Smrg        (*pGC->ops->PolyArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]);
18836747b715Smrg    return Success;
188405b261ecSmrg}
188505b261ecSmrg
188605b261ecSmrgint
188705b261ecSmrgProcFillPoly(ClientPtr client)
188805b261ecSmrg{
1889f7df2e56Smrg    int things;
189005b261ecSmrg    GC *pGC;
189105b261ecSmrg    DrawablePtr pDraw;
1892f7df2e56Smrg
189305b261ecSmrg    REQUEST(xFillPolyReq);
189405b261ecSmrg
189505b261ecSmrg    REQUEST_AT_LEAST_SIZE(xFillPolyReq);
1896f7df2e56Smrg    if ((stuff->shape != Complex) && (stuff->shape != Nonconvex) &&
1897f7df2e56Smrg        (stuff->shape != Convex)) {
1898f7df2e56Smrg        client->errorValue = stuff->shape;
189905b261ecSmrg        return BadValue;
190005b261ecSmrg    }
1901f7df2e56Smrg    if ((stuff->coordMode != CoordModeOrigin) &&
1902f7df2e56Smrg        (stuff->coordMode != CoordModePrevious)) {
1903f7df2e56Smrg        client->errorValue = stuff->coordMode;
190405b261ecSmrg        return BadValue;
190505b261ecSmrg    }
190605b261ecSmrg
19074642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
19086747b715Smrg    things = bytes_to_int32((client->req_len << 2) - sizeof(xFillPolyReq));
190905b261ecSmrg    if (things)
191005b261ecSmrg        (*pGC->ops->FillPolygon) (pDraw, pGC, stuff->shape,
1911f7df2e56Smrg                                  stuff->coordMode, things,
1912f7df2e56Smrg                                  (DDXPointPtr) &stuff[1]);
19136747b715Smrg    return Success;
191405b261ecSmrg}
191505b261ecSmrg
191605b261ecSmrgint
191705b261ecSmrgProcPolyFillRectangle(ClientPtr client)
191805b261ecSmrg{
1919f7df2e56Smrg    int things;
192005b261ecSmrg    GC *pGC;
192105b261ecSmrg    DrawablePtr pDraw;
1922f7df2e56Smrg
192305b261ecSmrg    REQUEST(xPolyFillRectangleReq);
192405b261ecSmrg
192505b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq);
19264642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
192705b261ecSmrg    things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq);
192805b261ecSmrg    if (things & 4)
1929f7df2e56Smrg        return BadLength;
193005b261ecSmrg    things >>= 3;
193105b261ecSmrg
193205b261ecSmrg    if (things)
193305b261ecSmrg        (*pGC->ops->PolyFillRect) (pDraw, pGC, things,
1934f7df2e56Smrg                                   (xRectangle *) &stuff[1]);
19356747b715Smrg    return Success;
193605b261ecSmrg}
193705b261ecSmrg
193805b261ecSmrgint
193905b261ecSmrgProcPolyFillArc(ClientPtr client)
194005b261ecSmrg{
1941f7df2e56Smrg    int narcs;
194205b261ecSmrg    GC *pGC;
194305b261ecSmrg    DrawablePtr pDraw;
1944f7df2e56Smrg
194505b261ecSmrg    REQUEST(xPolyFillArcReq);
194605b261ecSmrg
194705b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolyFillArcReq);
19484642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
194905b261ecSmrg    narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq);
195005b261ecSmrg    if (narcs % sizeof(xArc))
1951f7df2e56Smrg        return BadLength;
195205b261ecSmrg    narcs /= sizeof(xArc);
195305b261ecSmrg    if (narcs)
195405b261ecSmrg        (*pGC->ops->PolyFillArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]);
19556747b715Smrg    return Success;
195605b261ecSmrg}
195705b261ecSmrg
195805b261ecSmrg#ifdef MATCH_CLIENT_ENDIAN
195905b261ecSmrg
196005b261ecSmrgint
1961f7df2e56SmrgServerOrder(void)
196205b261ecSmrg{
1963f7df2e56Smrg    int whichbyte = 1;
196405b261ecSmrg
196505b261ecSmrg    if (*((char *) &whichbyte))
1966f7df2e56Smrg        return LSBFirst;
196705b261ecSmrg    return MSBFirst;
196805b261ecSmrg}
196905b261ecSmrg
197005b261ecSmrg#define ClientOrder(client) ((client)->swapped ? !ServerOrder() : ServerOrder())
197105b261ecSmrg
197205b261ecSmrgvoid
1973f7df2e56SmrgReformatImage(char *base, int nbytes, int bpp, int order)
197405b261ecSmrg{
197505b261ecSmrg    switch (bpp) {
1976f7df2e56Smrg    case 1:                    /* yuck */
1977f7df2e56Smrg        if (BITMAP_BIT_ORDER != order)
1978f7df2e56Smrg            BitOrderInvert((unsigned char *) base, nbytes);
197905b261ecSmrg#if IMAGE_BYTE_ORDER != BITMAP_BIT_ORDER && BITMAP_SCANLINE_UNIT != 8
1980f7df2e56Smrg        ReformatImage(base, nbytes, BITMAP_SCANLINE_UNIT, order);
198105b261ecSmrg#endif
1982f7df2e56Smrg        break;
198305b261ecSmrg    case 4:
1984f7df2e56Smrg        break;                  /* yuck */
198505b261ecSmrg    case 8:
1986f7df2e56Smrg        break;
198705b261ecSmrg    case 16:
1988f7df2e56Smrg        if (IMAGE_BYTE_ORDER != order)
1989f7df2e56Smrg            TwoByteSwap((unsigned char *) base, nbytes);
1990f7df2e56Smrg        break;
199105b261ecSmrg    case 32:
1992f7df2e56Smrg        if (IMAGE_BYTE_ORDER != order)
1993f7df2e56Smrg            FourByteSwap((unsigned char *) base, nbytes);
1994f7df2e56Smrg        break;
199505b261ecSmrg    }
199605b261ecSmrg}
199705b261ecSmrg#else
199805b261ecSmrg#define ReformatImage(b,n,bpp,o)
199905b261ecSmrg#endif
200005b261ecSmrg
200105b261ecSmrg/* 64-bit server notes: the protocol restricts padding of images to
200205b261ecSmrg * 8-, 16-, or 32-bits. We would like to have 64-bits for the server
200305b261ecSmrg * to use internally. Removes need for internal alignment checking.
200405b261ecSmrg * All of the PutImage functions could be changed individually, but
200505b261ecSmrg * as currently written, they call other routines which require things
200605b261ecSmrg * to be 64-bit padded on scanlines, so we changed things here.
200705b261ecSmrg * If an image would be padded differently for 64- versus 32-, then
200805b261ecSmrg * copy each scanline to a 64-bit padded scanline.
200905b261ecSmrg * Also, we need to make sure that the image is aligned on a 64-bit
201005b261ecSmrg * boundary, even if the scanlines are padded to our satisfaction.
201105b261ecSmrg */
201205b261ecSmrgint
201305b261ecSmrgProcPutImage(ClientPtr client)
201405b261ecSmrg{
201505b261ecSmrg    GC *pGC;
201605b261ecSmrg    DrawablePtr pDraw;
2017f7df2e56Smrg    long length;                /* length of scanline server padded */
2018f7df2e56Smrg    long lengthProto;           /* length of scanline protocol padded */
2019f7df2e56Smrg    char *tmpImage;
2020f7df2e56Smrg
202105b261ecSmrg    REQUEST(xPutImageReq);
202205b261ecSmrg
202305b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPutImageReq);
20244642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
2025f7df2e56Smrg    if (stuff->format == XYBitmap) {
202605b261ecSmrg        if ((stuff->depth != 1) ||
2027f7df2e56Smrg            (stuff->leftPad >= (unsigned int) screenInfo.bitmapScanlinePad))
202805b261ecSmrg            return BadMatch;
2029f7df2e56Smrg        length = BitmapBytePad(stuff->width + stuff->leftPad);
203005b261ecSmrg    }
2031f7df2e56Smrg    else if (stuff->format == XYPixmap) {
2032f7df2e56Smrg        if ((pDraw->depth != stuff->depth) ||
2033f7df2e56Smrg            (stuff->leftPad >= (unsigned int) screenInfo.bitmapScanlinePad))
203405b261ecSmrg            return BadMatch;
2035f7df2e56Smrg        length = BitmapBytePad(stuff->width + stuff->leftPad);
2036f7df2e56Smrg        length *= stuff->depth;
203705b261ecSmrg    }
2038f7df2e56Smrg    else if (stuff->format == ZPixmap) {
203905b261ecSmrg        if ((pDraw->depth != stuff->depth) || (stuff->leftPad != 0))
204005b261ecSmrg            return BadMatch;
2041f7df2e56Smrg        length = PixmapBytePad(stuff->width, stuff->depth);
204205b261ecSmrg    }
2043f7df2e56Smrg    else {
2044f7df2e56Smrg        client->errorValue = stuff->format;
204505b261ecSmrg        return BadValue;
204605b261ecSmrg    }
204705b261ecSmrg
2048f7df2e56Smrg    tmpImage = (char *) &stuff[1];
204905b261ecSmrg    lengthProto = length;
20500b0d8713Smrg
2051f7df2e56Smrg    if (stuff->height != 0 && lengthProto >= (INT32_MAX / stuff->height))
20520b0d8713Smrg        return BadLength;
2053f7df2e56Smrg
20546747b715Smrg    if ((bytes_to_int32(lengthProto * stuff->height) +
2055f7df2e56Smrg         bytes_to_int32(sizeof(xPutImageReq))) != client->req_len)
2056f7df2e56Smrg        return BadLength;
2057f7df2e56Smrg
2058f7df2e56Smrg    ReformatImage(tmpImage, lengthProto * stuff->height,
2059f7df2e56Smrg                  stuff->format == ZPixmap ? BitsPerPixel(stuff->depth) : 1,
2060f7df2e56Smrg                  ClientOrder(client));
206105b261ecSmrg
206205b261ecSmrg    (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, stuff->dstX, stuff->dstY,
2063f7df2e56Smrg                           stuff->width, stuff->height,
2064f7df2e56Smrg                           stuff->leftPad, stuff->format, tmpImage);
206505b261ecSmrg
2066f7df2e56Smrg    return Success;
206705b261ecSmrg}
206805b261ecSmrg
206905b261ecSmrgstatic int
2070f7df2e56SmrgDoGetImage(ClientPtr client, int format, Drawable drawable,
2071f7df2e56Smrg           int x, int y, int width, int height,
2072f7df2e56Smrg           Mask planemask)
207305b261ecSmrg{
2074f7df2e56Smrg    DrawablePtr pDraw, pBoundingDraw;
2075f7df2e56Smrg    int nlines, linesPerBuf, rc;
2076f7df2e56Smrg    int linesDone;
2077f7df2e56Smrg
20786747b715Smrg    /* coordinates relative to the bounding drawable */
2079f7df2e56Smrg    int relx, rely;
2080f7df2e56Smrg    long widthBytesLine, length;
2081f7df2e56Smrg    Mask plane = 0;
2082f7df2e56Smrg    char *pBuf;
2083f7df2e56Smrg    xGetImageReply xgi;
208405b261ecSmrg    RegionPtr pVisibleRegion = NULL;
208505b261ecSmrg
2086f7df2e56Smrg    if ((format != XYPixmap) && (format != ZPixmap)) {
2087f7df2e56Smrg        client->errorValue = format;
20886747b715Smrg        return BadValue;
208905b261ecSmrg    }
209005b261ecSmrg    rc = dixLookupDrawable(&pDraw, drawable, client, 0, DixReadAccess);
209105b261ecSmrg    if (rc != Success)
2092f7df2e56Smrg        return rc;
209305b261ecSmrg
20946747b715Smrg    memset(&xgi, 0, sizeof(xGetImageReply));
20956747b715Smrg
20966747b715Smrg    relx = x;
20976747b715Smrg    rely = y;
20986747b715Smrg
2099f7df2e56Smrg    if (pDraw->type == DRAWABLE_WINDOW) {
2100f7df2e56Smrg        WindowPtr pWin = (WindowPtr) pDraw;
2101f7df2e56Smrg
2102f7df2e56Smrg        /* "If the drawable is a window, the window must be viewable ... or a
2103f7df2e56Smrg         * BadMatch error results" */
2104f7df2e56Smrg        if (!pWin->viewable)
2105f7df2e56Smrg            return BadMatch;
21066747b715Smrg
2107f7df2e56Smrg        /* If the drawable is a window, the rectangle must be contained within
2108f7df2e56Smrg         * its bounds (including the border). */
2109f7df2e56Smrg        if (x < -wBorderWidth(pWin) ||
2110f7df2e56Smrg            x + width > wBorderWidth(pWin) + (int) pDraw->width ||
2111f7df2e56Smrg            y < -wBorderWidth(pWin) ||
2112f7df2e56Smrg            y + height > wBorderWidth(pWin) + (int) pDraw->height)
2113f7df2e56Smrg            return BadMatch;
21146747b715Smrg
2115f7df2e56Smrg        relx += pDraw->x;
2116f7df2e56Smrg        rely += pDraw->y;
21176747b715Smrg
2118f7df2e56Smrg        if (pDraw->pScreen->GetWindowPixmap) {
2119f7df2e56Smrg            PixmapPtr pPix = (*pDraw->pScreen->GetWindowPixmap) (pWin);
21206747b715Smrg
2121f7df2e56Smrg            pBoundingDraw = &pPix->drawable;
21226747b715Smrg#ifdef COMPOSITE
2123f7df2e56Smrg            relx -= pPix->screen_x;
2124f7df2e56Smrg            rely -= pPix->screen_y;
21256747b715Smrg#endif
2126f7df2e56Smrg        }
2127f7df2e56Smrg        else {
2128f7df2e56Smrg            pBoundingDraw = (DrawablePtr) pDraw->pScreen->root;
2129f7df2e56Smrg        }
21306747b715Smrg
2131f7df2e56Smrg        xgi.visual = wVisual(pWin);
213205b261ecSmrg    }
2133f7df2e56Smrg    else {
2134f7df2e56Smrg        pBoundingDraw = pDraw;
2135f7df2e56Smrg        xgi.visual = None;
213605b261ecSmrg    }
213705b261ecSmrg
21386747b715Smrg    /* "If the drawable is a pixmap, the given rectangle must be wholly
21396747b715Smrg     *  contained within the pixmap, or a BadMatch error results.  If the
21406747b715Smrg     *  drawable is a window [...] it must be the case that if there were no
21416747b715Smrg     *  inferiors or overlapping windows, the specified rectangle of the window
21426747b715Smrg     *  would be fully visible on the screen and wholly contained within the
21436747b715Smrg     *  outside edges of the window, or a BadMatch error results."
21446747b715Smrg     *
21456747b715Smrg     * We relax the window case slightly to mean that the rectangle must exist
21466747b715Smrg     * within the bounds of the window's backing pixmap.  In particular, this
21476747b715Smrg     * means that a GetImage request may succeed or fail with BadMatch depending
21486747b715Smrg     * on whether any of its ancestor windows are redirected.  */
2149f7df2e56Smrg    if (relx < 0 || relx + width > (int) pBoundingDraw->width ||
2150f7df2e56Smrg        rely < 0 || rely + height > (int) pBoundingDraw->height)
2151f7df2e56Smrg        return BadMatch;
21526747b715Smrg
215305b261ecSmrg    xgi.type = X_Reply;
215405b261ecSmrg    xgi.sequenceNumber = client->sequence;
215505b261ecSmrg    xgi.depth = pDraw->depth;
2156f7df2e56Smrg    if (format == ZPixmap) {
2157f7df2e56Smrg        widthBytesLine = PixmapBytePad(width, pDraw->depth);
2158f7df2e56Smrg        length = widthBytesLine * height;
215905b261ecSmrg
216005b261ecSmrg    }
2161f7df2e56Smrg    else {
2162f7df2e56Smrg        widthBytesLine = BitmapBytePad(width);
2163f7df2e56Smrg        plane = ((Mask) 1) << (pDraw->depth - 1);
2164f7df2e56Smrg        /* only planes asked for */
2165f7df2e56Smrg        length = widthBytesLine * height *
2166f7df2e56Smrg            Ones(planemask & (plane | (plane - 1)));
216705b261ecSmrg
216805b261ecSmrg    }
216905b261ecSmrg
217005b261ecSmrg    xgi.length = length;
217105b261ecSmrg
2172f7df2e56Smrg    xgi.length = bytes_to_int32(xgi.length);
2173f7df2e56Smrg    if (widthBytesLine == 0 || height == 0)
2174f7df2e56Smrg        linesPerBuf = 0;
2175f7df2e56Smrg    else if (widthBytesLine >= IMAGE_BUFSIZE)
2176f7df2e56Smrg        linesPerBuf = 1;
2177f7df2e56Smrg    else {
2178f7df2e56Smrg        linesPerBuf = IMAGE_BUFSIZE / widthBytesLine;
2179f7df2e56Smrg        if (linesPerBuf > height)
2180f7df2e56Smrg            linesPerBuf = height;
2181f7df2e56Smrg    }
2182f7df2e56Smrg    length = linesPerBuf * widthBytesLine;
2183f7df2e56Smrg    if (linesPerBuf < height) {
2184f7df2e56Smrg        /* we have to make sure intermediate buffers don't need padding */
2185f7df2e56Smrg        while ((linesPerBuf > 1) &&
2186f7df2e56Smrg               (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD) - 1))) {
2187f7df2e56Smrg            linesPerBuf--;
2188f7df2e56Smrg            length -= widthBytesLine;
2189f7df2e56Smrg        }
2190f7df2e56Smrg        while (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD) - 1)) {
2191f7df2e56Smrg            linesPerBuf++;
2192f7df2e56Smrg            length += widthBytesLine;
2193f7df2e56Smrg        }
219405b261ecSmrg    }
2195f7df2e56Smrg    if (!(pBuf = calloc(1, length)))
2196f7df2e56Smrg        return BadAlloc;
2197f7df2e56Smrg    WriteReplyToClient(client, sizeof(xGetImageReply), &xgi);
219805b261ecSmrg
21994e185dc0Smrg    if (pDraw->type == DRAWABLE_WINDOW) {
22007e31ba66Smrg        pVisibleRegion = &((WindowPtr) pDraw)->borderClip;
22014e185dc0Smrg        pDraw->pScreen->SourceValidate(pDraw, x, y, width, height,
22024e185dc0Smrg                                       IncludeInferiors);
22034e185dc0Smrg    }
2204f7df2e56Smrg
2205f7df2e56Smrg    if (linesPerBuf == 0) {
2206f7df2e56Smrg        /* nothing to do */
2207f7df2e56Smrg    }
2208f7df2e56Smrg    else if (format == ZPixmap) {
220905b261ecSmrg        linesDone = 0;
2210f7df2e56Smrg        while (height - linesDone > 0) {
2211f7df2e56Smrg            nlines = min(linesPerBuf, height - linesDone);
2212f7df2e56Smrg            (*pDraw->pScreen->GetImage) (pDraw,
2213f7df2e56Smrg                                         x,
2214f7df2e56Smrg                                         y + linesDone,
2215f7df2e56Smrg                                         width,
2216f7df2e56Smrg                                         nlines,
2217f7df2e56Smrg                                         format, planemask, (void *) pBuf);
2218f7df2e56Smrg            if (pVisibleRegion)
2219f7df2e56Smrg                XaceCensorImage(client, pVisibleRegion, widthBytesLine,
2220f7df2e56Smrg                                pDraw, x, y + linesDone, width,
2221f7df2e56Smrg                                nlines, format, pBuf);
2222f7df2e56Smrg
2223f7df2e56Smrg            /* Note that this is NOT a call to WriteSwappedDataToClient,
222405b261ecSmrg               as we do NOT byte swap */
2225f7df2e56Smrg            ReformatImage(pBuf, (int) (nlines * widthBytesLine),
2226f7df2e56Smrg                          BitsPerPixel(pDraw->depth), ClientOrder(client));
2227f7df2e56Smrg
2228f7df2e56Smrg            WriteToClient(client, (int) (nlines * widthBytesLine), pBuf);
2229f7df2e56Smrg            linesDone += nlines;
223005b261ecSmrg        }
223105b261ecSmrg    }
2232f7df2e56Smrg    else {                      /* XYPixmap */
2233f7df2e56Smrg
2234f7df2e56Smrg        for (; plane; plane >>= 1) {
2235f7df2e56Smrg            if (planemask & plane) {
2236f7df2e56Smrg                linesDone = 0;
2237f7df2e56Smrg                while (height - linesDone > 0) {
2238f7df2e56Smrg                    nlines = min(linesPerBuf, height - linesDone);
2239f7df2e56Smrg                    (*pDraw->pScreen->GetImage) (pDraw,
2240f7df2e56Smrg                                                 x,
2241f7df2e56Smrg                                                 y + linesDone,
2242f7df2e56Smrg                                                 width,
2243f7df2e56Smrg                                                 nlines,
2244f7df2e56Smrg                                                 format, plane, (void *) pBuf);
2245f7df2e56Smrg                    if (pVisibleRegion)
2246f7df2e56Smrg                        XaceCensorImage(client, pVisibleRegion,
2247f7df2e56Smrg                                        widthBytesLine,
2248f7df2e56Smrg                                        pDraw, x, y + linesDone, width,
2249f7df2e56Smrg                                        nlines, format, pBuf);
2250f7df2e56Smrg
2251f7df2e56Smrg                    /* Note: NOT a call to WriteSwappedDataToClient,
2252f7df2e56Smrg                       as we do NOT byte swap */
2253f7df2e56Smrg                    ReformatImage(pBuf, (int) (nlines * widthBytesLine),
2254f7df2e56Smrg                                  1, ClientOrder(client));
2255f7df2e56Smrg
2256f7df2e56Smrg                    WriteToClient(client, (int)(nlines * widthBytesLine), pBuf);
2257f7df2e56Smrg                    linesDone += nlines;
2258f7df2e56Smrg                }
225905b261ecSmrg            }
2260f7df2e56Smrg        }
226105b261ecSmrg    }
2262f7df2e56Smrg    free(pBuf);
22636747b715Smrg    return Success;
226405b261ecSmrg}
226505b261ecSmrg
226605b261ecSmrgint
226705b261ecSmrgProcGetImage(ClientPtr client)
226805b261ecSmrg{
226905b261ecSmrg    REQUEST(xGetImageReq);
227005b261ecSmrg
227105b261ecSmrg    REQUEST_SIZE_MATCH(xGetImageReq);
227205b261ecSmrg
227305b261ecSmrg    return DoGetImage(client, stuff->format, stuff->drawable,
2274f7df2e56Smrg                      stuff->x, stuff->y,
2275f7df2e56Smrg                      (int) stuff->width, (int) stuff->height,
2276f7df2e56Smrg                      stuff->planeMask);
227705b261ecSmrg}
227805b261ecSmrg
227905b261ecSmrgint
228005b261ecSmrgProcPolyText(ClientPtr client)
228105b261ecSmrg{
2282f7df2e56Smrg    int err;
2283f7df2e56Smrg
228405b261ecSmrg    REQUEST(xPolyTextReq);
228505b261ecSmrg    DrawablePtr pDraw;
228605b261ecSmrg    GC *pGC;
228705b261ecSmrg
228805b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolyTextReq);
22894642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
229005b261ecSmrg
229105b261ecSmrg    err = PolyText(client,
2292f7df2e56Smrg                   pDraw,
2293f7df2e56Smrg                   pGC,
2294f7df2e56Smrg                   (unsigned char *) &stuff[1],
2295f7df2e56Smrg                   ((unsigned char *) stuff) + (client->req_len << 2),
2296f7df2e56Smrg                   stuff->x, stuff->y, stuff->reqType, stuff->drawable);
2297f7df2e56Smrg
2298f7df2e56Smrg    if (err == Success) {
2299f7df2e56Smrg        return Success;
230005b261ecSmrg    }
230105b261ecSmrg    else
2302f7df2e56Smrg        return err;
230305b261ecSmrg}
230405b261ecSmrg
230505b261ecSmrgint
230605b261ecSmrgProcImageText8(ClientPtr client)
230705b261ecSmrg{
2308f7df2e56Smrg    int err;
230905b261ecSmrg    DrawablePtr pDraw;
231005b261ecSmrg    GC *pGC;
231105b261ecSmrg
231205b261ecSmrg    REQUEST(xImageTextReq);
231305b261ecSmrg
231405b261ecSmrg    REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars);
23154642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
231605b261ecSmrg
231705b261ecSmrg    err = ImageText(client,
2318f7df2e56Smrg                    pDraw,
2319f7df2e56Smrg                    pGC,
2320f7df2e56Smrg                    stuff->nChars,
2321f7df2e56Smrg                    (unsigned char *) &stuff[1],
2322f7df2e56Smrg                    stuff->x, stuff->y, stuff->reqType, stuff->drawable);
2323f7df2e56Smrg
2324f7df2e56Smrg    if (err == Success) {
2325f7df2e56Smrg        return Success;
232605b261ecSmrg    }
232705b261ecSmrg    else
2328f7df2e56Smrg        return err;
232905b261ecSmrg}
233005b261ecSmrg
233105b261ecSmrgint
233205b261ecSmrgProcImageText16(ClientPtr client)
233305b261ecSmrg{
2334f7df2e56Smrg    int err;
233505b261ecSmrg    DrawablePtr pDraw;
233605b261ecSmrg    GC *pGC;
233705b261ecSmrg
233805b261ecSmrg    REQUEST(xImageTextReq);
233905b261ecSmrg
234005b261ecSmrg    REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars << 1);
23414642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
234205b261ecSmrg
234305b261ecSmrg    err = ImageText(client,
2344f7df2e56Smrg                    pDraw,
2345f7df2e56Smrg                    pGC,
2346f7df2e56Smrg                    stuff->nChars,
2347f7df2e56Smrg                    (unsigned char *) &stuff[1],
2348f7df2e56Smrg                    stuff->x, stuff->y, stuff->reqType, stuff->drawable);
2349f7df2e56Smrg
2350f7df2e56Smrg    if (err == Success) {
2351f7df2e56Smrg        return Success;
235205b261ecSmrg    }
235305b261ecSmrg    else
2354f7df2e56Smrg        return err;
235505b261ecSmrg}
235605b261ecSmrg
235705b261ecSmrgint
235805b261ecSmrgProcCreateColormap(ClientPtr client)
235905b261ecSmrg{
2360f7df2e56Smrg    VisualPtr pVisual;
2361f7df2e56Smrg    ColormapPtr pmap;
2362f7df2e56Smrg    Colormap mid;
2363f7df2e56Smrg    WindowPtr pWin;
236405b261ecSmrg    ScreenPtr pScreen;
2365f7df2e56Smrg
236605b261ecSmrg    REQUEST(xCreateColormapReq);
236705b261ecSmrg    int i, result;
236805b261ecSmrg
236905b261ecSmrg    REQUEST_SIZE_MATCH(xCreateColormapReq);
237005b261ecSmrg
2371f7df2e56Smrg    if ((stuff->alloc != AllocNone) && (stuff->alloc != AllocAll)) {
2372f7df2e56Smrg        client->errorValue = stuff->alloc;
23736747b715Smrg        return BadValue;
237405b261ecSmrg    }
237505b261ecSmrg    mid = stuff->mid;
237605b261ecSmrg    LEGAL_NEW_RESOURCE(mid, client);
23774642e01fSmrg    result = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
237805b261ecSmrg    if (result != Success)
237905b261ecSmrg        return result;
238005b261ecSmrg
238105b261ecSmrg    pScreen = pWin->drawable.pScreen;
238205b261ecSmrg    for (i = 0, pVisual = pScreen->visuals;
2383f7df2e56Smrg         i < pScreen->numVisuals; i++, pVisual++) {
2384f7df2e56Smrg        if (pVisual->vid != stuff->visual)
2385f7df2e56Smrg            continue;
2386f7df2e56Smrg        return CreateColormap(mid, pScreen, pVisual, &pmap,
2387f7df2e56Smrg                              (int) stuff->alloc, client->index);
238805b261ecSmrg    }
238905b261ecSmrg    client->errorValue = stuff->visual;
23906747b715Smrg    return BadMatch;
239105b261ecSmrg}
239205b261ecSmrg
239305b261ecSmrgint
239405b261ecSmrgProcFreeColormap(ClientPtr client)
239505b261ecSmrg{
239605b261ecSmrg    ColormapPtr pmap;
23974642e01fSmrg    int rc;
2398f7df2e56Smrg
239905b261ecSmrg    REQUEST(xResourceReq);
240005b261ecSmrg
240105b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
2402f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pmap, stuff->id, RT_COLORMAP,
2403f7df2e56Smrg                                 client, DixDestroyAccess);
2404f7df2e56Smrg    if (rc == Success) {
2405f7df2e56Smrg        /* Freeing a default colormap is a no-op */
2406f7df2e56Smrg        if (!(pmap->flags & IsDefault))
2407f7df2e56Smrg            FreeResource(stuff->id, RT_NONE);
2408f7df2e56Smrg        return Success;
240905b261ecSmrg    }
2410f7df2e56Smrg    else {
2411f7df2e56Smrg        client->errorValue = stuff->id;
2412f7df2e56Smrg        return rc;
241305b261ecSmrg    }
241405b261ecSmrg}
241505b261ecSmrg
241605b261ecSmrgint
241705b261ecSmrgProcCopyColormapAndFree(ClientPtr client)
241805b261ecSmrg{
2419f7df2e56Smrg    Colormap mid;
2420f7df2e56Smrg    ColormapPtr pSrcMap;
2421f7df2e56Smrg
242205b261ecSmrg    REQUEST(xCopyColormapAndFreeReq);
24234642e01fSmrg    int rc;
242405b261ecSmrg
242505b261ecSmrg    REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq);
242605b261ecSmrg    mid = stuff->mid;
242705b261ecSmrg    LEGAL_NEW_RESOURCE(mid, client);
2428f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pSrcMap, stuff->srcCmap,
2429f7df2e56Smrg                                 RT_COLORMAP, client,
2430f7df2e56Smrg                                 DixReadAccess | DixRemoveAccess);
24314642e01fSmrg    if (rc == Success)
2432f7df2e56Smrg        return CopyColormapAndFree(mid, pSrcMap, client->index);
24336747b715Smrg    client->errorValue = stuff->srcCmap;
24346747b715Smrg    return rc;
243505b261ecSmrg}
243605b261ecSmrg
243705b261ecSmrgint
243805b261ecSmrgProcInstallColormap(ClientPtr client)
243905b261ecSmrg{
244005b261ecSmrg    ColormapPtr pcmp;
24414642e01fSmrg    int rc;
2442f7df2e56Smrg
244305b261ecSmrg    REQUEST(xResourceReq);
244405b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
24454642e01fSmrg
2446f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->id, RT_COLORMAP,
2447f7df2e56Smrg                                 client, DixInstallAccess);
24484642e01fSmrg    if (rc != Success)
2449f7df2e56Smrg        goto out;
24504642e01fSmrg
24514642e01fSmrg    rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess);
24526747b715Smrg    if (rc != Success) {
2453f7df2e56Smrg        if (rc == BadValue)
2454f7df2e56Smrg            rc = BadColor;
2455f7df2e56Smrg        goto out;
24566747b715Smrg    }
24574642e01fSmrg
24584642e01fSmrg    (*(pcmp->pScreen->InstallColormap)) (pcmp);
24596747b715Smrg    return Success;
24604642e01fSmrg
2461f7df2e56Smrg out:
24624642e01fSmrg    client->errorValue = stuff->id;
24636747b715Smrg    return rc;
246405b261ecSmrg}
246505b261ecSmrg
246605b261ecSmrgint
246705b261ecSmrgProcUninstallColormap(ClientPtr client)
246805b261ecSmrg{
246905b261ecSmrg    ColormapPtr pcmp;
24704642e01fSmrg    int rc;
2471f7df2e56Smrg
247205b261ecSmrg    REQUEST(xResourceReq);
247305b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
24744642e01fSmrg
2475f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->id, RT_COLORMAP,
2476f7df2e56Smrg                                 client, DixUninstallAccess);
24774642e01fSmrg    if (rc != Success)
2478f7df2e56Smrg        goto out;
24794642e01fSmrg
24804642e01fSmrg    rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess);
24816747b715Smrg    if (rc != Success) {
2482f7df2e56Smrg        if (rc == BadValue)
2483f7df2e56Smrg            rc = BadColor;
2484f7df2e56Smrg        goto out;
24856747b715Smrg    }
24864642e01fSmrg
2487f7df2e56Smrg    if (pcmp->mid != pcmp->pScreen->defColormap)
2488f7df2e56Smrg        (*(pcmp->pScreen->UninstallColormap)) (pcmp);
24896747b715Smrg    return Success;
24904642e01fSmrg
2491f7df2e56Smrg out:
24924642e01fSmrg    client->errorValue = stuff->id;
24936747b715Smrg    return rc;
249405b261ecSmrg}
249505b261ecSmrg
249605b261ecSmrgint
249705b261ecSmrgProcListInstalledColormaps(ClientPtr client)
249805b261ecSmrg{
2499f7df2e56Smrg    xListInstalledColormapsReply *preply;
250005b261ecSmrg    int nummaps, rc;
250105b261ecSmrg    WindowPtr pWin;
2502f7df2e56Smrg
250305b261ecSmrg    REQUEST(xResourceReq);
250405b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
25054642e01fSmrg
25064642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
250705b261ecSmrg    if (rc != Success)
2508f7df2e56Smrg        return rc;
25094642e01fSmrg
25104642e01fSmrg    rc = XaceHook(XACE_SCREEN_ACCESS, client, pWin->drawable.pScreen,
2511f7df2e56Smrg                  DixGetAttrAccess);
25124642e01fSmrg    if (rc != Success)
2513f7df2e56Smrg        return rc;
251405b261ecSmrg
25156747b715Smrg    preply = malloc(sizeof(xListInstalledColormapsReply) +
2516f7df2e56Smrg                    pWin->drawable.pScreen->maxInstalledCmaps *
2517f7df2e56Smrg                    sizeof(Colormap));
2518f7df2e56Smrg    if (!preply)
25196747b715Smrg        return BadAlloc;
252005b261ecSmrg
252105b261ecSmrg    preply->type = X_Reply;
252205b261ecSmrg    preply->sequenceNumber = client->sequence;
252305b261ecSmrg    nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps)
2524f7df2e56Smrg        (pWin->drawable.pScreen, (Colormap *) &preply[1]);
252505b261ecSmrg    preply->nColormaps = nummaps;
252605b261ecSmrg    preply->length = nummaps;
2527f7df2e56Smrg    WriteReplyToClient(client, sizeof(xListInstalledColormapsReply), preply);
252805b261ecSmrg    client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
252905b261ecSmrg    WriteSwappedDataToClient(client, nummaps * sizeof(Colormap), &preply[1]);
25306747b715Smrg    free(preply);
25316747b715Smrg    return Success;
253205b261ecSmrg}
253305b261ecSmrg
253405b261ecSmrgint
2535f7df2e56SmrgProcAllocColor(ClientPtr client)
253605b261ecSmrg{
253705b261ecSmrg    ColormapPtr pmap;
25384642e01fSmrg    int rc;
2539f7df2e56Smrg
254005b261ecSmrg    REQUEST(xAllocColorReq);
254105b261ecSmrg
254205b261ecSmrg    REQUEST_SIZE_MATCH(xAllocColorReq);
2543f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pmap, stuff->cmap, RT_COLORMAP,
2544f7df2e56Smrg                                 client, DixAddAccess);
2545f7df2e56Smrg    if (rc == Success) {
2546f7df2e56Smrg        xAllocColorReply acr = {
2547f7df2e56Smrg            .type = X_Reply,
2548f7df2e56Smrg            .sequenceNumber = client->sequence,
2549f7df2e56Smrg            .length = 0,
2550f7df2e56Smrg            .red = stuff->red,
2551f7df2e56Smrg            .green = stuff->green,
2552f7df2e56Smrg            .blue = stuff->blue,
2553f7df2e56Smrg            .pixel = 0
2554f7df2e56Smrg        };
2555f7df2e56Smrg        if ((rc = AllocColor(pmap, &acr.red, &acr.green, &acr.blue,
2556f7df2e56Smrg                             &acr.pixel, client->index)))
2557f7df2e56Smrg            return rc;
255805b261ecSmrg#ifdef PANORAMIX
2559f7df2e56Smrg        if (noPanoramiXExtension || !pmap->pScreen->myNum)
256005b261ecSmrg#endif
2561f7df2e56Smrg            WriteReplyToClient(client, sizeof(xAllocColorReply), &acr);
2562f7df2e56Smrg        return Success;
256305b261ecSmrg
256405b261ecSmrg    }
2565f7df2e56Smrg    else {
256605b261ecSmrg        client->errorValue = stuff->cmap;
25676747b715Smrg        return rc;
256805b261ecSmrg    }
256905b261ecSmrg}
257005b261ecSmrg
257105b261ecSmrgint
2572f7df2e56SmrgProcAllocNamedColor(ClientPtr client)
257305b261ecSmrg{
257405b261ecSmrg    ColormapPtr pcmp;
25754642e01fSmrg    int rc;
2576f7df2e56Smrg
257705b261ecSmrg    REQUEST(xAllocNamedColorReq);
257805b261ecSmrg
257905b261ecSmrg    REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes);
2580f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2581f7df2e56Smrg                                 client, DixAddAccess);
2582f7df2e56Smrg    if (rc == Success) {
2583f7df2e56Smrg        xAllocNamedColorReply ancr = {
2584f7df2e56Smrg            .type = X_Reply,
2585f7df2e56Smrg            .sequenceNumber = client->sequence,
2586f7df2e56Smrg            .length = 0
2587f7df2e56Smrg        };
2588f7df2e56Smrg        if (OsLookupColor
2589f7df2e56Smrg            (pcmp->pScreen->myNum, (char *) &stuff[1], stuff->nbytes,
2590f7df2e56Smrg             &ancr.exactRed, &ancr.exactGreen, &ancr.exactBlue)) {
2591f7df2e56Smrg            ancr.screenRed = ancr.exactRed;
2592f7df2e56Smrg            ancr.screenGreen = ancr.exactGreen;
2593f7df2e56Smrg            ancr.screenBlue = ancr.exactBlue;
2594f7df2e56Smrg            ancr.pixel = 0;
2595f7df2e56Smrg            if ((rc = AllocColor(pcmp,
2596f7df2e56Smrg                                 &ancr.screenRed, &ancr.screenGreen,
2597f7df2e56Smrg                                 &ancr.screenBlue, &ancr.pixel, client->index)))
2598f7df2e56Smrg                return rc;
259905b261ecSmrg#ifdef PANORAMIX
2600f7df2e56Smrg            if (noPanoramiXExtension || !pcmp->pScreen->myNum)
260105b261ecSmrg#endif
2602f7df2e56Smrg                WriteReplyToClient(client, sizeof(xAllocNamedColorReply),
2603f7df2e56Smrg                                   &ancr);
2604f7df2e56Smrg            return Success;
2605f7df2e56Smrg        }
2606f7df2e56Smrg        else
2607f7df2e56Smrg            return BadName;
2608f7df2e56Smrg
260905b261ecSmrg    }
2610f7df2e56Smrg    else {
261105b261ecSmrg        client->errorValue = stuff->cmap;
26126747b715Smrg        return rc;
261305b261ecSmrg    }
261405b261ecSmrg}
261505b261ecSmrg
261605b261ecSmrgint
2617f7df2e56SmrgProcAllocColorCells(ClientPtr client)
261805b261ecSmrg{
261905b261ecSmrg    ColormapPtr pcmp;
26204642e01fSmrg    int rc;
2621f7df2e56Smrg
262205b261ecSmrg    REQUEST(xAllocColorCellsReq);
262305b261ecSmrg
262405b261ecSmrg    REQUEST_SIZE_MATCH(xAllocColorCellsReq);
2625f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2626f7df2e56Smrg                                 client, DixAddAccess);
2627f7df2e56Smrg    if (rc == Success) {
2628f7df2e56Smrg        int npixels, nmasks;
2629f7df2e56Smrg        long length;
2630f7df2e56Smrg        Pixel *ppixels, *pmasks;
2631f7df2e56Smrg
2632f7df2e56Smrg        npixels = stuff->colors;
2633f7df2e56Smrg        if (!npixels) {
2634f7df2e56Smrg            client->errorValue = npixels;
2635f7df2e56Smrg            return BadValue;
2636f7df2e56Smrg        }
2637f7df2e56Smrg        if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) {
2638f7df2e56Smrg            client->errorValue = stuff->contiguous;
2639f7df2e56Smrg            return BadValue;
2640f7df2e56Smrg        }
2641f7df2e56Smrg        nmasks = stuff->planes;
2642f7df2e56Smrg        length = ((long) npixels + (long) nmasks) * sizeof(Pixel);
2643f7df2e56Smrg        ppixels = malloc(length);
2644f7df2e56Smrg        if (!ppixels)
26456747b715Smrg            return BadAlloc;
2646f7df2e56Smrg        pmasks = ppixels + npixels;
2647f7df2e56Smrg
2648f7df2e56Smrg        if ((rc = AllocColorCells(client->index, pcmp, npixels, nmasks,
2649f7df2e56Smrg                                  (Bool) stuff->contiguous, ppixels, pmasks))) {
2650f7df2e56Smrg            free(ppixels);
2651f7df2e56Smrg            return rc;
2652f7df2e56Smrg        }
265305b261ecSmrg#ifdef PANORAMIX
2654f7df2e56Smrg        if (noPanoramiXExtension || !pcmp->pScreen->myNum)
265505b261ecSmrg#endif
2656f7df2e56Smrg        {
2657f7df2e56Smrg            xAllocColorCellsReply accr = {
2658f7df2e56Smrg                .type = X_Reply,
2659f7df2e56Smrg                .sequenceNumber = client->sequence,
2660f7df2e56Smrg                .length = bytes_to_int32(length),
2661f7df2e56Smrg                .nPixels = npixels,
2662f7df2e56Smrg                .nMasks = nmasks
2663f7df2e56Smrg            };
2664f7df2e56Smrg            WriteReplyToClient(client, sizeof(xAllocColorCellsReply), &accr);
2665f7df2e56Smrg            client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
2666f7df2e56Smrg            WriteSwappedDataToClient(client, length, ppixels);
2667f7df2e56Smrg        }
2668f7df2e56Smrg        free(ppixels);
26696747b715Smrg        return Success;
267005b261ecSmrg    }
2671f7df2e56Smrg    else {
267205b261ecSmrg        client->errorValue = stuff->cmap;
26736747b715Smrg        return rc;
267405b261ecSmrg    }
267505b261ecSmrg}
267605b261ecSmrg
267705b261ecSmrgint
267805b261ecSmrgProcAllocColorPlanes(ClientPtr client)
267905b261ecSmrg{
268005b261ecSmrg    ColormapPtr pcmp;
26814642e01fSmrg    int rc;
2682f7df2e56Smrg
268305b261ecSmrg    REQUEST(xAllocColorPlanesReq);
268405b261ecSmrg
268505b261ecSmrg    REQUEST_SIZE_MATCH(xAllocColorPlanesReq);
2686f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2687f7df2e56Smrg                                 client, DixAddAccess);
2688f7df2e56Smrg    if (rc == Success) {
2689f7df2e56Smrg        xAllocColorPlanesReply acpr;
2690f7df2e56Smrg        int npixels;
2691f7df2e56Smrg        long length;
2692f7df2e56Smrg        Pixel *ppixels;
2693f7df2e56Smrg
2694f7df2e56Smrg        npixels = stuff->colors;
2695f7df2e56Smrg        if (!npixels) {
2696f7df2e56Smrg            client->errorValue = npixels;
2697f7df2e56Smrg            return BadValue;
2698f7df2e56Smrg        }
2699f7df2e56Smrg        if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) {
2700f7df2e56Smrg            client->errorValue = stuff->contiguous;
2701f7df2e56Smrg            return BadValue;
2702f7df2e56Smrg        }
2703f7df2e56Smrg        acpr = (xAllocColorPlanesReply) {
2704f7df2e56Smrg            .type = X_Reply,
2705f7df2e56Smrg            .sequenceNumber = client->sequence,
2706f7df2e56Smrg            .nPixels = npixels
2707f7df2e56Smrg        };
2708f7df2e56Smrg        length = (long) npixels *sizeof(Pixel);
2709f7df2e56Smrg
2710f7df2e56Smrg        ppixels = malloc(length);
2711f7df2e56Smrg        if (!ppixels)
27126747b715Smrg            return BadAlloc;
2713f7df2e56Smrg        if ((rc = AllocColorPlanes(client->index, pcmp, npixels,
2714f7df2e56Smrg                                   (int) stuff->red, (int) stuff->green,
2715f7df2e56Smrg                                   (int) stuff->blue, (Bool) stuff->contiguous,
2716f7df2e56Smrg                                   ppixels, &acpr.redMask, &acpr.greenMask,
2717f7df2e56Smrg                                   &acpr.blueMask))) {
27186747b715Smrg            free(ppixels);
2719f7df2e56Smrg            return rc;
2720f7df2e56Smrg        }
2721f7df2e56Smrg        acpr.length = bytes_to_int32(length);
272205b261ecSmrg#ifdef PANORAMIX
2723f7df2e56Smrg        if (noPanoramiXExtension || !pcmp->pScreen->myNum)
272405b261ecSmrg#endif
2725f7df2e56Smrg        {
2726f7df2e56Smrg            WriteReplyToClient(client, sizeof(xAllocColorPlanesReply), &acpr);
2727f7df2e56Smrg            client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
2728f7df2e56Smrg            WriteSwappedDataToClient(client, length, ppixels);
2729f7df2e56Smrg        }
2730f7df2e56Smrg        free(ppixels);
27316747b715Smrg        return Success;
273205b261ecSmrg    }
2733f7df2e56Smrg    else {
273405b261ecSmrg        client->errorValue = stuff->cmap;
27356747b715Smrg        return rc;
273605b261ecSmrg    }
273705b261ecSmrg}
273805b261ecSmrg
273905b261ecSmrgint
274005b261ecSmrgProcFreeColors(ClientPtr client)
274105b261ecSmrg{
274205b261ecSmrg    ColormapPtr pcmp;
27434642e01fSmrg    int rc;
2744f7df2e56Smrg
274505b261ecSmrg    REQUEST(xFreeColorsReq);
274605b261ecSmrg
274705b261ecSmrg    REQUEST_AT_LEAST_SIZE(xFreeColorsReq);
2748f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2749f7df2e56Smrg                                 client, DixRemoveAccess);
2750f7df2e56Smrg    if (rc == Success) {
2751f7df2e56Smrg        int count;
275205b261ecSmrg
2753f7df2e56Smrg        if (pcmp->flags & AllAllocated)
2754f7df2e56Smrg            return BadAccess;
2755f7df2e56Smrg        count = bytes_to_int32((client->req_len << 2) - sizeof(xFreeColorsReq));
2756f7df2e56Smrg        return FreeColors(pcmp, client->index, count,
2757f7df2e56Smrg                          (Pixel *) &stuff[1], (Pixel) stuff->planeMask);
275805b261ecSmrg    }
2759f7df2e56Smrg    else {
276005b261ecSmrg        client->errorValue = stuff->cmap;
27616747b715Smrg        return rc;
276205b261ecSmrg    }
276305b261ecSmrg}
276405b261ecSmrg
276505b261ecSmrgint
2766f7df2e56SmrgProcStoreColors(ClientPtr client)
276705b261ecSmrg{
276805b261ecSmrg    ColormapPtr pcmp;
27694642e01fSmrg    int rc;
2770f7df2e56Smrg
277105b261ecSmrg    REQUEST(xStoreColorsReq);
277205b261ecSmrg
277305b261ecSmrg    REQUEST_AT_LEAST_SIZE(xStoreColorsReq);
2774f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2775f7df2e56Smrg                                 client, DixWriteAccess);
2776f7df2e56Smrg    if (rc == Success) {
2777f7df2e56Smrg        int count;
277805b261ecSmrg
277905b261ecSmrg        count = (client->req_len << 2) - sizeof(xStoreColorsReq);
2780f7df2e56Smrg        if (count % sizeof(xColorItem))
2781f7df2e56Smrg            return BadLength;
2782f7df2e56Smrg        count /= sizeof(xColorItem);
2783f7df2e56Smrg        return StoreColors(pcmp, count, (xColorItem *) &stuff[1], client);
278405b261ecSmrg    }
2785f7df2e56Smrg    else {
278605b261ecSmrg        client->errorValue = stuff->cmap;
27876747b715Smrg        return rc;
278805b261ecSmrg    }
278905b261ecSmrg}
279005b261ecSmrg
279105b261ecSmrgint
2792f7df2e56SmrgProcStoreNamedColor(ClientPtr client)
279305b261ecSmrg{
279405b261ecSmrg    ColormapPtr pcmp;
27954642e01fSmrg    int rc;
2796f7df2e56Smrg
279705b261ecSmrg    REQUEST(xStoreNamedColorReq);
279805b261ecSmrg
279905b261ecSmrg    REQUEST_FIXED_SIZE(xStoreNamedColorReq, stuff->nbytes);
2800f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2801f7df2e56Smrg                                 client, DixWriteAccess);
2802f7df2e56Smrg    if (rc == Success) {
2803f7df2e56Smrg        xColorItem def;
2804f7df2e56Smrg
2805f7df2e56Smrg        if (OsLookupColor(pcmp->pScreen->myNum, (char *) &stuff[1],
2806f7df2e56Smrg                          stuff->nbytes, &def.red, &def.green, &def.blue)) {
2807f7df2e56Smrg            def.flags = stuff->flags;
2808f7df2e56Smrg            def.pixel = stuff->pixel;
2809f7df2e56Smrg            return StoreColors(pcmp, 1, &def, client);
2810f7df2e56Smrg        }
28116747b715Smrg        return BadName;
281205b261ecSmrg    }
2813f7df2e56Smrg    else {
281405b261ecSmrg        client->errorValue = stuff->cmap;
28156747b715Smrg        return rc;
281605b261ecSmrg    }
281705b261ecSmrg}
281805b261ecSmrg
281905b261ecSmrgint
282005b261ecSmrgProcQueryColors(ClientPtr client)
282105b261ecSmrg{
282205b261ecSmrg    ColormapPtr pcmp;
28234642e01fSmrg    int rc;
2824f7df2e56Smrg
282505b261ecSmrg    REQUEST(xQueryColorsReq);
282605b261ecSmrg
282705b261ecSmrg    REQUEST_AT_LEAST_SIZE(xQueryColorsReq);
2828f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2829f7df2e56Smrg                                 client, DixReadAccess);
2830f7df2e56Smrg    if (rc == Success) {
2831f7df2e56Smrg        int count;
2832f7df2e56Smrg        xrgb *prgbs;
2833f7df2e56Smrg        xQueryColorsReply qcr;
2834f7df2e56Smrg
2835f7df2e56Smrg        count =
2836f7df2e56Smrg            bytes_to_int32((client->req_len << 2) - sizeof(xQueryColorsReq));
2837f7df2e56Smrg        prgbs = calloc(count, sizeof(xrgb));
2838f7df2e56Smrg        if (!prgbs && count)
28396747b715Smrg            return BadAlloc;
2840f7df2e56Smrg        if ((rc =
2841f7df2e56Smrg             QueryColors(pcmp, count, (Pixel *) &stuff[1], prgbs, client))) {
2842f7df2e56Smrg            free(prgbs);
2843f7df2e56Smrg            return rc;
2844f7df2e56Smrg        }
2845f7df2e56Smrg        qcr = (xQueryColorsReply) {
2846f7df2e56Smrg            .type = X_Reply,
2847f7df2e56Smrg            .sequenceNumber = client->sequence,
2848f7df2e56Smrg            .length = bytes_to_int32(count * sizeof(xrgb)),
2849f7df2e56Smrg            .nColors = count
2850f7df2e56Smrg        };
2851f7df2e56Smrg        WriteReplyToClient(client, sizeof(xQueryColorsReply), &qcr);
2852f7df2e56Smrg        if (count) {
2853f7df2e56Smrg            client->pSwapReplyFunc = (ReplySwapPtr) SQColorsExtend;
2854f7df2e56Smrg            WriteSwappedDataToClient(client, count * sizeof(xrgb), prgbs);
2855f7df2e56Smrg        }
2856f7df2e56Smrg        free(prgbs);
2857f7df2e56Smrg        return Success;
2858f7df2e56Smrg
285905b261ecSmrg    }
2860f7df2e56Smrg    else {
286105b261ecSmrg        client->errorValue = stuff->cmap;
28626747b715Smrg        return rc;
286305b261ecSmrg    }
2864f7df2e56Smrg}
286505b261ecSmrg
286605b261ecSmrgint
286705b261ecSmrgProcLookupColor(ClientPtr client)
286805b261ecSmrg{
286905b261ecSmrg    ColormapPtr pcmp;
28704642e01fSmrg    int rc;
2871f7df2e56Smrg
287205b261ecSmrg    REQUEST(xLookupColorReq);
287305b261ecSmrg
287405b261ecSmrg    REQUEST_FIXED_SIZE(xLookupColorReq, stuff->nbytes);
2875f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2876f7df2e56Smrg                                 client, DixReadAccess);
2877f7df2e56Smrg    if (rc == Success) {
2878f7df2e56Smrg        CARD16 exactRed, exactGreen, exactBlue;
2879f7df2e56Smrg
2880f7df2e56Smrg        if (OsLookupColor
2881f7df2e56Smrg            (pcmp->pScreen->myNum, (char *) &stuff[1], stuff->nbytes,
2882f7df2e56Smrg             &exactRed, &exactGreen, &exactBlue)) {
2883f7df2e56Smrg            xLookupColorReply lcr = {
2884f7df2e56Smrg                .type = X_Reply,
2885f7df2e56Smrg                .sequenceNumber = client->sequence,
2886f7df2e56Smrg                .length = 0,
2887f7df2e56Smrg                .exactRed = exactRed,
2888f7df2e56Smrg                .exactGreen = exactGreen,
2889f7df2e56Smrg                .exactBlue = exactBlue,
2890f7df2e56Smrg                .screenRed = exactRed,
2891f7df2e56Smrg                .screenGreen = exactGreen,
2892f7df2e56Smrg                .screenBlue = exactBlue
2893f7df2e56Smrg            };
2894f7df2e56Smrg            (*pcmp->pScreen->ResolveColor) (&lcr.screenRed,
2895f7df2e56Smrg                                            &lcr.screenGreen,
2896f7df2e56Smrg                                            &lcr.screenBlue, pcmp->pVisual);
2897f7df2e56Smrg            WriteReplyToClient(client, sizeof(xLookupColorReply), &lcr);
2898f7df2e56Smrg            return Success;
2899f7df2e56Smrg        }
29006747b715Smrg        return BadName;
290105b261ecSmrg    }
2902f7df2e56Smrg    else {
290305b261ecSmrg        client->errorValue = stuff->cmap;
29046747b715Smrg        return rc;
290505b261ecSmrg    }
290605b261ecSmrg}
290705b261ecSmrg
290805b261ecSmrgint
2909f7df2e56SmrgProcCreateCursor(ClientPtr client)
291005b261ecSmrg{
2911f7df2e56Smrg    CursorPtr pCursor;
2912f7df2e56Smrg    PixmapPtr src;
2913f7df2e56Smrg    PixmapPtr msk;
2914f7df2e56Smrg    unsigned char *srcbits;
2915f7df2e56Smrg    unsigned char *mskbits;
2916f7df2e56Smrg    unsigned short width, height;
2917f7df2e56Smrg    long n;
2918f7df2e56Smrg    CursorMetricRec cm;
29194642e01fSmrg    int rc;
292005b261ecSmrg
292105b261ecSmrg    REQUEST(xCreateCursorReq);
292205b261ecSmrg
292305b261ecSmrg    REQUEST_SIZE_MATCH(xCreateCursorReq);
292405b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->cid, client);
292505b261ecSmrg
2926f7df2e56Smrg    rc = dixLookupResourceByType((void **) &src, stuff->source, RT_PIXMAP,
2927f7df2e56Smrg                                 client, DixReadAccess);
29284642e01fSmrg    if (rc != Success) {
2929f7df2e56Smrg        client->errorValue = stuff->source;
2930f7df2e56Smrg        return rc;
293105b261ecSmrg    }
29324642e01fSmrg
2933f7df2e56Smrg    if (src->drawable.depth != 1)
2934f7df2e56Smrg        return (BadMatch);
2935f7df2e56Smrg
2936f7df2e56Smrg    /* Find and validate cursor mask pixmap, if one is provided */
2937f7df2e56Smrg    if (stuff->mask != None) {
2938f7df2e56Smrg        rc = dixLookupResourceByType((void **) &msk, stuff->mask, RT_PIXMAP,
2939f7df2e56Smrg                                     client, DixReadAccess);
2940f7df2e56Smrg        if (rc != Success) {
2941f7df2e56Smrg            client->errorValue = stuff->mask;
2942f7df2e56Smrg            return rc;
2943f7df2e56Smrg        }
2944f7df2e56Smrg
2945f7df2e56Smrg        if (src->drawable.width != msk->drawable.width
2946f7df2e56Smrg            || src->drawable.height != msk->drawable.height
2947f7df2e56Smrg            || src->drawable.depth != 1 || msk->drawable.depth != 1)
2948f7df2e56Smrg            return BadMatch;
2949f7df2e56Smrg    }
2950f7df2e56Smrg    else
2951f7df2e56Smrg        msk = NULL;
295205b261ecSmrg
295305b261ecSmrg    width = src->drawable.width;
295405b261ecSmrg    height = src->drawable.height;
295505b261ecSmrg
2956f7df2e56Smrg    if (stuff->x > width || stuff->y > height)
2957f7df2e56Smrg        return BadMatch;
295805b261ecSmrg
2959f7df2e56Smrg    srcbits = calloc(BitmapBytePad(width), height);
296005b261ecSmrg    if (!srcbits)
2961f7df2e56Smrg        return BadAlloc;
2962f7df2e56Smrg    n = BitmapBytePad(width) * height;
29636747b715Smrg    mskbits = malloc(n);
2964f7df2e56Smrg    if (!mskbits) {
2965f7df2e56Smrg        free(srcbits);
2966f7df2e56Smrg        return BadAlloc;
296705b261ecSmrg    }
296805b261ecSmrg
2969f7df2e56Smrg    (*src->drawable.pScreen->GetImage) ((DrawablePtr) src, 0, 0, width, height,
2970f7df2e56Smrg                                        XYPixmap, 1, (void *) srcbits);
2971f7df2e56Smrg    if (msk == (PixmapPtr) NULL) {
2972f7df2e56Smrg        unsigned char *bits = mskbits;
2973f7df2e56Smrg
2974f7df2e56Smrg        while (--n >= 0)
2975f7df2e56Smrg            *bits++ = ~0;
297605b261ecSmrg    }
2977f7df2e56Smrg    else {
2978f7df2e56Smrg        /* zeroing the (pad) bits helps some ddx cursor handling */
2979f7df2e56Smrg        memset((char *) mskbits, 0, n);
2980f7df2e56Smrg        (*msk->drawable.pScreen->GetImage) ((DrawablePtr) msk, 0, 0, width,
2981f7df2e56Smrg                                            height, XYPixmap, 1,
2982f7df2e56Smrg                                            (void *) mskbits);
298305b261ecSmrg    }
298405b261ecSmrg    cm.width = width;
298505b261ecSmrg    cm.height = height;
298605b261ecSmrg    cm.xhot = stuff->x;
298705b261ecSmrg    cm.yhot = stuff->y;
29884642e01fSmrg    rc = AllocARGBCursor(srcbits, mskbits, NULL, &cm,
2989f7df2e56Smrg                         stuff->foreRed, stuff->foreGreen, stuff->foreBlue,
2990f7df2e56Smrg                         stuff->backRed, stuff->backGreen, stuff->backBlue,
2991f7df2e56Smrg                         &pCursor, client, stuff->cid);
299205b261ecSmrg
29934642e01fSmrg    if (rc != Success)
2994f7df2e56Smrg        goto bail;
2995f7df2e56Smrg    if (!AddResource(stuff->cid, RT_CURSOR, (void *) pCursor)) {
2996f7df2e56Smrg        rc = BadAlloc;
2997f7df2e56Smrg        goto bail;
2998f7df2e56Smrg    }
29994642e01fSmrg
30006747b715Smrg    return Success;
3001f7df2e56Smrg bail:
3002f7df2e56Smrg    free(srcbits);
3003f7df2e56Smrg    free(mskbits);
3004f7df2e56Smrg    return rc;
300505b261ecSmrg}
300605b261ecSmrg
300705b261ecSmrgint
3008f7df2e56SmrgProcCreateGlyphCursor(ClientPtr client)
300905b261ecSmrg{
301005b261ecSmrg    CursorPtr pCursor;
301105b261ecSmrg    int res;
301205b261ecSmrg
301305b261ecSmrg    REQUEST(xCreateGlyphCursorReq);
301405b261ecSmrg
301505b261ecSmrg    REQUEST_SIZE_MATCH(xCreateGlyphCursorReq);
301605b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->cid, client);
301705b261ecSmrg
301805b261ecSmrg    res = AllocGlyphCursor(stuff->source, stuff->sourceChar,
3019f7df2e56Smrg                           stuff->mask, stuff->maskChar,
3020f7df2e56Smrg                           stuff->foreRed, stuff->foreGreen, stuff->foreBlue,
3021f7df2e56Smrg                           stuff->backRed, stuff->backGreen, stuff->backBlue,
3022f7df2e56Smrg                           &pCursor, client, stuff->cid);
302305b261ecSmrg    if (res != Success)
3024f7df2e56Smrg        return res;
3025f7df2e56Smrg    if (AddResource(stuff->cid, RT_CURSOR, (void *) pCursor))
3026f7df2e56Smrg        return Success;
302705b261ecSmrg    return BadAlloc;
302805b261ecSmrg}
302905b261ecSmrg
303005b261ecSmrgint
3031f7df2e56SmrgProcFreeCursor(ClientPtr client)
303205b261ecSmrg{
303305b261ecSmrg    CursorPtr pCursor;
30344642e01fSmrg    int rc;
3035f7df2e56Smrg
303605b261ecSmrg    REQUEST(xResourceReq);
303705b261ecSmrg
303805b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
3039f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pCursor, stuff->id, RT_CURSOR,
3040f7df2e56Smrg                                 client, DixDestroyAccess);
3041f7df2e56Smrg    if (rc == Success) {
3042f7df2e56Smrg        FreeResource(stuff->id, RT_NONE);
3043f7df2e56Smrg        return Success;
304405b261ecSmrg    }
3045f7df2e56Smrg    else {
3046f7df2e56Smrg        client->errorValue = stuff->id;
3047f7df2e56Smrg        return rc;
304805b261ecSmrg    }
304905b261ecSmrg}
305005b261ecSmrg
305105b261ecSmrgint
3052f7df2e56SmrgProcQueryBestSize(ClientPtr client)
305305b261ecSmrg{
3054f7df2e56Smrg    xQueryBestSizeReply reply;
305505b261ecSmrg    DrawablePtr pDraw;
305605b261ecSmrg    ScreenPtr pScreen;
305705b261ecSmrg    int rc;
3058f7df2e56Smrg
305905b261ecSmrg    REQUEST(xQueryBestSizeReq);
306005b261ecSmrg    REQUEST_SIZE_MATCH(xQueryBestSizeReq);
306105b261ecSmrg
3062f7df2e56Smrg    if ((stuff->class != CursorShape) &&
3063f7df2e56Smrg        (stuff->class != TileShape) && (stuff->class != StippleShape)) {
3064f7df2e56Smrg        client->errorValue = stuff->class;
30656747b715Smrg        return BadValue;
306605b261ecSmrg    }
306705b261ecSmrg
306805b261ecSmrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
3069f7df2e56Smrg                           DixGetAttrAccess);
307005b261ecSmrg    if (rc != Success)
3071f7df2e56Smrg        return rc;
307205b261ecSmrg    if (stuff->class != CursorShape && pDraw->type == UNDRAWABLE_WINDOW)
3073f7df2e56Smrg        return BadMatch;
307405b261ecSmrg    pScreen = pDraw->pScreen;
30754642e01fSmrg    rc = XaceHook(XACE_SCREEN_ACCESS, client, pScreen, DixGetAttrAccess);
30764642e01fSmrg    if (rc != Success)
3077f7df2e56Smrg        return rc;
3078f7df2e56Smrg    (*pScreen->QueryBestSize) (stuff->class, &stuff->width,
3079f7df2e56Smrg                               &stuff->height, pScreen);
3080f7df2e56Smrg    reply = (xQueryBestSizeReply) {
3081f7df2e56Smrg        .type = X_Reply,
3082f7df2e56Smrg        .sequenceNumber = client->sequence,
3083f7df2e56Smrg        .length = 0,
3084f7df2e56Smrg        .width = stuff->width,
3085f7df2e56Smrg        .height = stuff->height
3086f7df2e56Smrg    };
308705b261ecSmrg    WriteReplyToClient(client, sizeof(xQueryBestSizeReply), &reply);
30886747b715Smrg    return Success;
308905b261ecSmrg}
309005b261ecSmrg
309105b261ecSmrgint
3092f7df2e56SmrgProcSetScreenSaver(ClientPtr client)
309305b261ecSmrg{
30944642e01fSmrg    int rc, i, blankingOption, exposureOption;
3095f7df2e56Smrg
309605b261ecSmrg    REQUEST(xSetScreenSaverReq);
309705b261ecSmrg    REQUEST_SIZE_MATCH(xSetScreenSaverReq);
30984642e01fSmrg
30994642e01fSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
3100f7df2e56Smrg        rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i],
3101f7df2e56Smrg                      DixSetAttrAccess);
3102f7df2e56Smrg        if (rc != Success)
3103f7df2e56Smrg            return rc;
31044642e01fSmrg    }
31054642e01fSmrg
310605b261ecSmrg    blankingOption = stuff->preferBlank;
310705b261ecSmrg    if ((blankingOption != DontPreferBlanking) &&
310805b261ecSmrg        (blankingOption != PreferBlanking) &&
3109f7df2e56Smrg        (blankingOption != DefaultBlanking)) {
3110f7df2e56Smrg        client->errorValue = blankingOption;
311105b261ecSmrg        return BadValue;
311205b261ecSmrg    }
311305b261ecSmrg    exposureOption = stuff->allowExpose;
311405b261ecSmrg    if ((exposureOption != DontAllowExposures) &&
311505b261ecSmrg        (exposureOption != AllowExposures) &&
3116f7df2e56Smrg        (exposureOption != DefaultExposures)) {
3117f7df2e56Smrg        client->errorValue = exposureOption;
311805b261ecSmrg        return BadValue;
311905b261ecSmrg    }
3120f7df2e56Smrg    if (stuff->timeout < -1) {
3121f7df2e56Smrg        client->errorValue = stuff->timeout;
312205b261ecSmrg        return BadValue;
312305b261ecSmrg    }
3124f7df2e56Smrg    if (stuff->interval < -1) {
3125f7df2e56Smrg        client->errorValue = stuff->interval;
312605b261ecSmrg        return BadValue;
312705b261ecSmrg    }
312805b261ecSmrg
312905b261ecSmrg    if (blankingOption == DefaultBlanking)
3130f7df2e56Smrg        ScreenSaverBlanking = defaultScreenSaverBlanking;
313105b261ecSmrg    else
3132f7df2e56Smrg        ScreenSaverBlanking = blankingOption;
313305b261ecSmrg    if (exposureOption == DefaultExposures)
3134f7df2e56Smrg        ScreenSaverAllowExposures = defaultScreenSaverAllowExposures;
313505b261ecSmrg    else
3136f7df2e56Smrg        ScreenSaverAllowExposures = exposureOption;
313705b261ecSmrg
313805b261ecSmrg    if (stuff->timeout >= 0)
3139f7df2e56Smrg        ScreenSaverTime = stuff->timeout * MILLI_PER_SECOND;
3140f7df2e56Smrg    else
3141f7df2e56Smrg        ScreenSaverTime = defaultScreenSaverTime;
314205b261ecSmrg    if (stuff->interval >= 0)
3143f7df2e56Smrg        ScreenSaverInterval = stuff->interval * MILLI_PER_SECOND;
314405b261ecSmrg    else
3145f7df2e56Smrg        ScreenSaverInterval = defaultScreenSaverInterval;
314605b261ecSmrg
314705b261ecSmrg    SetScreenSaverTimer();
31486747b715Smrg    return Success;
314905b261ecSmrg}
315005b261ecSmrg
315105b261ecSmrgint
315205b261ecSmrgProcGetScreenSaver(ClientPtr client)
315305b261ecSmrg{
315405b261ecSmrg    xGetScreenSaverReply rep;
31554642e01fSmrg    int rc, i;
3156f7df2e56Smrg
315705b261ecSmrg    REQUEST_SIZE_MATCH(xReq);
31584642e01fSmrg
31594642e01fSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
3160f7df2e56Smrg        rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i],
3161f7df2e56Smrg                      DixGetAttrAccess);
3162f7df2e56Smrg        if (rc != Success)
3163f7df2e56Smrg            return rc;
3164f7df2e56Smrg    }
3165f7df2e56Smrg
3166f7df2e56Smrg    rep = (xGetScreenSaverReply) {
3167f7df2e56Smrg        .type = X_Reply,
3168f7df2e56Smrg        .sequenceNumber = client->sequence,
3169f7df2e56Smrg        .length = 0,
3170f7df2e56Smrg        .timeout = ScreenSaverTime / MILLI_PER_SECOND,
3171f7df2e56Smrg        .interval = ScreenSaverInterval / MILLI_PER_SECOND,
3172f7df2e56Smrg        .preferBlanking = ScreenSaverBlanking,
3173f7df2e56Smrg        .allowExposures = ScreenSaverAllowExposures
3174f7df2e56Smrg    };
317505b261ecSmrg    WriteReplyToClient(client, sizeof(xGetScreenSaverReply), &rep);
31766747b715Smrg    return Success;
317705b261ecSmrg}
317805b261ecSmrg
317905b261ecSmrgint
318005b261ecSmrgProcChangeHosts(ClientPtr client)
318105b261ecSmrg{
318205b261ecSmrg    REQUEST(xChangeHostsReq);
318305b261ecSmrg
318405b261ecSmrg    REQUEST_FIXED_SIZE(xChangeHostsReq, stuff->hostLength);
318505b261ecSmrg
3186f7df2e56Smrg    if (stuff->mode == HostInsert)
3187f7df2e56Smrg        return AddHost(client, (int) stuff->hostFamily,
3188f7df2e56Smrg                       stuff->hostLength, (void *) &stuff[1]);
31896747b715Smrg    if (stuff->mode == HostDelete)
3190f7df2e56Smrg        return RemoveHost(client, (int) stuff->hostFamily,
3191f7df2e56Smrg                          stuff->hostLength, (void *) &stuff[1]);
31926747b715Smrg    client->errorValue = stuff->mode;
31936747b715Smrg    return BadValue;
319405b261ecSmrg}
319505b261ecSmrg
319605b261ecSmrgint
319705b261ecSmrgProcListHosts(ClientPtr client)
319805b261ecSmrg{
319905b261ecSmrg    xListHostsReply reply;
3200f7df2e56Smrg    int len, nHosts, result;
3201f7df2e56Smrg    BOOL enabled;
3202f7df2e56Smrg    void *pdata;
3203f7df2e56Smrg
320405b261ecSmrg    /* REQUEST(xListHostsReq); */
320505b261ecSmrg
320605b261ecSmrg    REQUEST_SIZE_MATCH(xListHostsReq);
320705b261ecSmrg
320805b261ecSmrg    /* untrusted clients can't list hosts */
32094642e01fSmrg    result = XaceHook(XACE_SERVER_ACCESS, client, DixReadAccess);
32104642e01fSmrg    if (result != Success)
3211f7df2e56Smrg        return result;
321205b261ecSmrg
3213f7df2e56Smrg    result = GetHosts(&pdata, &nHosts, &len, &enabled);
321405b261ecSmrg    if (result != Success)
3215f7df2e56Smrg        return result;
3216f7df2e56Smrg
3217f7df2e56Smrg    reply = (xListHostsReply) {
3218f7df2e56Smrg        .type = X_Reply,
3219f7df2e56Smrg        .enabled = enabled,
3220f7df2e56Smrg        .sequenceNumber = client->sequence,
3221f7df2e56Smrg        .length = bytes_to_int32(len),
3222f7df2e56Smrg        .nHosts = nHosts
3223f7df2e56Smrg    };
322405b261ecSmrg    WriteReplyToClient(client, sizeof(xListHostsReply), &reply);
3225f7df2e56Smrg    if (nHosts) {
3226f7df2e56Smrg        client->pSwapReplyFunc = (ReplySwapPtr) SLHostsExtend;
3227f7df2e56Smrg        WriteSwappedDataToClient(client, len, pdata);
322805b261ecSmrg    }
32296747b715Smrg    free(pdata);
32306747b715Smrg    return Success;
323105b261ecSmrg}
323205b261ecSmrg
323305b261ecSmrgint
323405b261ecSmrgProcChangeAccessControl(ClientPtr client)
323505b261ecSmrg{
323605b261ecSmrg    REQUEST(xSetAccessControlReq);
323705b261ecSmrg
323805b261ecSmrg    REQUEST_SIZE_MATCH(xSetAccessControlReq);
3239f7df2e56Smrg    if ((stuff->mode != EnableAccess) && (stuff->mode != DisableAccess)) {
3240f7df2e56Smrg        client->errorValue = stuff->mode;
324105b261ecSmrg        return BadValue;
324205b261ecSmrg    }
32436747b715Smrg    return ChangeAccessControl(client, stuff->mode == EnableAccess);
324405b261ecSmrg}
324505b261ecSmrg
324605b261ecSmrg/*********************
324705b261ecSmrg * CloseDownRetainedResources
324805b261ecSmrg *
3249f7df2e56Smrg *    Find all clients that are gone and have terminated in RetainTemporary
325005b261ecSmrg *    and destroy their resources.
325105b261ecSmrg *********************/
325205b261ecSmrg
325305b261ecSmrgstatic void
325405b261ecSmrgCloseDownRetainedResources(void)
325505b261ecSmrg{
325605b261ecSmrg    int i;
325705b261ecSmrg    ClientPtr client;
325805b261ecSmrg
3259f7df2e56Smrg    for (i = 1; i < currentMaxClients; i++) {
326005b261ecSmrg        client = clients[i];
326105b261ecSmrg        if (client && (client->closeDownMode == RetainTemporary)
3262f7df2e56Smrg            && (client->clientGone))
3263f7df2e56Smrg            CloseDownClient(client);
326405b261ecSmrg    }
326505b261ecSmrg}
326605b261ecSmrg
326705b261ecSmrgint
326805b261ecSmrgProcKillClient(ClientPtr client)
326905b261ecSmrg{
327005b261ecSmrg    REQUEST(xResourceReq);
327105b261ecSmrg    ClientPtr killclient;
327205b261ecSmrg    int rc;
327305b261ecSmrg
327405b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
3275f7df2e56Smrg    if (stuff->id == AllTemporary) {
3276f7df2e56Smrg        CloseDownRetainedResources();
32776747b715Smrg        return Success;
327805b261ecSmrg    }
327905b261ecSmrg
328005b261ecSmrg    rc = dixLookupClient(&killclient, stuff->id, client, DixDestroyAccess);
328105b261ecSmrg    if (rc == Success) {
3282f7df2e56Smrg        CloseDownClient(killclient);
3283f7df2e56Smrg        if (client == killclient) {
3284f7df2e56Smrg            /* force yield and return Success, so that Dispatch()
3285f7df2e56Smrg             * doesn't try to touch client
3286f7df2e56Smrg             */
3287f7df2e56Smrg            isItTimeToYield = TRUE;
3288f7df2e56Smrg        }
3289f7df2e56Smrg        return Success;
329005b261ecSmrg    }
329105b261ecSmrg    else
3292f7df2e56Smrg        return rc;
329305b261ecSmrg}
329405b261ecSmrg
329505b261ecSmrgint
329605b261ecSmrgProcSetFontPath(ClientPtr client)
329705b261ecSmrg{
329805b261ecSmrg    unsigned char *ptr;
329905b261ecSmrg    unsigned long nbytes, total;
330005b261ecSmrg    long nfonts;
33016747b715Smrg    int n;
3302f7df2e56Smrg
330305b261ecSmrg    REQUEST(xSetFontPathReq);
3304f7df2e56Smrg
330505b261ecSmrg    REQUEST_AT_LEAST_SIZE(xSetFontPathReq);
3306f7df2e56Smrg
330705b261ecSmrg    nbytes = (client->req_len << 2) - sizeof(xSetFontPathReq);
330805b261ecSmrg    total = nbytes;
3309f7df2e56Smrg    ptr = (unsigned char *) &stuff[1];
331005b261ecSmrg    nfonts = stuff->nFonts;
3311f7df2e56Smrg    while (--nfonts >= 0) {
3312f7df2e56Smrg        if ((total == 0) || (total < (n = (*ptr + 1))))
3313f7df2e56Smrg            return BadLength;
3314f7df2e56Smrg        total -= n;
3315f7df2e56Smrg        ptr += n;
331605b261ecSmrg    }
331705b261ecSmrg    if (total >= 4)
3318f7df2e56Smrg        return BadLength;
3319f7df2e56Smrg    return SetFontPath(client, stuff->nFonts, (unsigned char *) &stuff[1]);
332005b261ecSmrg}
332105b261ecSmrg
332205b261ecSmrgint
332305b261ecSmrgProcGetFontPath(ClientPtr client)
332405b261ecSmrg{
332505b261ecSmrg    xGetFontPathReply reply;
33264642e01fSmrg    int rc, stringLens, numpaths;
332705b261ecSmrg    unsigned char *bufferStart;
3328f7df2e56Smrg
332905b261ecSmrg    /* REQUEST (xReq); */
333005b261ecSmrg
333105b261ecSmrg    REQUEST_SIZE_MATCH(xReq);
33324642e01fSmrg    rc = GetFontPath(client, &numpaths, &stringLens, &bufferStart);
33334642e01fSmrg    if (rc != Success)
3334f7df2e56Smrg        return rc;
333505b261ecSmrg
3336f7df2e56Smrg    reply = (xGetFontPathReply) {
3337f7df2e56Smrg        .type = X_Reply,
3338f7df2e56Smrg        .sequenceNumber = client->sequence,
3339f7df2e56Smrg        .length = bytes_to_int32(stringLens + numpaths),
3340f7df2e56Smrg        .nPaths = numpaths
3341f7df2e56Smrg    };
334205b261ecSmrg
334305b261ecSmrg    WriteReplyToClient(client, sizeof(xGetFontPathReply), &reply);
334405b261ecSmrg    if (stringLens || numpaths)
3345f7df2e56Smrg        WriteToClient(client, stringLens + numpaths, bufferStart);
33466747b715Smrg    return Success;
334705b261ecSmrg}
334805b261ecSmrg
334905b261ecSmrgint
335005b261ecSmrgProcChangeCloseDownMode(ClientPtr client)
335105b261ecSmrg{
33524642e01fSmrg    int rc;
3353f7df2e56Smrg
335405b261ecSmrg    REQUEST(xSetCloseDownModeReq);
335505b261ecSmrg    REQUEST_SIZE_MATCH(xSetCloseDownModeReq);
33564642e01fSmrg
33574642e01fSmrg    rc = XaceHook(XACE_CLIENT_ACCESS, client, client, DixManageAccess);
33584642e01fSmrg    if (rc != Success)
3359f7df2e56Smrg        return rc;
33604642e01fSmrg
336105b261ecSmrg    if ((stuff->mode == AllTemporary) ||
3362f7df2e56Smrg        (stuff->mode == RetainPermanent) || (stuff->mode == RetainTemporary)) {
3363f7df2e56Smrg        client->closeDownMode = stuff->mode;
3364f7df2e56Smrg        return Success;
336505b261ecSmrg    }
3366f7df2e56Smrg    else {
3367f7df2e56Smrg        client->errorValue = stuff->mode;
3368f7df2e56Smrg        return BadValue;
336905b261ecSmrg    }
337005b261ecSmrg}
337105b261ecSmrg
3372f7df2e56Smrgint
3373f7df2e56SmrgProcForceScreenSaver(ClientPtr client)
3374f7df2e56Smrg{
33754642e01fSmrg    int rc;
3376f7df2e56Smrg
337705b261ecSmrg    REQUEST(xForceScreenSaverReq);
337805b261ecSmrg
337905b261ecSmrg    REQUEST_SIZE_MATCH(xForceScreenSaverReq);
3380f7df2e56Smrg
3381f7df2e56Smrg    if ((stuff->mode != ScreenSaverReset) && (stuff->mode != ScreenSaverActive)) {
3382f7df2e56Smrg        client->errorValue = stuff->mode;
338305b261ecSmrg        return BadValue;
338405b261ecSmrg    }
3385f7df2e56Smrg    rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, (int) stuff->mode);
33864642e01fSmrg    if (rc != Success)
3387f7df2e56Smrg        return rc;
33886747b715Smrg    return Success;
338905b261ecSmrg}
339005b261ecSmrg
3391f7df2e56Smrgint
3392f7df2e56SmrgProcNoOperation(ClientPtr client)
339305b261ecSmrg{
339405b261ecSmrg    REQUEST_AT_LEAST_SIZE(xReq);
3395f7df2e56Smrg
339605b261ecSmrg    /* noop -- don't do anything */
33976747b715Smrg    return Success;
339805b261ecSmrg}
339905b261ecSmrg
340005b261ecSmrg/**********************
340105b261ecSmrg * CloseDownClient
340205b261ecSmrg *
340305b261ecSmrg *  Client can either mark his resources destroy or retain.  If retained and
340405b261ecSmrg *  then killed again, the client is really destroyed.
340505b261ecSmrg *********************/
340605b261ecSmrg
340705b261ecSmrgchar dispatchExceptionAtReset = DE_RESET;
340805b261ecSmrg
340905b261ecSmrgvoid
341005b261ecSmrgCloseDownClient(ClientPtr client)
341105b261ecSmrg{
341205b261ecSmrg    Bool really_close_down = client->clientGone ||
3413f7df2e56Smrg        client->closeDownMode == DestroyAll;
341405b261ecSmrg
3415f7df2e56Smrg    if (!client->clientGone) {
3416f7df2e56Smrg        /* ungrab server if grabbing client dies */
3417f7df2e56Smrg        if (grabState != GrabNone && grabClient == client) {
3418f7df2e56Smrg            UngrabServer(client);
3419f7df2e56Smrg        }
3420f7df2e56Smrg        BITCLEAR(grabWaiters, client->index);
3421f7df2e56Smrg        DeleteClientFromAnySelections(client);
3422f7df2e56Smrg        ReleaseActiveGrabs(client);
3423f7df2e56Smrg        DeleteClientFontStuff(client);
3424f7df2e56Smrg        if (!really_close_down) {
3425f7df2e56Smrg            /*  This frees resources that should never be retained
3426f7df2e56Smrg             *  no matter what the close down mode is.  Actually we
3427f7df2e56Smrg             *  could do this unconditionally, but it's probably
3428f7df2e56Smrg             *  better not to traverse all the client's resources
3429f7df2e56Smrg             *  twice (once here, once a few lines down in
3430f7df2e56Smrg             *  FreeClientResources) in the common case of
3431f7df2e56Smrg             *  really_close_down == TRUE.
3432f7df2e56Smrg             */
3433f7df2e56Smrg            FreeClientNeverRetainResources(client);
3434f7df2e56Smrg            client->clientState = ClientStateRetained;
3435f7df2e56Smrg            if (ClientStateCallback) {
3436f7df2e56Smrg                NewClientInfoRec clientinfo;
3437f7df2e56Smrg
3438f7df2e56Smrg                clientinfo.client = client;
3439f7df2e56Smrg                clientinfo.prefix = (xConnSetupPrefix *) NULL;
3440f7df2e56Smrg                clientinfo.setup = (xConnSetup *) NULL;
3441f7df2e56Smrg                CallCallbacks((&ClientStateCallback), (void *) &clientinfo);
3442f7df2e56Smrg            }
3443f7df2e56Smrg        }
3444f7df2e56Smrg        client->clientGone = TRUE;      /* so events aren't sent to client */
3445f7df2e56Smrg        if (ClientIsAsleep(client))
3446f7df2e56Smrg            ClientSignal(client);
3447f7df2e56Smrg        ProcessWorkQueueZombies();
3448f7df2e56Smrg        CloseDownConnection(client);
34497e31ba66Smrg        output_pending_clear(client);
34507e31ba66Smrg        mark_client_not_ready(client);
3451f7df2e56Smrg
3452f7df2e56Smrg        /* If the client made it to the Running stage, nClients has
3453f7df2e56Smrg         * been incremented on its behalf, so we need to decrement it
3454f7df2e56Smrg         * now.  If it hasn't gotten to Running, nClients has *not*
3455f7df2e56Smrg         * been incremented, so *don't* decrement it.
3456f7df2e56Smrg         */
3457f7df2e56Smrg        if (client->clientState != ClientStateInitial) {
3458f7df2e56Smrg            --nClients;
3459f7df2e56Smrg        }
3460f7df2e56Smrg    }
3461f7df2e56Smrg
3462f7df2e56Smrg    if (really_close_down) {
3463f7df2e56Smrg        if (client->clientState == ClientStateRunning && nClients == 0)
3464f7df2e56Smrg            dispatchException |= dispatchExceptionAtReset;
3465f7df2e56Smrg
3466f7df2e56Smrg        client->clientState = ClientStateGone;
3467f7df2e56Smrg        if (ClientStateCallback) {
3468f7df2e56Smrg            NewClientInfoRec clientinfo;
3469f7df2e56Smrg
3470f7df2e56Smrg            clientinfo.client = client;
3471f7df2e56Smrg            clientinfo.prefix = (xConnSetupPrefix *) NULL;
3472f7df2e56Smrg            clientinfo.setup = (xConnSetup *) NULL;
3473f7df2e56Smrg            CallCallbacks((&ClientStateCallback), (void *) &clientinfo);
3474f7df2e56Smrg        }
3475f7df2e56Smrg        TouchListenerGone(client->clientAsMask);
3476f7df2e56Smrg        FreeClientResources(client);
3477f7df2e56Smrg        /* Disable client ID tracking. This must be done after
3478f7df2e56Smrg         * ClientStateCallback. */
3479f7df2e56Smrg        ReleaseClientIds(client);
348005b261ecSmrg#ifdef XSERVER_DTRACE
3481f7df2e56Smrg        XSERVER_CLIENT_DISCONNECT(client->index);
3482f7df2e56Smrg#endif
3483f7df2e56Smrg        if (client->index < nextFreeClientID)
3484f7df2e56Smrg            nextFreeClientID = client->index;
3485f7df2e56Smrg        clients[client->index] = NullClient;
3486f7df2e56Smrg        SmartLastClient = NullClient;
3487f7df2e56Smrg        dixFreeObjectWithPrivates(client, PRIVATE_CLIENT);
348805b261ecSmrg
3489f7df2e56Smrg        while (!clients[currentMaxClients - 1])
3490f7df2e56Smrg            currentMaxClients--;
349105b261ecSmrg    }
349205b261ecSmrg}
349305b261ecSmrg
349405b261ecSmrgstatic void
349505b261ecSmrgKillAllClients(void)
349605b261ecSmrg{
349705b261ecSmrg    int i;
3498f7df2e56Smrg
3499f7df2e56Smrg    for (i = 1; i < currentMaxClients; i++)
350005b261ecSmrg        if (clients[i]) {
350105b261ecSmrg            /* Make sure Retained clients are released. */
350205b261ecSmrg            clients[i]->closeDownMode = DestroyAll;
3503f7df2e56Smrg            CloseDownClient(clients[i]);
350405b261ecSmrg        }
350505b261ecSmrg}
350605b261ecSmrg
3507f7df2e56Smrgvoid
3508f7df2e56SmrgInitClient(ClientPtr client, int i, void *ospriv)
350905b261ecSmrg{
351005b261ecSmrg    client->index = i;
35117e31ba66Smrg    xorg_list_init(&client->ready);
35127e31ba66Smrg    xorg_list_init(&client->output_pending);
3513f7df2e56Smrg    client->clientAsMask = ((Mask) i) << CLIENTOFFSET;
35144642e01fSmrg    client->closeDownMode = i ? DestroyAll : RetainPermanent;
351505b261ecSmrg    client->requestVector = InitialVector;
351605b261ecSmrg    client->osPrivate = ospriv;
3517f7df2e56Smrg    QueryMinMaxKeyCodes(&client->minKC, &client->maxKC);
351805b261ecSmrg    client->smart_start_tick = SmartScheduleTime;
351905b261ecSmrg    client->smart_stop_tick = SmartScheduleTime;
3520f7df2e56Smrg    client->clientIds = NULL;
352105b261ecSmrg}
352205b261ecSmrg
352305b261ecSmrg/************************
352405b261ecSmrg * int NextAvailableClient(ospriv)
352505b261ecSmrg *
352605b261ecSmrg * OS dependent portion can't assign client id's because of CloseDownModes.
352705b261ecSmrg * Returns NULL if there are no free clients.
352805b261ecSmrg *************************/
352905b261ecSmrg
3530f7df2e56SmrgClientPtr
3531f7df2e56SmrgNextAvailableClient(void *ospriv)
353205b261ecSmrg{
353305b261ecSmrg    int i;
353405b261ecSmrg    ClientPtr client;
353505b261ecSmrg    xReq data;
353605b261ecSmrg
353705b261ecSmrg    i = nextFreeClientID;
3538f7df2e56Smrg    if (i == LimitClients)
3539f7df2e56Smrg        return (ClientPtr) NULL;
3540f7df2e56Smrg    clients[i] = client =
3541f7df2e56Smrg        dixAllocateObjectWithPrivates(ClientRec, PRIVATE_CLIENT);
354205b261ecSmrg    if (!client)
3543f7df2e56Smrg        return (ClientPtr) NULL;
354405b261ecSmrg    InitClient(client, i, ospriv);
3545f7df2e56Smrg    if (!InitClientResources(client)) {
3546f7df2e56Smrg        dixFreeObjectWithPrivates(client, PRIVATE_CLIENT);
3547f7df2e56Smrg        return (ClientPtr) NULL;
354805b261ecSmrg    }
354905b261ecSmrg    data.reqType = 1;
35506747b715Smrg    data.length = bytes_to_int32(sz_xReq + sz_xConnClientPrefix);
3551f7df2e56Smrg    if (!InsertFakeRequest(client, (char *) &data, sz_xReq)) {
3552f7df2e56Smrg        FreeClientResources(client);
3553f7df2e56Smrg        dixFreeObjectWithPrivates(client, PRIVATE_CLIENT);
3554f7df2e56Smrg        return (ClientPtr) NULL;
355505b261ecSmrg    }
355605b261ecSmrg    if (i == currentMaxClients)
3557f7df2e56Smrg        currentMaxClients++;
3558f7df2e56Smrg    while ((nextFreeClientID < LimitClients) && clients[nextFreeClientID])
3559f7df2e56Smrg        nextFreeClientID++;
3560f7df2e56Smrg
3561f7df2e56Smrg    /* Enable client ID tracking. This must be done before
3562f7df2e56Smrg     * ClientStateCallback. */
3563f7df2e56Smrg    ReserveClientIds(client);
3564f7df2e56Smrg
3565f7df2e56Smrg    if (ClientStateCallback) {
3566f7df2e56Smrg        NewClientInfoRec clientinfo;
356705b261ecSmrg
3568f7df2e56Smrg        clientinfo.client = client;
3569f7df2e56Smrg        clientinfo.prefix = (xConnSetupPrefix *) NULL;
357005b261ecSmrg        clientinfo.setup = (xConnSetup *) NULL;
3571f7df2e56Smrg        CallCallbacks((&ClientStateCallback), (void *) &clientinfo);
3572f7df2e56Smrg    }
35736747b715Smrg    return client;
357405b261ecSmrg}
357505b261ecSmrg
357605b261ecSmrgint
357705b261ecSmrgProcInitialConnection(ClientPtr client)
357805b261ecSmrg{
357905b261ecSmrg    REQUEST(xReq);
358005b261ecSmrg    xConnClientPrefix *prefix;
358105b261ecSmrg    int whichbyte = 1;
3582f7df2e56Smrg    char order;
358305b261ecSmrg
3584f7df2e56Smrg    prefix = (xConnClientPrefix *) ((char *)stuff + sz_xReq);
3585f7df2e56Smrg    order = prefix->byteOrder;
3586f7df2e56Smrg    if (order != 'l' && order != 'B' && order != 'r' && order != 'R')
35876747b715Smrg	return client->noClientException = -1;
3588f7df2e56Smrg    if (((*(char *) &whichbyte) && (order == 'B' || order == 'R')) ||
3589f7df2e56Smrg	(!(*(char *) &whichbyte) && (order == 'l' || order == 'r'))) {
359005b261ecSmrg	client->swapped = TRUE;
359105b261ecSmrg	SwapConnClientPrefix(prefix);
359205b261ecSmrg    }
359305b261ecSmrg    stuff->reqType = 2;
35946747b715Smrg    stuff->length += bytes_to_int32(prefix->nbytesAuthProto) +
3595f7df2e56Smrg        bytes_to_int32(prefix->nbytesAuthString);
3596f7df2e56Smrg    if (client->swapped) {
3597f7df2e56Smrg        swaps(&stuff->length);
3598f7df2e56Smrg    }
3599f7df2e56Smrg    if (order == 'r' || order == 'R') {
3600f7df2e56Smrg	client->local = FALSE;
360105b261ecSmrg    }
360205b261ecSmrg    ResetCurrentRequest(client);
36036747b715Smrg    return Success;
360405b261ecSmrg}
360505b261ecSmrg
36064642e01fSmrgstatic int
3607f7df2e56SmrgSendConnSetup(ClientPtr client, const char *reason)
360805b261ecSmrg{
360905b261ecSmrg    xWindowRoot *root;
361005b261ecSmrg    int i;
361105b261ecSmrg    int numScreens;
3612f7df2e56Smrg    char *lConnectionInfo;
3613f7df2e56Smrg    xConnSetupPrefix *lconnSetupPrefix;
361405b261ecSmrg
3615f7df2e56Smrg    if (reason) {
3616f7df2e56Smrg        xConnSetupPrefix csp;
3617f7df2e56Smrg
3618f7df2e56Smrg        csp.success = xFalse;
3619f7df2e56Smrg        csp.lengthReason = strlen(reason);
3620f7df2e56Smrg        csp.length = bytes_to_int32(csp.lengthReason);
3621f7df2e56Smrg        csp.majorVersion = X_PROTOCOL;
3622f7df2e56Smrg        csp.minorVersion = X_PROTOCOL_REVISION;
3623f7df2e56Smrg        if (client->swapped)
3624f7df2e56Smrg            WriteSConnSetupPrefix(client, &csp);
3625f7df2e56Smrg        else
3626f7df2e56Smrg            WriteToClient(client, sz_xConnSetupPrefix, &csp);
3627f7df2e56Smrg        WriteToClient(client, (int) csp.lengthReason, reason);
3628f7df2e56Smrg        return client->noClientException = -1;
362905b261ecSmrg    }
363005b261ecSmrg
363105b261ecSmrg    numScreens = screenInfo.numScreens;
363205b261ecSmrg    lConnectionInfo = ConnectionInfo;
363305b261ecSmrg    lconnSetupPrefix = &connSetupPrefix;
363405b261ecSmrg
363505b261ecSmrg    /* We're about to start speaking X protocol back to the client by
363605b261ecSmrg     * sending the connection setup info.  This means the authorization
363705b261ecSmrg     * step is complete, and we can count the client as an
363805b261ecSmrg     * authorized one.
363905b261ecSmrg     */
364005b261ecSmrg    nClients++;
364105b261ecSmrg
364205b261ecSmrg    client->requestVector = client->swapped ? SwappedProcVector : ProcVector;
364305b261ecSmrg    client->sequence = 0;
3644f7df2e56Smrg    ((xConnSetup *) lConnectionInfo)->ridBase = client->clientAsMask;
3645f7df2e56Smrg    ((xConnSetup *) lConnectionInfo)->ridMask = RESOURCE_ID_MASK;
364605b261ecSmrg#ifdef MATCH_CLIENT_ENDIAN
3647f7df2e56Smrg    ((xConnSetup *) lConnectionInfo)->imageByteOrder = ClientOrder(client);
3648f7df2e56Smrg    ((xConnSetup *) lConnectionInfo)->bitmapBitOrder = ClientOrder(client);
364905b261ecSmrg#endif
365005b261ecSmrg    /* fill in the "currentInputMask" */
3651f7df2e56Smrg    root = (xWindowRoot *) (lConnectionInfo + connBlockScreenStart);
365205b261ecSmrg#ifdef PANORAMIX
365305b261ecSmrg    if (noPanoramiXExtension)
3654f7df2e56Smrg        numScreens = screenInfo.numScreens;
3655f7df2e56Smrg    else
3656f7df2e56Smrg        numScreens = ((xConnSetup *) ConnectionInfo)->numRoots;
365705b261ecSmrg#endif
365805b261ecSmrg
3659f7df2e56Smrg    for (i = 0; i < numScreens; i++) {
3660f7df2e56Smrg        unsigned int j;
3661f7df2e56Smrg        xDepth *pDepth;
3662f7df2e56Smrg        WindowPtr pRoot = screenInfo.screens[i]->root;
366305b261ecSmrg
36646747b715Smrg        root->currentInputMask = pRoot->eventMask | wOtherEventMasks(pRoot);
3665f7df2e56Smrg        pDepth = (xDepth *) (root + 1);
3666f7df2e56Smrg        for (j = 0; j < root->nDepths; j++) {
3667f7df2e56Smrg            pDepth = (xDepth *) (((char *) (pDepth + 1)) +
3668f7df2e56Smrg                                 pDepth->nVisuals * sizeof(xVisualType));
3669f7df2e56Smrg        }
3670f7df2e56Smrg        root = (xWindowRoot *) pDepth;
367105b261ecSmrg    }
367205b261ecSmrg
3673f7df2e56Smrg    if (client->swapped) {
3674f7df2e56Smrg        WriteSConnSetupPrefix(client, lconnSetupPrefix);
3675f7df2e56Smrg        WriteSConnectionInfo(client,
3676f7df2e56Smrg                             (unsigned long) (lconnSetupPrefix->length << 2),
3677f7df2e56Smrg                             lConnectionInfo);
367805b261ecSmrg    }
3679f7df2e56Smrg    else {
3680f7df2e56Smrg        WriteToClient(client, sizeof(xConnSetupPrefix), lconnSetupPrefix);
3681f7df2e56Smrg        WriteToClient(client, (int) (lconnSetupPrefix->length << 2),
3682f7df2e56Smrg		      lConnectionInfo);
368305b261ecSmrg    }
368405b261ecSmrg    client->clientState = ClientStateRunning;
3685f7df2e56Smrg    if (ClientStateCallback) {
3686f7df2e56Smrg        NewClientInfoRec clientinfo;
368705b261ecSmrg
3688f7df2e56Smrg        clientinfo.client = client;
3689f7df2e56Smrg        clientinfo.prefix = lconnSetupPrefix;
3690f7df2e56Smrg        clientinfo.setup = (xConnSetup *) lConnectionInfo;
3691f7df2e56Smrg        CallCallbacks((&ClientStateCallback), (void *) &clientinfo);
3692f7df2e56Smrg    }
36936747b715Smrg    return Success;
369405b261ecSmrg}
369505b261ecSmrg
369605b261ecSmrgint
369705b261ecSmrgProcEstablishConnection(ClientPtr client)
369805b261ecSmrg{
3699f7df2e56Smrg    const char *reason;
3700f7df2e56Smrg    char *auth_proto, *auth_string;
370105b261ecSmrg    xConnClientPrefix *prefix;
3702f7df2e56Smrg
370305b261ecSmrg    REQUEST(xReq);
370405b261ecSmrg
3705f7df2e56Smrg    prefix = (xConnClientPrefix *) ((char *) stuff + sz_xReq);
3706f7df2e56Smrg    auth_proto = (char *) prefix + sz_xConnClientPrefix;
37076747b715Smrg    auth_string = auth_proto + pad_to_int32(prefix->nbytesAuthProto);
37086e78d31fSmrg
37096e78d31fSmrg    if ((client->req_len << 2) != sz_xReq + sz_xConnClientPrefix +
37106e78d31fSmrg	pad_to_int32(prefix->nbytesAuthProto) +
37116e78d31fSmrg	pad_to_int32(prefix->nbytesAuthString))
37126e78d31fSmrg        reason = "Bad length";
37136e78d31fSmrg    else if ((prefix->majorVersion != X_PROTOCOL) ||
3714f7df2e56Smrg        (prefix->minorVersion != X_PROTOCOL_REVISION))
3715f7df2e56Smrg        reason = "Protocol version mismatch";
371605b261ecSmrg    else
3717f7df2e56Smrg        reason = ClientAuthorized(client,
3718f7df2e56Smrg                                  (unsigned short) prefix->nbytesAuthProto,
3719f7df2e56Smrg                                  auth_proto,
3720f7df2e56Smrg                                  (unsigned short) prefix->nbytesAuthString,
3721f7df2e56Smrg                                  auth_string);
3722f7df2e56Smrg
3723f7df2e56Smrg    return (SendConnSetup(client, reason));
372405b261ecSmrg}
372505b261ecSmrg
37266747b715Smrgvoid
3727f7df2e56SmrgSendErrorToClient(ClientPtr client, unsigned majorCode, unsigned minorCode,
372805b261ecSmrg                  XID resId, int errorCode)
372905b261ecSmrg{
3730f7df2e56Smrg    xError rep = {
3731f7df2e56Smrg        .type = X_Error,
3732f7df2e56Smrg        .errorCode = errorCode,
3733f7df2e56Smrg        .resourceID = resId,
3734f7df2e56Smrg        .minorCode = minorCode,
3735f7df2e56Smrg        .majorCode = majorCode
3736f7df2e56Smrg    };
373705b261ecSmrg
3738f7df2e56Smrg    WriteEventsToClient(client, 1, (xEvent *) &rep);
373905b261ecSmrg}
374005b261ecSmrg
374105b261ecSmrgvoid
374205b261ecSmrgMarkClientException(ClientPtr client)
374305b261ecSmrg{
374405b261ecSmrg    client->noClientException = -1;
374505b261ecSmrg}
37466747b715Smrg
37476747b715Smrg/*
37486747b715Smrg * This array encodes the answer to the question "what is the log base 2
37496747b715Smrg * of the number of pixels that fit in a scanline pad unit?"
37506747b715Smrg * Note that ~0 is an invalid entry (mostly for the benefit of the reader).
37516747b715Smrg */
37526747b715Smrgstatic int answer[6][4] = {
3753f7df2e56Smrg    /* pad   pad   pad     pad */
3754f7df2e56Smrg    /*  8     16    32    64 */
3755f7df2e56Smrg
3756f7df2e56Smrg    {3, 4, 5, 6},               /* 1 bit per pixel */
3757f7df2e56Smrg    {1, 2, 3, 4},               /* 4 bits per pixel */
3758f7df2e56Smrg    {0, 1, 2, 3},               /* 8 bits per pixel */
3759f7df2e56Smrg    {~0, 0, 1, 2},              /* 16 bits per pixel */
3760f7df2e56Smrg    {~0, ~0, 0, 1},             /* 24 bits per pixel */
3761f7df2e56Smrg    {~0, ~0, 0, 1}              /* 32 bits per pixel */
37626747b715Smrg};
37636747b715Smrg
37646747b715Smrg/*
37656747b715Smrg * This array gives the answer to the question "what is the first index for
37666747b715Smrg * the answer array above given the number of bits per pixel?"
37676747b715Smrg * Note that ~0 is an invalid entry (mostly for the benefit of the reader).
37686747b715Smrg */
3769f7df2e56Smrgstatic int indexForBitsPerPixel[33] = {
3770f7df2e56Smrg    ~0, 0, ~0, ~0,              /* 1 bit per pixel */
3771f7df2e56Smrg    1, ~0, ~0, ~0,              /* 4 bits per pixel */
3772f7df2e56Smrg    2, ~0, ~0, ~0,              /* 8 bits per pixel */
3773f7df2e56Smrg    ~0, ~0, ~0, ~0,
3774f7df2e56Smrg    3, ~0, ~0, ~0,              /* 16 bits per pixel */
3775f7df2e56Smrg    ~0, ~0, ~0, ~0,
3776f7df2e56Smrg    4, ~0, ~0, ~0,              /* 24 bits per pixel */
3777f7df2e56Smrg    ~0, ~0, ~0, ~0,
3778f7df2e56Smrg    5                           /* 32 bits per pixel */
37796747b715Smrg};
37806747b715Smrg
37816747b715Smrg/*
37826747b715Smrg * This array gives the bytesperPixel value for cases where the number
37836747b715Smrg * of bits per pixel is a multiple of 8 but not a power of 2.
37846747b715Smrg */
3785f7df2e56Smrgstatic int answerBytesPerPixel[33] = {
3786f7df2e56Smrg    ~0, 0, ~0, ~0,              /* 1 bit per pixel */
3787f7df2e56Smrg    0, ~0, ~0, ~0,              /* 4 bits per pixel */
3788f7df2e56Smrg    0, ~0, ~0, ~0,              /* 8 bits per pixel */
3789f7df2e56Smrg    ~0, ~0, ~0, ~0,
3790f7df2e56Smrg    0, ~0, ~0, ~0,              /* 16 bits per pixel */
3791f7df2e56Smrg    ~0, ~0, ~0, ~0,
3792f7df2e56Smrg    3, ~0, ~0, ~0,              /* 24 bits per pixel */
3793f7df2e56Smrg    ~0, ~0, ~0, ~0,
3794f7df2e56Smrg    0                           /* 32 bits per pixel */
37956747b715Smrg};
37966747b715Smrg
37976747b715Smrg/*
37986747b715Smrg * This array gives the answer to the question "what is the second index for
37996747b715Smrg * the answer array above given the number of bits per scanline pad unit?"
38006747b715Smrg * Note that ~0 is an invalid entry (mostly for the benefit of the reader).
38016747b715Smrg */
3802f7df2e56Smrgstatic int indexForScanlinePad[65] = {
3803f7df2e56Smrg    ~0, ~0, ~0, ~0,
3804f7df2e56Smrg    ~0, ~0, ~0, ~0,
3805f7df2e56Smrg    0, ~0, ~0, ~0,              /* 8 bits per scanline pad unit */
3806f7df2e56Smrg    ~0, ~0, ~0, ~0,
3807f7df2e56Smrg    1, ~0, ~0, ~0,              /* 16 bits per scanline pad unit */
3808f7df2e56Smrg    ~0, ~0, ~0, ~0,
3809f7df2e56Smrg    ~0, ~0, ~0, ~0,
3810f7df2e56Smrg    ~0, ~0, ~0, ~0,
3811f7df2e56Smrg    2, ~0, ~0, ~0,              /* 32 bits per scanline pad unit */
3812f7df2e56Smrg    ~0, ~0, ~0, ~0,
3813f7df2e56Smrg    ~0, ~0, ~0, ~0,
3814f7df2e56Smrg    ~0, ~0, ~0, ~0,
3815f7df2e56Smrg    ~0, ~0, ~0, ~0,
3816f7df2e56Smrg    ~0, ~0, ~0, ~0,
3817f7df2e56Smrg    ~0, ~0, ~0, ~0,
3818f7df2e56Smrg    ~0, ~0, ~0, ~0,
3819f7df2e56Smrg    3                           /* 64 bits per scanline pad unit */
38206747b715Smrg};
38216747b715Smrg
38226747b715Smrg/*
38236747b715Smrg	grow the array of screenRecs if necessary.
38246747b715Smrg	call the device-supplied initialization procedure
38256747b715Smrgwith its screen number, a pointer to its ScreenRec, argc, and argv.
38266747b715Smrg	return the number of successfully installed screens.
38276747b715Smrg
38286747b715Smrg*/
38296747b715Smrg
3830f7df2e56Smrgstatic int init_screen(ScreenPtr pScreen, int i, Bool gpu)
38316747b715Smrg{
38326747b715Smrg    int scanlinepad, format, depth, bitsPerPixel, j, k;
38336747b715Smrg
3834f7df2e56Smrg    dixInitScreenSpecificPrivates(pScreen);
38356747b715Smrg
38366747b715Smrg    if (!dixAllocatePrivates(&pScreen->devPrivates, PRIVATE_SCREEN)) {
3837f7df2e56Smrg        return -1;
38386747b715Smrg    }
38396747b715Smrg    pScreen->myNum = i;
3840f7df2e56Smrg    if (gpu) {
3841f7df2e56Smrg        pScreen->myNum += GPU_SCREEN_OFFSET;
3842f7df2e56Smrg        pScreen->isGPU = TRUE;
3843f7df2e56Smrg    }
3844f7df2e56Smrg    pScreen->totalPixmapSize = 0;       /* computed in CreateScratchPixmapForScreen */
3845f7df2e56Smrg    pScreen->ClipNotify = 0;    /* for R4 ddx compatibility */
38466747b715Smrg    pScreen->CreateScreenResources = 0;
38476747b715Smrg
3848f7df2e56Smrg    xorg_list_init(&pScreen->pixmap_dirty_list);
38497e31ba66Smrg    xorg_list_init(&pScreen->slave_list);
3850f7df2e56Smrg
38516747b715Smrg    /*
38526747b715Smrg     * This loop gets run once for every Screen that gets added,
38536747b715Smrg     * but thats ok.  If the ddx layer initializes the formats
38546747b715Smrg     * one at a time calling AddScreen() after each, then each
38556747b715Smrg     * iteration will make it a little more accurate.  Worst case
38566747b715Smrg     * we do this loop N * numPixmapFormats where N is # of screens.
38576747b715Smrg     * Anyway, this must be called after InitOutput and before the
38586747b715Smrg     * screen init routine is called.
38596747b715Smrg     */
3860f7df2e56Smrg    for (format = 0; format < screenInfo.numPixmapFormats; format++) {
3861f7df2e56Smrg        depth = screenInfo.formats[format].depth;
3862f7df2e56Smrg        bitsPerPixel = screenInfo.formats[format].bitsPerPixel;
3863f7df2e56Smrg        scanlinepad = screenInfo.formats[format].scanlinePad;
3864f7df2e56Smrg        j = indexForBitsPerPixel[bitsPerPixel];
3865f7df2e56Smrg        k = indexForScanlinePad[scanlinepad];
3866f7df2e56Smrg        PixmapWidthPaddingInfo[depth].padPixelsLog2 = answer[j][k];
3867f7df2e56Smrg        PixmapWidthPaddingInfo[depth].padRoundUp =
3868f7df2e56Smrg            (scanlinepad / bitsPerPixel) - 1;
3869f7df2e56Smrg        j = indexForBitsPerPixel[8];    /* bits per byte */
3870f7df2e56Smrg        PixmapWidthPaddingInfo[depth].padBytesLog2 = answer[j][k];
3871f7df2e56Smrg        PixmapWidthPaddingInfo[depth].bitsPerPixel = bitsPerPixel;
3872f7df2e56Smrg        if (answerBytesPerPixel[bitsPerPixel]) {
3873f7df2e56Smrg            PixmapWidthPaddingInfo[depth].notPower2 = 1;
3874f7df2e56Smrg            PixmapWidthPaddingInfo[depth].bytesPerPixel =
3875f7df2e56Smrg                answerBytesPerPixel[bitsPerPixel];
3876f7df2e56Smrg        }
3877f7df2e56Smrg        else {
3878f7df2e56Smrg            PixmapWidthPaddingInfo[depth].notPower2 = 0;
3879f7df2e56Smrg        }
38806747b715Smrg    }
3881f7df2e56Smrg    return 0;
3882f7df2e56Smrg}
3883f7df2e56Smrg
3884f7df2e56Smrgint
3885f7df2e56SmrgAddScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ ,
3886f7df2e56Smrg                           int /*argc */ ,
3887f7df2e56Smrg                           char **      /*argv */
3888f7df2e56Smrg          ), int argc, char **argv)
3889f7df2e56Smrg{
3890f7df2e56Smrg
3891f7df2e56Smrg    int i;
3892f7df2e56Smrg    ScreenPtr pScreen;
3893f7df2e56Smrg    Bool ret;
3894f7df2e56Smrg
3895f7df2e56Smrg    i = screenInfo.numScreens;
3896f7df2e56Smrg    if (i == MAXSCREENS)
3897f7df2e56Smrg        return -1;
3898f7df2e56Smrg
3899f7df2e56Smrg    pScreen = (ScreenPtr) calloc(1, sizeof(ScreenRec));
3900f7df2e56Smrg    if (!pScreen)
3901f7df2e56Smrg        return -1;
39026747b715Smrg
3903f7df2e56Smrg    ret = init_screen(pScreen, i, FALSE);
3904f7df2e56Smrg    if (ret != 0) {
3905f7df2e56Smrg        free(pScreen);
3906f7df2e56Smrg        return ret;
3907f7df2e56Smrg    }
39086747b715Smrg    /* This is where screen specific stuff gets initialized.  Load the
39096747b715Smrg       screen structure, call the hardware, whatever.
39106747b715Smrg       This is also where the default colormap should be allocated and
39116747b715Smrg       also pixel values for blackPixel, whitePixel, and the cursor
39126747b715Smrg       Note that InitScreen is NOT allowed to modify argc, argv, or
39136747b715Smrg       any of the strings pointed to by argv.  They may be passed to
39146747b715Smrg       multiple screens.
3915f7df2e56Smrg     */
39166747b715Smrg    screenInfo.screens[i] = pScreen;
39176747b715Smrg    screenInfo.numScreens++;
3918f7df2e56Smrg    if (!(*pfnInit) (pScreen, argc, argv)) {
3919f7df2e56Smrg        dixFreeScreenSpecificPrivates(pScreen);
3920f7df2e56Smrg        dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN);
3921f7df2e56Smrg        free(pScreen);
3922f7df2e56Smrg        screenInfo.numScreens--;
3923f7df2e56Smrg        return -1;
39246747b715Smrg    }
39256747b715Smrg
3926f7df2e56Smrg    update_desktop_dimensions();
3927f7df2e56Smrg
3928f7df2e56Smrg    dixRegisterScreenPrivateKey(&cursorScreenDevPriv, pScreen, PRIVATE_CURSOR,
3929f7df2e56Smrg                                0);
39306747b715Smrg
39316747b715Smrg    return i;
39326747b715Smrg}
3933f7df2e56Smrg
3934f7df2e56Smrgint
3935f7df2e56SmrgAddGPUScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ ,
3936f7df2e56Smrg                              int /*argc */ ,
3937f7df2e56Smrg                              char **      /*argv */
3938f7df2e56Smrg                              ),
3939f7df2e56Smrg             int argc, char **argv)
3940f7df2e56Smrg{
3941f7df2e56Smrg    int i;
3942f7df2e56Smrg    ScreenPtr pScreen;
3943f7df2e56Smrg    Bool ret;
3944f7df2e56Smrg
3945f7df2e56Smrg    i = screenInfo.numGPUScreens;
3946f7df2e56Smrg    if (i == MAXGPUSCREENS)
3947f7df2e56Smrg        return -1;
3948f7df2e56Smrg
3949f7df2e56Smrg    pScreen = (ScreenPtr) calloc(1, sizeof(ScreenRec));
3950f7df2e56Smrg    if (!pScreen)
3951f7df2e56Smrg        return -1;
3952f7df2e56Smrg
3953f7df2e56Smrg    ret = init_screen(pScreen, i, TRUE);
3954f7df2e56Smrg    if (ret != 0) {
3955f7df2e56Smrg        free(pScreen);
3956f7df2e56Smrg        return ret;
3957f7df2e56Smrg    }
3958f7df2e56Smrg
3959f7df2e56Smrg    /* This is where screen specific stuff gets initialized.  Load the
3960f7df2e56Smrg       screen structure, call the hardware, whatever.
3961f7df2e56Smrg       This is also where the default colormap should be allocated and
3962f7df2e56Smrg       also pixel values for blackPixel, whitePixel, and the cursor
3963f7df2e56Smrg       Note that InitScreen is NOT allowed to modify argc, argv, or
3964f7df2e56Smrg       any of the strings pointed to by argv.  They may be passed to
3965f7df2e56Smrg       multiple screens.
3966f7df2e56Smrg     */
3967f7df2e56Smrg    screenInfo.gpuscreens[i] = pScreen;
3968f7df2e56Smrg    screenInfo.numGPUScreens++;
3969f7df2e56Smrg    if (!(*pfnInit) (pScreen, argc, argv)) {
3970f7df2e56Smrg        dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN);
3971f7df2e56Smrg        free(pScreen);
3972f7df2e56Smrg        screenInfo.numGPUScreens--;
3973f7df2e56Smrg        return -1;
3974f7df2e56Smrg    }
3975f7df2e56Smrg
3976f7df2e56Smrg    update_desktop_dimensions();
3977f7df2e56Smrg
39787e31ba66Smrg    /*
39797e31ba66Smrg     * We cannot register the Screen PRIVATE_CURSOR key if cursors are already
39807e31ba66Smrg     * created, because dix/privates.c does not have relocation code for
39817e31ba66Smrg     * PRIVATE_CURSOR. Once this is fixed the if() can be removed and we can
39827e31ba66Smrg     * register the Screen PRIVATE_CURSOR key unconditionally.
39837e31ba66Smrg     */
39847e31ba66Smrg    if (!dixPrivatesCreated(PRIVATE_CURSOR))
39857e31ba66Smrg        dixRegisterScreenPrivateKey(&cursorScreenDevPriv, pScreen,
39867e31ba66Smrg                                    PRIVATE_CURSOR, 0);
39877e31ba66Smrg
3988f7df2e56Smrg    return i;
3989f7df2e56Smrg}
3990f7df2e56Smrg
3991f7df2e56Smrgvoid
3992f7df2e56SmrgRemoveGPUScreen(ScreenPtr pScreen)
3993f7df2e56Smrg{
3994f7df2e56Smrg    int idx, j;
3995f7df2e56Smrg    if (!pScreen->isGPU)
3996f7df2e56Smrg        return;
3997f7df2e56Smrg
3998f7df2e56Smrg    idx = pScreen->myNum - GPU_SCREEN_OFFSET;
3999f7df2e56Smrg    for (j = idx; j < screenInfo.numGPUScreens - 1; j++) {
4000f7df2e56Smrg        screenInfo.gpuscreens[j] = screenInfo.gpuscreens[j + 1];
4001f7df2e56Smrg        screenInfo.gpuscreens[j]->myNum = j + GPU_SCREEN_OFFSET;
4002f7df2e56Smrg    }
4003f7df2e56Smrg    screenInfo.numGPUScreens--;
4004f7df2e56Smrg
4005f7df2e56Smrg    /* this gets freed later in the resource list, but without
4006f7df2e56Smrg     * the screen existing it causes crashes - so remove it here */
4007f7df2e56Smrg    if (pScreen->defColormap)
4008f7df2e56Smrg        FreeResource(pScreen->defColormap, RT_COLORMAP);
4009f7df2e56Smrg    free(pScreen);
4010f7df2e56Smrg
4011f7df2e56Smrg}
4012f7df2e56Smrg
4013f7df2e56Smrgvoid
4014f7df2e56SmrgAttachUnboundGPU(ScreenPtr pScreen, ScreenPtr new)
4015f7df2e56Smrg{
4016f7df2e56Smrg    assert(new->isGPU);
4017f7df2e56Smrg    assert(!new->current_master);
40187e31ba66Smrg    xorg_list_add(&new->slave_head, &pScreen->slave_list);
4019f7df2e56Smrg    new->current_master = pScreen;
4020f7df2e56Smrg}
4021f7df2e56Smrg
4022f7df2e56Smrgvoid
4023f7df2e56SmrgDetachUnboundGPU(ScreenPtr slave)
4024f7df2e56Smrg{
4025f7df2e56Smrg    assert(slave->isGPU);
40267e31ba66Smrg    assert(!slave->is_output_slave);
40277e31ba66Smrg    assert(!slave->is_offload_slave);
40287e31ba66Smrg    xorg_list_del(&slave->slave_head);
4029f7df2e56Smrg    slave->current_master = NULL;
4030f7df2e56Smrg}
4031f7df2e56Smrg
4032f7df2e56Smrgvoid
4033f7df2e56SmrgAttachOutputGPU(ScreenPtr pScreen, ScreenPtr new)
4034f7df2e56Smrg{
4035f7df2e56Smrg    assert(new->isGPU);
40367e31ba66Smrg    assert(!new->is_output_slave);
40377e31ba66Smrg    assert(new->current_master == pScreen);
40387e31ba66Smrg    new->is_output_slave = TRUE;
40397e31ba66Smrg    new->current_master->output_slaves++;
4040f7df2e56Smrg}
4041f7df2e56Smrg
4042f7df2e56Smrgvoid
4043f7df2e56SmrgDetachOutputGPU(ScreenPtr slave)
4044f7df2e56Smrg{
4045f7df2e56Smrg    assert(slave->isGPU);
40467e31ba66Smrg    assert(slave->is_output_slave);
40477e31ba66Smrg    slave->current_master->output_slaves--;
40487e31ba66Smrg    slave->is_output_slave = FALSE;
4049f7df2e56Smrg}
4050f7df2e56Smrg
4051f7df2e56Smrgvoid
4052f7df2e56SmrgAttachOffloadGPU(ScreenPtr pScreen, ScreenPtr new)
4053f7df2e56Smrg{
4054f7df2e56Smrg    assert(new->isGPU);
40557e31ba66Smrg    assert(!new->is_offload_slave);
40567e31ba66Smrg    assert(new->current_master == pScreen);
40577e31ba66Smrg    new->is_offload_slave = TRUE;
4058f7df2e56Smrg}
4059f7df2e56Smrg
4060f7df2e56Smrgvoid
4061f7df2e56SmrgDetachOffloadGPU(ScreenPtr slave)
4062f7df2e56Smrg{
4063f7df2e56Smrg    assert(slave->isGPU);
40647e31ba66Smrg    assert(slave->is_offload_slave);
40657e31ba66Smrg    slave->is_offload_slave = FALSE;
4066f7df2e56Smrg}
4067f7df2e56Smrg
4068