105b261ecSmrg/***********************************************************
205b261ecSmrg
305b261ecSmrgCopyright 1987, 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 by Digital Equipment Corporation, Maynard, Massachusetts.
2605b261ecSmrg
2705b261ecSmrg                        All Rights Reserved
2805b261ecSmrg
2935c4bbdfSmrgPermission to use, copy, modify, and distribute this software and its
3035c4bbdfSmrgdocumentation for any purpose and without fee is hereby granted,
3105b261ecSmrgprovided that the above copyright notice appear in all copies and that
3235c4bbdfSmrgboth 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
3535c4bbdfSmrgsoftware 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#ifdef HAVE_DIX_CONFIG_H
4805b261ecSmrg#include <dix-config.h>
4905b261ecSmrg#endif
5005b261ecSmrg
5105b261ecSmrg#include <X11/X.h>
5205b261ecSmrg#include <X11/Xmd.h>
5305b261ecSmrg#include "servermd.h"
5405b261ecSmrg#include "scrnintstr.h"
5505b261ecSmrg#include "dixstruct.h"
5605b261ecSmrg#include "cursorstr.h"
5705b261ecSmrg#include "dixfontstr.h"
5805b261ecSmrg#include "opaque.h"
594642e01fSmrg#include "inputstr.h"
604642e01fSmrg#include "xace.h"
6105b261ecSmrg
6205b261ecSmrgtypedef struct _GlyphShare {
6305b261ecSmrg    FontPtr font;
6405b261ecSmrg    unsigned short sourceChar;
6505b261ecSmrg    unsigned short maskChar;
6605b261ecSmrg    CursorBitsPtr bits;
6705b261ecSmrg    struct _GlyphShare *next;
6805b261ecSmrg} GlyphShare, *GlyphSharePtr;
6905b261ecSmrg
7035c4bbdfSmrgstatic GlyphSharePtr sharedGlyphs = (GlyphSharePtr) NULL;
7105b261ecSmrg
7235c4bbdfSmrgDevScreenPrivateKeyRec cursorScreenDevPriv;
736747b715Smrg
7435c4bbdfSmrgstatic CARD32 cursorSerial;
7505b261ecSmrg
7605b261ecSmrgstatic void
7705b261ecSmrgFreeCursorBits(CursorBitsPtr bits)
7805b261ecSmrg{
7905b261ecSmrg    if (--bits->refcnt > 0)
8035c4bbdfSmrg        return;
816747b715Smrg    free(bits->source);
826747b715Smrg    free(bits->mask);
836747b715Smrg    free(bits->argb);
846747b715Smrg    dixFiniPrivates(bits, PRIVATE_CURSOR_BITS);
8535c4bbdfSmrg    if (bits->refcnt == 0) {
8635c4bbdfSmrg        GlyphSharePtr *prev, this;
8735c4bbdfSmrg
8835c4bbdfSmrg        for (prev = &sharedGlyphs;
8935c4bbdfSmrg             (this = *prev) && (this->bits != bits); prev = &this->next);
9035c4bbdfSmrg        if (this) {
9135c4bbdfSmrg            *prev = this->next;
9235c4bbdfSmrg            CloseFont(this->font, (Font) 0);
9335c4bbdfSmrg            free(this);
9435c4bbdfSmrg        }
9535c4bbdfSmrg        free(bits);
9605b261ecSmrg    }
9705b261ecSmrg}
9805b261ecSmrg
9905b261ecSmrg/**
10005b261ecSmrg * To be called indirectly by DeleteResource; must use exactly two args.
10105b261ecSmrg *
10205b261ecSmrg *  \param value must conform to DeleteType
10305b261ecSmrg */
1046747b715Smrgint
10535c4bbdfSmrgFreeCursor(void *value, XID cid)
10605b261ecSmrg{
10735c4bbdfSmrg    int nscr;
10835c4bbdfSmrg    CursorPtr pCurs = (CursorPtr) value;
10935c4bbdfSmrg
11035c4bbdfSmrg    ScreenPtr pscr;
11135c4bbdfSmrg    DeviceIntPtr pDev = NULL;   /* unused anyway */
11205b261ecSmrg
11305b261ecSmrg
11435c4bbdfSmrg    UnrefCursor(pCurs);
11535c4bbdfSmrg    if (CursorRefCount(pCurs) != 0)
11635c4bbdfSmrg        return Success;
11705b261ecSmrg
11835c4bbdfSmrg    BUG_WARN(CursorRefCount(pCurs) < 0);
11935c4bbdfSmrg
12035c4bbdfSmrg    for (nscr = 0; nscr < screenInfo.numScreens; nscr++) {
12135c4bbdfSmrg        pscr = screenInfo.screens[nscr];
12235c4bbdfSmrg        (void) (*pscr->UnrealizeCursor) (pDev, pscr, pCurs);
12305b261ecSmrg    }
12405b261ecSmrg    FreeCursorBits(pCurs->bits);
1256747b715Smrg    dixFiniPrivates(pCurs, PRIVATE_CURSOR);
12635c4bbdfSmrg    free(pCurs);
1276747b715Smrg    return Success;
12805b261ecSmrg}
12905b261ecSmrg
13035c4bbdfSmrgCursorPtr
13135c4bbdfSmrgRefCursor(CursorPtr cursor)
13235c4bbdfSmrg{
13335c4bbdfSmrg    if (cursor)
13435c4bbdfSmrg        cursor->refcnt++;
13535c4bbdfSmrg    return cursor;
13635c4bbdfSmrg}
13735c4bbdfSmrg
13835c4bbdfSmrgCursorPtr
13935c4bbdfSmrgUnrefCursor(CursorPtr cursor)
14035c4bbdfSmrg{
14135c4bbdfSmrg    if (cursor)
14235c4bbdfSmrg        cursor->refcnt--;
14335c4bbdfSmrg    return cursor;
14435c4bbdfSmrg}
14535c4bbdfSmrg
14635c4bbdfSmrgint
14735c4bbdfSmrgCursorRefCount(const CursorPtr cursor)
14835c4bbdfSmrg{
14935c4bbdfSmrg    return cursor ? cursor->refcnt : 0;
15035c4bbdfSmrg}
15135c4bbdfSmrg
15205b261ecSmrg
15305b261ecSmrg/*
15405b261ecSmrg * We check for empty cursors so that we won't have to display them
15505b261ecSmrg */
15605b261ecSmrgstatic void
15705b261ecSmrgCheckForEmptyMask(CursorBitsPtr bits)
15805b261ecSmrg{
15905b261ecSmrg    unsigned char *msk = bits->mask;
16005b261ecSmrg    int n = BitmapBytePad(bits->width) * bits->height;
16105b261ecSmrg
16205b261ecSmrg    bits->emptyMask = FALSE;
16335c4bbdfSmrg    while (n--)
16435c4bbdfSmrg        if (*(msk++) != 0)
16535c4bbdfSmrg            return;
16635c4bbdfSmrg    if (bits->argb) {
16735c4bbdfSmrg        CARD32 *argb = bits->argb;
16835c4bbdfSmrg
16935c4bbdfSmrg        n = bits->width * bits->height;
17035c4bbdfSmrg        while (n--)
17135c4bbdfSmrg            if (*argb++ & 0xff000000)
17235c4bbdfSmrg                return;
17305b261ecSmrg    }
17405b261ecSmrg    bits->emptyMask = TRUE;
17505b261ecSmrg}
17605b261ecSmrg
1776747b715Smrg/**
1786747b715Smrg * realize the cursor for every screen. Do not change the refcnt, this will be
1796747b715Smrg * changed when ChangeToCursor actually changes the sprite.
1806747b715Smrg *
1816747b715Smrg * @return Success if all cursors realize on all screens, BadAlloc if realize
1826747b715Smrg * failed for a device on a given screen.
1836747b715Smrg */
1846747b715Smrgstatic int
1856747b715SmrgRealizeCursorAllScreens(CursorPtr pCurs)
1866747b715Smrg{
1876747b715Smrg    DeviceIntPtr pDev;
18835c4bbdfSmrg    ScreenPtr pscr;
1896747b715Smrg    int nscr;
1906747b715Smrg
19135c4bbdfSmrg    for (nscr = 0; nscr < screenInfo.numScreens; nscr++) {
1926747b715Smrg        pscr = screenInfo.screens[nscr];
19335c4bbdfSmrg        for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
19435c4bbdfSmrg            if (DevHasCursor(pDev)) {
19535c4bbdfSmrg                if (!(*pscr->RealizeCursor) (pDev, pscr, pCurs)) {
1966747b715Smrg                    /* Realize failed for device pDev on screen pscr.
1976747b715Smrg                     * We have to assume that for all devices before, realize
1986747b715Smrg                     * worked. We need to rollback all devices so far on the
1996747b715Smrg                     * current screen and then all devices on previous
2006747b715Smrg                     * screens.
2016747b715Smrg                     */
20235c4bbdfSmrg                    DeviceIntPtr pDevIt = inputInfo.devices;    /*dev iterator */
20335c4bbdfSmrg
20435c4bbdfSmrg                    while (pDevIt && pDevIt != pDev) {
2056747b715Smrg                        if (DevHasCursor(pDevIt))
20635c4bbdfSmrg                            (*pscr->UnrealizeCursor) (pDevIt, pscr, pCurs);
2076747b715Smrg                        pDevIt = pDevIt->next;
2086747b715Smrg                    }
20935c4bbdfSmrg                    while (--nscr >= 0) {
2106747b715Smrg                        pscr = screenInfo.screens[nscr];
2116747b715Smrg                        /* now unrealize all devices on previous screens */
2126747b715Smrg                        pDevIt = inputInfo.devices;
21335c4bbdfSmrg                        while (pDevIt) {
2146747b715Smrg                            if (DevHasCursor(pDevIt))
21535c4bbdfSmrg                                (*pscr->UnrealizeCursor) (pDevIt, pscr, pCurs);
2166747b715Smrg                            pDevIt = pDevIt->next;
2176747b715Smrg                        }
21835c4bbdfSmrg                        (*pscr->UnrealizeCursor) (pDev, pscr, pCurs);
2196747b715Smrg                    }
2206747b715Smrg                    return BadAlloc;
2216747b715Smrg                }
2226747b715Smrg            }
2236747b715Smrg        }
2246747b715Smrg    }
2256747b715Smrg
2266747b715Smrg    return Success;
2276747b715Smrg}
2286747b715Smrg
22905b261ecSmrg/**
23005b261ecSmrg * does nothing about the resource table, just creates the data structure.
23105b261ecSmrg * does not copy the src and mask bits
23205b261ecSmrg *
23305b261ecSmrg *  \param psrcbits  server-defined padding
23405b261ecSmrg *  \param pmaskbits server-defined padding
23505b261ecSmrg *  \param argb      no padding
23605b261ecSmrg */
2374642e01fSmrgint
2384642e01fSmrgAllocARGBCursor(unsigned char *psrcbits, unsigned char *pmaskbits,
23935c4bbdfSmrg                CARD32 *argb, CursorMetricPtr cm,
24035c4bbdfSmrg                unsigned foreRed, unsigned foreGreen, unsigned foreBlue,
24135c4bbdfSmrg                unsigned backRed, unsigned backGreen, unsigned backBlue,
24235c4bbdfSmrg                CursorPtr *ppCurs, ClientPtr client, XID cid)
24305b261ecSmrg{
24435c4bbdfSmrg    CursorBitsPtr bits;
24535c4bbdfSmrg    CursorPtr pCurs;
2466747b715Smrg    int rc;
24705b261ecSmrg
2484642e01fSmrg    *ppCurs = NULL;
24935c4bbdfSmrg    pCurs = (CursorPtr) calloc(CURSOR_REC_SIZE + CURSOR_BITS_SIZE, 1);
25005b261ecSmrg    if (!pCurs)
25135c4bbdfSmrg        return BadAlloc;
25235c4bbdfSmrg
25335c4bbdfSmrg    bits = (CursorBitsPtr) ((char *) pCurs + CURSOR_REC_SIZE);
2546747b715Smrg    dixInitPrivates(pCurs, pCurs + 1, PRIVATE_CURSOR);
2556747b715Smrg    dixInitPrivates(bits, bits + 1, PRIVATE_CURSOR_BITS)
25635c4bbdfSmrg        bits->source = psrcbits;
25705b261ecSmrg    bits->mask = pmaskbits;
25805b261ecSmrg    bits->argb = argb;
25905b261ecSmrg    bits->width = cm->width;
26005b261ecSmrg    bits->height = cm->height;
26105b261ecSmrg    bits->xhot = cm->xhot;
26205b261ecSmrg    bits->yhot = cm->yhot;
26335c4bbdfSmrg    pCurs->refcnt = 1;
26405b261ecSmrg    bits->refcnt = -1;
26505b261ecSmrg    CheckForEmptyMask(bits);
26605b261ecSmrg    pCurs->bits = bits;
26705b261ecSmrg    pCurs->serialNumber = ++cursorSerial;
26805b261ecSmrg    pCurs->name = None;
26905b261ecSmrg
27005b261ecSmrg    pCurs->foreRed = foreRed;
27105b261ecSmrg    pCurs->foreGreen = foreGreen;
27205b261ecSmrg    pCurs->foreBlue = foreBlue;
27305b261ecSmrg
27405b261ecSmrg    pCurs->backRed = backRed;
27505b261ecSmrg    pCurs->backGreen = backGreen;
27605b261ecSmrg    pCurs->backBlue = backBlue;
27705b261ecSmrg
2784642e01fSmrg    pCurs->id = cid;
2794642e01fSmrg
2804642e01fSmrg    /* security creation/labeling check */
2814642e01fSmrg    rc = XaceHook(XACE_RESOURCE_ACCESS, client, cid, RT_CURSOR,
28235c4bbdfSmrg                  pCurs, RT_NONE, NULL, DixCreateAccess);
2836747b715Smrg    if (rc != Success)
2846747b715Smrg        goto error;
2856747b715Smrg
2866747b715Smrg    rc = RealizeCursorAllScreens(pCurs);
2876747b715Smrg    if (rc != Success)
2886747b715Smrg        goto error;
2896747b715Smrg
2904642e01fSmrg    *ppCurs = pCurs;
29135c4bbdfSmrg
29235c4bbdfSmrg    if (argb) {
29335c4bbdfSmrg        size_t i, size = bits->width * bits->height;
29435c4bbdfSmrg
29535c4bbdfSmrg        for (i = 0; i < size; i++) {
29635c4bbdfSmrg            if ((argb[i] & 0xff000000) == 0 && (argb[i] & 0xffffff) != 0) {
29735c4bbdfSmrg                /* ARGB data doesn't seem pre-multiplied, fix it */
29835c4bbdfSmrg                for (i = 0; i < size; i++) {
29935c4bbdfSmrg                    CARD32 a, ar, ag, ab;
30035c4bbdfSmrg
30135c4bbdfSmrg                    a = argb[i] >> 24;
30235c4bbdfSmrg                    ar = a * ((argb[i] >> 16) & 0xff) / 0xff;
30335c4bbdfSmrg                    ag = a * ((argb[i] >> 8) & 0xff) / 0xff;
30435c4bbdfSmrg                    ab = a * (argb[i] & 0xff) / 0xff;
30535c4bbdfSmrg
30635c4bbdfSmrg                    argb[i] = a << 24 | ar << 16 | ag << 8 | ab;
30735c4bbdfSmrg                }
30835c4bbdfSmrg
30935c4bbdfSmrg                break;
31035c4bbdfSmrg            }
31135c4bbdfSmrg        }
31235c4bbdfSmrg    }
31335c4bbdfSmrg
3146747b715Smrg    return Success;
3156747b715Smrg
31635c4bbdfSmrg error:
3176747b715Smrg    FreeCursorBits(bits);
3186747b715Smrg    dixFiniPrivates(pCurs, PRIVATE_CURSOR);
3196747b715Smrg    free(pCurs);
3206747b715Smrg
3214642e01fSmrg    return rc;
32205b261ecSmrg}
32305b261ecSmrg
32405b261ecSmrgint
32505b261ecSmrgAllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
32635c4bbdfSmrg                 unsigned foreRed, unsigned foreGreen, unsigned foreBlue,
32735c4bbdfSmrg                 unsigned backRed, unsigned backGreen, unsigned backBlue,
32835c4bbdfSmrg                 CursorPtr *ppCurs, ClientPtr client, XID cid)
32905b261ecSmrg{
33035c4bbdfSmrg    FontPtr sourcefont, maskfont;
33135c4bbdfSmrg    unsigned char *srcbits;
33235c4bbdfSmrg    unsigned char *mskbits;
33305b261ecSmrg    CursorMetricRec cm;
3344642e01fSmrg    int rc;
33535c4bbdfSmrg    CursorBitsPtr bits;
33635c4bbdfSmrg    CursorPtr pCurs;
33705b261ecSmrg    GlyphSharePtr pShare;
33805b261ecSmrg
33935c4bbdfSmrg    rc = dixLookupResourceByType((void **) &sourcefont, source, RT_FONT,
34035c4bbdfSmrg                                 client, DixUseAccess);
34135c4bbdfSmrg    if (rc != Success) {
34235c4bbdfSmrg        client->errorValue = source;
34335c4bbdfSmrg        return rc;
34405b261ecSmrg    }
34535c4bbdfSmrg    rc = dixLookupResourceByType((void **) &maskfont, mask, RT_FONT, client,
34635c4bbdfSmrg                                 DixUseAccess);
34735c4bbdfSmrg    if (rc != Success && mask != None) {
34835c4bbdfSmrg        client->errorValue = mask;
34935c4bbdfSmrg        return rc;
35005b261ecSmrg    }
35105b261ecSmrg    if (sourcefont != maskfont)
35235c4bbdfSmrg        pShare = (GlyphSharePtr) NULL;
35335c4bbdfSmrg    else {
35435c4bbdfSmrg        for (pShare = sharedGlyphs;
35535c4bbdfSmrg             pShare &&
35635c4bbdfSmrg             ((pShare->font != sourcefont) ||
35735c4bbdfSmrg              (pShare->sourceChar != sourceChar) ||
35835c4bbdfSmrg              (pShare->maskChar != maskChar)); pShare = pShare->next);
35905b261ecSmrg    }
36035c4bbdfSmrg    if (pShare) {
36135c4bbdfSmrg        pCurs = (CursorPtr) calloc(CURSOR_REC_SIZE, 1);
36235c4bbdfSmrg        if (!pCurs)
36335c4bbdfSmrg            return BadAlloc;
36435c4bbdfSmrg        dixInitPrivates(pCurs, pCurs + 1, PRIVATE_CURSOR);
36535c4bbdfSmrg        bits = pShare->bits;
36635c4bbdfSmrg        bits->refcnt++;
36705b261ecSmrg    }
36835c4bbdfSmrg    else {
36935c4bbdfSmrg        if (!CursorMetricsFromGlyph(sourcefont, sourceChar, &cm)) {
37035c4bbdfSmrg            client->errorValue = sourceChar;
37135c4bbdfSmrg            return BadValue;
37235c4bbdfSmrg        }
37335c4bbdfSmrg        if (!maskfont) {
37435c4bbdfSmrg            long n;
37535c4bbdfSmrg            unsigned char *mskptr;
37635c4bbdfSmrg
37735c4bbdfSmrg            n = BitmapBytePad(cm.width) * (long) cm.height;
37835c4bbdfSmrg            mskptr = mskbits = malloc(n);
37935c4bbdfSmrg            if (!mskptr)
38035c4bbdfSmrg                return BadAlloc;
38135c4bbdfSmrg            while (--n >= 0)
38235c4bbdfSmrg                *mskptr++ = ~0;
38335c4bbdfSmrg        }
38435c4bbdfSmrg        else {
38535c4bbdfSmrg            if (!CursorMetricsFromGlyph(maskfont, maskChar, &cm)) {
38635c4bbdfSmrg                client->errorValue = maskChar;
38735c4bbdfSmrg                return BadValue;
38835c4bbdfSmrg            }
38935c4bbdfSmrg            if ((rc = ServerBitsFromGlyph(maskfont, maskChar, &cm, &mskbits)))
39035c4bbdfSmrg                return rc;
39135c4bbdfSmrg        }
39235c4bbdfSmrg        if ((rc = ServerBitsFromGlyph(sourcefont, sourceChar, &cm, &srcbits))) {
39335c4bbdfSmrg            free(mskbits);
39435c4bbdfSmrg            return rc;
39535c4bbdfSmrg        }
39635c4bbdfSmrg        if (sourcefont != maskfont) {
39735c4bbdfSmrg            pCurs = (CursorPtr) calloc(CURSOR_REC_SIZE + CURSOR_BITS_SIZE, 1);
39835c4bbdfSmrg            if (pCurs)
39935c4bbdfSmrg                bits = (CursorBitsPtr) ((char *) pCurs + CURSOR_REC_SIZE);
40035c4bbdfSmrg            else
40135c4bbdfSmrg                bits = (CursorBitsPtr) NULL;
40235c4bbdfSmrg        }
40335c4bbdfSmrg        else {
40435c4bbdfSmrg            pCurs = (CursorPtr) calloc(CURSOR_REC_SIZE, 1);
40535c4bbdfSmrg            if (pCurs)
40635c4bbdfSmrg                bits = (CursorBitsPtr) calloc(CURSOR_BITS_SIZE, 1);
40735c4bbdfSmrg            else
40835c4bbdfSmrg                bits = (CursorBitsPtr) NULL;
40935c4bbdfSmrg        }
41035c4bbdfSmrg        if (!bits) {
41135c4bbdfSmrg            free(pCurs);
41235c4bbdfSmrg            free(mskbits);
41335c4bbdfSmrg            free(srcbits);
41435c4bbdfSmrg            return BadAlloc;
41535c4bbdfSmrg        }
41635c4bbdfSmrg        dixInitPrivates(pCurs, pCurs + 1, PRIVATE_CURSOR);
41735c4bbdfSmrg        dixInitPrivates(bits, bits + 1, PRIVATE_CURSOR_BITS);
41835c4bbdfSmrg        bits->source = srcbits;
41935c4bbdfSmrg        bits->mask = mskbits;
42035c4bbdfSmrg        bits->argb = 0;
42135c4bbdfSmrg        bits->width = cm.width;
42235c4bbdfSmrg        bits->height = cm.height;
42335c4bbdfSmrg        bits->xhot = cm.xhot;
42435c4bbdfSmrg        bits->yhot = cm.yhot;
42535c4bbdfSmrg        if (sourcefont != maskfont)
42635c4bbdfSmrg            bits->refcnt = -1;
42735c4bbdfSmrg        else {
42835c4bbdfSmrg            bits->refcnt = 1;
42935c4bbdfSmrg            pShare = malloc(sizeof(GlyphShare));
43035c4bbdfSmrg            if (!pShare) {
43135c4bbdfSmrg                FreeCursorBits(bits);
43235c4bbdfSmrg                return BadAlloc;
43335c4bbdfSmrg            }
43435c4bbdfSmrg            pShare->font = sourcefont;
43535c4bbdfSmrg            sourcefont->refcnt++;
43635c4bbdfSmrg            pShare->sourceChar = sourceChar;
43735c4bbdfSmrg            pShare->maskChar = maskChar;
43835c4bbdfSmrg            pShare->bits = bits;
43935c4bbdfSmrg            pShare->next = sharedGlyphs;
44035c4bbdfSmrg            sharedGlyphs = pShare;
44135c4bbdfSmrg        }
44205b261ecSmrg    }
4434642e01fSmrg
44405b261ecSmrg    CheckForEmptyMask(bits);
44505b261ecSmrg    pCurs->bits = bits;
44605b261ecSmrg    pCurs->refcnt = 1;
44705b261ecSmrg    pCurs->serialNumber = ++cursorSerial;
44805b261ecSmrg    pCurs->name = None;
44905b261ecSmrg
45005b261ecSmrg    pCurs->foreRed = foreRed;
45105b261ecSmrg    pCurs->foreGreen = foreGreen;
45205b261ecSmrg    pCurs->foreBlue = foreBlue;
45305b261ecSmrg
45405b261ecSmrg    pCurs->backRed = backRed;
45505b261ecSmrg    pCurs->backGreen = backGreen;
45605b261ecSmrg    pCurs->backBlue = backBlue;
45705b261ecSmrg
4584642e01fSmrg    pCurs->id = cid;
4594642e01fSmrg
4604642e01fSmrg    /* security creation/labeling check */
4614642e01fSmrg    rc = XaceHook(XACE_RESOURCE_ACCESS, client, cid, RT_CURSOR,
46235c4bbdfSmrg                  pCurs, RT_NONE, NULL, DixCreateAccess);
4636747b715Smrg    if (rc != Success)
4646747b715Smrg        goto error;
4654642e01fSmrg
4666747b715Smrg    rc = RealizeCursorAllScreens(pCurs);
4676747b715Smrg    if (rc != Success)
4686747b715Smrg        goto error;
4694642e01fSmrg
47005b261ecSmrg    *ppCurs = pCurs;
47105b261ecSmrg    return Success;
4726747b715Smrg
47335c4bbdfSmrg error:
4746747b715Smrg    FreeCursorBits(bits);
4756747b715Smrg    dixFiniPrivates(pCurs, PRIVATE_CURSOR);
4766747b715Smrg    free(pCurs);
4776747b715Smrg
4786747b715Smrg    return rc;
47905b261ecSmrg}
48005b261ecSmrg
48105b261ecSmrg/** CreateRootCursor
48205b261ecSmrg *
48305b261ecSmrg * look up the name of a font
48405b261ecSmrg * open the font
48505b261ecSmrg * add the font to the resource table
48605b261ecSmrg * make a cursor from the glyphs
48705b261ecSmrg * add the cursor to the resource table
48805b261ecSmrg *************************************************************/
48905b261ecSmrg
4906747b715SmrgCursorPtr
49105b261ecSmrgCreateRootCursor(char *unused1, unsigned int unused2)
49205b261ecSmrg{
49335c4bbdfSmrg    CursorPtr curs;
49435c4bbdfSmrg    FontPtr cursorfont;
49535c4bbdfSmrg    int err;
49635c4bbdfSmrg    XID fontID;
497ed6184dfSmrg    const char defaultCursorFont[] = "cursor";
49805b261ecSmrg
49905b261ecSmrg    fontID = FakeClientID(0);
50005b261ecSmrg    err = OpenFont(serverClient, fontID, FontLoadAll | FontOpenSync,
50135c4bbdfSmrg                   (unsigned) strlen(defaultCursorFont), defaultCursorFont);
50205b261ecSmrg    if (err != Success)
50335c4bbdfSmrg        return NullCursor;
50405b261ecSmrg
50535c4bbdfSmrg    err = dixLookupResourceByType((void **) &cursorfont, fontID, RT_FONT,
50635c4bbdfSmrg                                  serverClient, DixReadAccess);
5076747b715Smrg    if (err != Success)
50835c4bbdfSmrg        return NullCursor;
5094642e01fSmrg    if (AllocGlyphCursor(fontID, 0, fontID, 1, 0, 0, 0, ~0, ~0, ~0,
51035c4bbdfSmrg                         &curs, serverClient, (XID) 0) != Success)
51135c4bbdfSmrg        return NullCursor;
51205b261ecSmrg
51335c4bbdfSmrg    if (!AddResource(FakeClientID(0), RT_CURSOR, (void *) curs))
51435c4bbdfSmrg        return NullCursor;
51505b261ecSmrg
51605b261ecSmrg    return curs;
51705b261ecSmrg}
518