gc.c revision 4642e01f
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
2505b261ecSmrg
2605b261ecSmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
2705b261ecSmrg
2805b261ecSmrg                        All Rights Reserved
2905b261ecSmrg
3005b261ecSmrgPermission to use, copy, modify, and distribute this software and its
3105b261ecSmrgdocumentation for any purpose and without fee is hereby granted,
3205b261ecSmrgprovided that the above copyright notice appear in all copies and that
3305b261ecSmrgboth that copyright notice and this permission notice appear in
3405b261ecSmrgsupporting documentation, and that the name of Digital not be
3505b261ecSmrgused in advertising or publicity pertaining to distribution of the
3605b261ecSmrgsoftware without specific, written prior permission.
3705b261ecSmrg
3805b261ecSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
3905b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
4005b261ecSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
4105b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
4205b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
4305b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
4405b261ecSmrgSOFTWARE.
4505b261ecSmrg
4605b261ecSmrg******************************************************************/
4705b261ecSmrg
4805b261ecSmrg
4905b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
5005b261ecSmrg#include <dix-config.h>
5105b261ecSmrg#endif
5205b261ecSmrg
5305b261ecSmrg#include <X11/X.h>
5405b261ecSmrg#include <X11/Xmd.h>
5505b261ecSmrg#include <X11/Xproto.h>
5605b261ecSmrg#include "misc.h"
5705b261ecSmrg#include "resource.h"
5805b261ecSmrg#include "gcstruct.h"
5905b261ecSmrg#include "pixmapstr.h"
6005b261ecSmrg#include "dixfontstr.h"
6105b261ecSmrg#include "scrnintstr.h"
6205b261ecSmrg#include "region.h"
6305b261ecSmrg
644642e01fSmrg#include "privates.h"
6505b261ecSmrg#include "dix.h"
664642e01fSmrg#include "xace.h"
6705b261ecSmrg#include <assert.h>
6805b261ecSmrg
6905b261ecSmrgextern XID clientErrorValue;
7005b261ecSmrgextern FontPtr defaultFont;
7105b261ecSmrg
7205b261ecSmrgstatic Bool CreateDefaultTile(GCPtr pGC);
7305b261ecSmrg
7405b261ecSmrgstatic unsigned char DefaultDash[2] = {4, 4};
7505b261ecSmrg
7605b261ecSmrg_X_EXPORT void
7705b261ecSmrgValidateGC(DrawablePtr pDraw, GC *pGC)
7805b261ecSmrg{
7905b261ecSmrg    (*pGC->funcs->ValidateGC) (pGC, pGC->stateChanges, pDraw);
8005b261ecSmrg    pGC->stateChanges = 0;
8105b261ecSmrg    pGC->serialNumber = pDraw->serialNumber;
8205b261ecSmrg}
8305b261ecSmrg
8405b261ecSmrg
8505b261ecSmrg/* dixChangeGC(client, pGC, mask, pC32, pUnion)
8605b261ecSmrg *
8705b261ecSmrg * This function was created as part of the Security extension
8805b261ecSmrg * implementation.  The client performing the gc change must be passed so
8905b261ecSmrg * that access checks can be performed on any tiles, stipples, or fonts
9005b261ecSmrg * that are specified.  ddxen can call this too; they should normally
9105b261ecSmrg * pass NullClient for the client since any access checking should have
9205b261ecSmrg * already been done at a higher level.
9305b261ecSmrg *
9405b261ecSmrg * Since we had to create a new function anyway, we decided to change the
9505b261ecSmrg * way the list of gc values is passed to eliminate the compiler warnings
9605b261ecSmrg * caused by the DoChangeGC interface.  You can pass the values via pC32
9705b261ecSmrg * or pUnion, but not both; one of them must be NULL.  If you don't need
9805b261ecSmrg * to pass any pointers, you can use either one:
9905b261ecSmrg *
10005b261ecSmrg *     example calling dixChangeGC using pC32 parameter
10105b261ecSmrg *
10205b261ecSmrg *     CARD32 v[2];
10305b261ecSmrg *     v[0] = foreground;
10405b261ecSmrg *     v[1] = background;
10505b261ecSmrg *     dixChangeGC(client, pGC, GCForeground|GCBackground, v, NULL);
10605b261ecSmrg *
10705b261ecSmrg *     example calling dixChangeGC using pUnion parameter;
10805b261ecSmrg *     same effect as above
10905b261ecSmrg *
11005b261ecSmrg *     ChangeGCVal v[2];
11105b261ecSmrg *     v[0].val = foreground;
11205b261ecSmrg *     v[1].val = background;
11305b261ecSmrg *     dixChangeGC(client, pGC, GCForeground|GCBackground, NULL, v);
11405b261ecSmrg *
11505b261ecSmrg * However, if you need to pass a pointer to a pixmap or font, you MUST
11605b261ecSmrg * use the pUnion parameter.
11705b261ecSmrg *
11805b261ecSmrg *     example calling dixChangeGC passing pointers in the value list
11905b261ecSmrg *     v[1].ptr is a pointer to a pixmap
12005b261ecSmrg *
12105b261ecSmrg *     ChangeGCVal v[2];
12205b261ecSmrg *     v[0].val = FillTiled;
12305b261ecSmrg *     v[1].ptr = pPixmap;
12405b261ecSmrg *     dixChangeGC(client, pGC, GCFillStyle|GCTile, NULL, v);
12505b261ecSmrg *
12605b261ecSmrg * Note: we could have gotten by with just the pUnion parameter, but on
12705b261ecSmrg * 64 bit machines that would have forced us to copy the value list that
12805b261ecSmrg * comes in the ChangeGC request.
12905b261ecSmrg *
13005b261ecSmrg * Ideally, we'd change all the DoChangeGC calls to dixChangeGC, but this
13105b261ecSmrg * is far too many changes to consider at this time, so we've only
13205b261ecSmrg * changed the ones that caused compiler warnings.  New code should use
13305b261ecSmrg * dixChangeGC.
13405b261ecSmrg *
13505b261ecSmrg * dpw
13605b261ecSmrg */
13705b261ecSmrg
13805b261ecSmrg#define NEXTVAL(_type, _var) { \
13905b261ecSmrg      if (pC32) _var = (_type)*pC32++; \
14005b261ecSmrg      else { \
14105b261ecSmrg	_var = (_type)(pUnion->val); pUnion++; \
14205b261ecSmrg      } \
14305b261ecSmrg    }
14405b261ecSmrg
14505b261ecSmrg#define NEXT_PTR(_type, _var) { \
14605b261ecSmrg    assert(pUnion); _var = (_type)pUnion->ptr; pUnion++; }
14705b261ecSmrg
14805b261ecSmrg_X_EXPORT int
14905b261ecSmrgdixChangeGC(ClientPtr client, GC *pGC, BITS32 mask, CARD32 *pC32, ChangeGCValPtr pUnion)
15005b261ecSmrg{
15105b261ecSmrg    BITS32 	index2;
1524642e01fSmrg    int 	rc, error = 0;
15305b261ecSmrg    PixmapPtr 	pPixmap;
15405b261ecSmrg    BITS32	maskQ;
15505b261ecSmrg
15605b261ecSmrg    assert( (pC32 && !pUnion) || (!pC32 && pUnion) );
15705b261ecSmrg    pGC->serialNumber |= GC_CHANGE_SERIAL_BIT;
15805b261ecSmrg
15905b261ecSmrg    maskQ = mask;	/* save these for when we walk the GCque */
16005b261ecSmrg    while (mask && !error)
16105b261ecSmrg    {
16205b261ecSmrg	index2 = (BITS32) lowbit (mask);
16305b261ecSmrg	mask &= ~index2;
16405b261ecSmrg	pGC->stateChanges |= index2;
16505b261ecSmrg	switch (index2)
16605b261ecSmrg	{
16705b261ecSmrg	    case GCFunction:
16805b261ecSmrg	    {
16905b261ecSmrg		CARD8 newalu;
17005b261ecSmrg		NEXTVAL(CARD8, newalu);
17105b261ecSmrg		if (newalu <= GXset)
17205b261ecSmrg		    pGC->alu = newalu;
17305b261ecSmrg		else
17405b261ecSmrg		{
17505b261ecSmrg		    clientErrorValue = newalu;
17605b261ecSmrg		    error = BadValue;
17705b261ecSmrg		}
17805b261ecSmrg		break;
17905b261ecSmrg	    }
18005b261ecSmrg	    case GCPlaneMask:
18105b261ecSmrg		NEXTVAL(unsigned long, pGC->planemask);
18205b261ecSmrg		break;
18305b261ecSmrg	    case GCForeground:
18405b261ecSmrg		NEXTVAL(unsigned long, pGC->fgPixel);
18505b261ecSmrg		/*
18605b261ecSmrg		 * this is for CreateGC
18705b261ecSmrg		 */
18805b261ecSmrg		if (!pGC->tileIsPixel && !pGC->tile.pixmap)
18905b261ecSmrg		{
19005b261ecSmrg		    pGC->tileIsPixel = TRUE;
19105b261ecSmrg		    pGC->tile.pixel = pGC->fgPixel;
19205b261ecSmrg		}
19305b261ecSmrg		break;
19405b261ecSmrg	    case GCBackground:
19505b261ecSmrg		NEXTVAL(unsigned long, pGC->bgPixel);
19605b261ecSmrg		break;
19705b261ecSmrg	    case GCLineWidth:		/* ??? line width is a CARD16 */
19805b261ecSmrg		 NEXTVAL(CARD16, pGC->lineWidth);
19905b261ecSmrg		break;
20005b261ecSmrg	    case GCLineStyle:
20105b261ecSmrg	    {
20205b261ecSmrg		unsigned int newlinestyle;
20305b261ecSmrg		NEXTVAL(unsigned int, newlinestyle);
20405b261ecSmrg		if (newlinestyle <= LineDoubleDash)
20505b261ecSmrg		    pGC->lineStyle = newlinestyle;
20605b261ecSmrg		else
20705b261ecSmrg		{
20805b261ecSmrg		    clientErrorValue = newlinestyle;
20905b261ecSmrg		    error = BadValue;
21005b261ecSmrg		}
21105b261ecSmrg		break;
21205b261ecSmrg	    }
21305b261ecSmrg	    case GCCapStyle:
21405b261ecSmrg	    {
21505b261ecSmrg		unsigned int newcapstyle;
21605b261ecSmrg		NEXTVAL(unsigned int, newcapstyle);
21705b261ecSmrg		if (newcapstyle <= CapProjecting)
21805b261ecSmrg		    pGC->capStyle = newcapstyle;
21905b261ecSmrg		else
22005b261ecSmrg		{
22105b261ecSmrg		    clientErrorValue = newcapstyle;
22205b261ecSmrg		    error = BadValue;
22305b261ecSmrg		}
22405b261ecSmrg		break;
22505b261ecSmrg	    }
22605b261ecSmrg	    case GCJoinStyle:
22705b261ecSmrg	    {
22805b261ecSmrg		unsigned int newjoinstyle;
22905b261ecSmrg		NEXTVAL(unsigned int, newjoinstyle);
23005b261ecSmrg		if (newjoinstyle <= JoinBevel)
23105b261ecSmrg		    pGC->joinStyle = newjoinstyle;
23205b261ecSmrg		else
23305b261ecSmrg		{
23405b261ecSmrg		    clientErrorValue = newjoinstyle;
23505b261ecSmrg		    error = BadValue;
23605b261ecSmrg		}
23705b261ecSmrg		break;
23805b261ecSmrg	    }
23905b261ecSmrg	    case GCFillStyle:
24005b261ecSmrg	    {
24105b261ecSmrg		unsigned int newfillstyle;
24205b261ecSmrg		NEXTVAL(unsigned int, newfillstyle);
24305b261ecSmrg		if (newfillstyle <= FillOpaqueStippled)
24405b261ecSmrg		    pGC->fillStyle = newfillstyle;
24505b261ecSmrg		else
24605b261ecSmrg		{
24705b261ecSmrg		    clientErrorValue = newfillstyle;
24805b261ecSmrg		    error = BadValue;
24905b261ecSmrg		}
25005b261ecSmrg		break;
25105b261ecSmrg	    }
25205b261ecSmrg	    case GCFillRule:
25305b261ecSmrg	    {
25405b261ecSmrg		unsigned int newfillrule;
25505b261ecSmrg		NEXTVAL(unsigned int, newfillrule);
25605b261ecSmrg		if (newfillrule <= WindingRule)
25705b261ecSmrg		    pGC->fillRule = newfillrule;
25805b261ecSmrg		else
25905b261ecSmrg		{
26005b261ecSmrg		    clientErrorValue = newfillrule;
26105b261ecSmrg		    error = BadValue;
26205b261ecSmrg		}
26305b261ecSmrg		break;
26405b261ecSmrg	    }
26505b261ecSmrg	    case GCTile:
26605b261ecSmrg	    {
26705b261ecSmrg		XID newpix = 0;
26805b261ecSmrg		if (pUnion)
26905b261ecSmrg		{
27005b261ecSmrg		    NEXT_PTR(PixmapPtr, pPixmap);
2714642e01fSmrg		    rc = Success;
27205b261ecSmrg		}
27305b261ecSmrg		else
27405b261ecSmrg		{
27505b261ecSmrg		    NEXTVAL(XID, newpix);
2764642e01fSmrg		    rc = dixLookupResource((pointer *)&pPixmap, newpix,
2774642e01fSmrg					   RT_PIXMAP, client, DixReadAccess);
27805b261ecSmrg		}
2794642e01fSmrg		if (rc == Success)
28005b261ecSmrg		{
28105b261ecSmrg		    if ((pPixmap->drawable.depth != pGC->depth) ||
28205b261ecSmrg			(pPixmap->drawable.pScreen != pGC->pScreen))
28305b261ecSmrg		    {
28405b261ecSmrg			error = BadMatch;
28505b261ecSmrg		    }
28605b261ecSmrg		    else
28705b261ecSmrg		    {
28805b261ecSmrg			pPixmap->refcnt++;
28905b261ecSmrg			if (!pGC->tileIsPixel)
29005b261ecSmrg			    (* pGC->pScreen->DestroyPixmap)(pGC->tile.pixmap);
29105b261ecSmrg			pGC->tileIsPixel = FALSE;
29205b261ecSmrg			pGC->tile.pixmap = pPixmap;
29305b261ecSmrg		    }
29405b261ecSmrg		}
29505b261ecSmrg		else
29605b261ecSmrg		{
29705b261ecSmrg		    clientErrorValue = newpix;
2984642e01fSmrg		    error = (rc == BadValue) ? BadPixmap : rc;
29905b261ecSmrg		}
30005b261ecSmrg		break;
30105b261ecSmrg	    }
30205b261ecSmrg	    case GCStipple:
30305b261ecSmrg	    {
30405b261ecSmrg		XID newstipple = 0;
30505b261ecSmrg		if (pUnion)
30605b261ecSmrg		{
30705b261ecSmrg		    NEXT_PTR(PixmapPtr, pPixmap);
3084642e01fSmrg		    rc = Success;
30905b261ecSmrg		}
31005b261ecSmrg		else
31105b261ecSmrg		{
31205b261ecSmrg		    NEXTVAL(XID, newstipple)
3134642e01fSmrg		    rc = dixLookupResource((pointer *)&pPixmap, newstipple,
3144642e01fSmrg					   RT_PIXMAP, client, DixReadAccess);
31505b261ecSmrg		}
3164642e01fSmrg		if (rc == Success)
31705b261ecSmrg		{
31805b261ecSmrg		    if ((pPixmap->drawable.depth != 1) ||
31905b261ecSmrg			(pPixmap->drawable.pScreen != pGC->pScreen))
32005b261ecSmrg		    {
32105b261ecSmrg			error = BadMatch;
32205b261ecSmrg		    }
32305b261ecSmrg		    else
32405b261ecSmrg		    {
32505b261ecSmrg			pPixmap->refcnt++;
32605b261ecSmrg			if (pGC->stipple)
32705b261ecSmrg			    (* pGC->pScreen->DestroyPixmap)(pGC->stipple);
32805b261ecSmrg			pGC->stipple = pPixmap;
32905b261ecSmrg		    }
33005b261ecSmrg		}
33105b261ecSmrg		else
33205b261ecSmrg		{
33305b261ecSmrg		    clientErrorValue = newstipple;
3344642e01fSmrg		    error = (rc == BadValue) ? BadPixmap : rc;
33505b261ecSmrg		}
33605b261ecSmrg		break;
33705b261ecSmrg	    }
33805b261ecSmrg	    case GCTileStipXOrigin:
33905b261ecSmrg		NEXTVAL(INT16, pGC->patOrg.x);
34005b261ecSmrg		break;
34105b261ecSmrg	    case GCTileStipYOrigin:
34205b261ecSmrg		NEXTVAL(INT16, pGC->patOrg.y);
34305b261ecSmrg		break;
34405b261ecSmrg	    case GCFont:
34505b261ecSmrg    	    {
34605b261ecSmrg		FontPtr	pFont;
34705b261ecSmrg		XID newfont = 0;
34805b261ecSmrg		if (pUnion)
34905b261ecSmrg		{
35005b261ecSmrg		    NEXT_PTR(FontPtr, pFont);
3514642e01fSmrg		    rc = Success;
35205b261ecSmrg		}
35305b261ecSmrg		else
35405b261ecSmrg		{
35505b261ecSmrg		    NEXTVAL(XID, newfont)
3564642e01fSmrg		    rc = dixLookupResource((pointer *)&pFont, newfont,
3574642e01fSmrg					   RT_FONT, client, DixUseAccess);
35805b261ecSmrg		}
3594642e01fSmrg		if (rc == Success)
36005b261ecSmrg		{
36105b261ecSmrg		    pFont->refcnt++;
36205b261ecSmrg		    if (pGC->font)
36305b261ecSmrg    		        CloseFont(pGC->font, (Font)0);
36405b261ecSmrg		    pGC->font = pFont;
36505b261ecSmrg		 }
36605b261ecSmrg		else
36705b261ecSmrg		{
36805b261ecSmrg		    clientErrorValue = newfont;
3694642e01fSmrg		    error = (rc == BadValue) ? BadFont : rc;
37005b261ecSmrg		}
37105b261ecSmrg		break;
37205b261ecSmrg	    }
37305b261ecSmrg	    case GCSubwindowMode:
37405b261ecSmrg	    {
37505b261ecSmrg		unsigned int newclipmode;
37605b261ecSmrg		NEXTVAL(unsigned int, newclipmode);
37705b261ecSmrg		if (newclipmode <= IncludeInferiors)
37805b261ecSmrg		    pGC->subWindowMode = newclipmode;
37905b261ecSmrg		else
38005b261ecSmrg		{
38105b261ecSmrg		    clientErrorValue = newclipmode;
38205b261ecSmrg		    error = BadValue;
38305b261ecSmrg		}
38405b261ecSmrg		break;
38505b261ecSmrg	    }
38605b261ecSmrg	    case GCGraphicsExposures:
38705b261ecSmrg    	    {
38805b261ecSmrg		unsigned int newge;
38905b261ecSmrg		NEXTVAL(unsigned int, newge);
39005b261ecSmrg		if (newge <= xTrue)
39105b261ecSmrg		    pGC->graphicsExposures = newge;
39205b261ecSmrg		else
39305b261ecSmrg		{
39405b261ecSmrg		    clientErrorValue = newge;
39505b261ecSmrg		    error = BadValue;
39605b261ecSmrg		}
39705b261ecSmrg		break;
39805b261ecSmrg	    }
39905b261ecSmrg	    case GCClipXOrigin:
40005b261ecSmrg		NEXTVAL(INT16, pGC->clipOrg.x);
40105b261ecSmrg		break;
40205b261ecSmrg	    case GCClipYOrigin:
40305b261ecSmrg		NEXTVAL(INT16, pGC->clipOrg.y);
40405b261ecSmrg		break;
40505b261ecSmrg	    case GCClipMask:
40605b261ecSmrg	    {
40705b261ecSmrg		Pixmap pid = 0;
40805b261ecSmrg		int    clipType = 0;
40905b261ecSmrg
41005b261ecSmrg		if (pUnion)
41105b261ecSmrg		{
41205b261ecSmrg		    NEXT_PTR(PixmapPtr, pPixmap);
41305b261ecSmrg		}
41405b261ecSmrg		else
41505b261ecSmrg		{
41605b261ecSmrg		    NEXTVAL(Pixmap, pid)
41705b261ecSmrg		    if (pid == None)
41805b261ecSmrg		    {
41905b261ecSmrg			clipType = CT_NONE;
42005b261ecSmrg			pPixmap = NullPixmap;
42105b261ecSmrg		    }
4224642e01fSmrg		    else {
4234642e01fSmrg			rc = dixLookupResource((pointer *)&pPixmap, pid,
4244642e01fSmrg					       RT_PIXMAP, client,
4254642e01fSmrg					       DixReadAccess);
4264642e01fSmrg			if (rc != Success) {
4274642e01fSmrg			    clientErrorValue = pid;
4284642e01fSmrg			    error = (rc == BadValue) ? BadPixmap : rc;
4294642e01fSmrg			}
4304642e01fSmrg		    }
43105b261ecSmrg		}
43205b261ecSmrg
43305b261ecSmrg		if (pPixmap)
43405b261ecSmrg		{
43505b261ecSmrg		    if ((pPixmap->drawable.depth != 1) ||
43605b261ecSmrg			(pPixmap->drawable.pScreen != pGC->pScreen))
43705b261ecSmrg		    {
43805b261ecSmrg			error = BadMatch;
43905b261ecSmrg		    }
44005b261ecSmrg		    else
44105b261ecSmrg		    {
44205b261ecSmrg			clipType = CT_PIXMAP;
44305b261ecSmrg			pPixmap->refcnt++;
44405b261ecSmrg		    }
44505b261ecSmrg		}
44605b261ecSmrg		if(error == Success)
44705b261ecSmrg		{
44805b261ecSmrg		    (*pGC->funcs->ChangeClip)(pGC, clipType,
44905b261ecSmrg					      (pointer)pPixmap, 0);
45005b261ecSmrg		}
45105b261ecSmrg		break;
45205b261ecSmrg	    }
45305b261ecSmrg	    case GCDashOffset:
45405b261ecSmrg		NEXTVAL(INT16, pGC->dashOffset);
45505b261ecSmrg		break;
45605b261ecSmrg	    case GCDashList:
45705b261ecSmrg	    {
45805b261ecSmrg		CARD8 newdash;
45905b261ecSmrg		NEXTVAL(CARD8, newdash);
46005b261ecSmrg		if (newdash == 4)
46105b261ecSmrg		{
46205b261ecSmrg		    if (pGC->dash != DefaultDash)
46305b261ecSmrg		    {
46405b261ecSmrg			xfree(pGC->dash);
46505b261ecSmrg			pGC->numInDashList = 2;
46605b261ecSmrg			pGC->dash = DefaultDash;
46705b261ecSmrg		    }
46805b261ecSmrg		}
46905b261ecSmrg		else if (newdash != 0)
47005b261ecSmrg 		{
47105b261ecSmrg		    unsigned char *dash;
47205b261ecSmrg
47305b261ecSmrg		    dash = (unsigned char *)xalloc(2 * sizeof(unsigned char));
47405b261ecSmrg		    if (dash)
47505b261ecSmrg		    {
47605b261ecSmrg			if (pGC->dash != DefaultDash)
47705b261ecSmrg			    xfree(pGC->dash);
47805b261ecSmrg			pGC->numInDashList = 2;
47905b261ecSmrg			pGC->dash = dash;
48005b261ecSmrg			dash[0] = newdash;
48105b261ecSmrg			dash[1] = newdash;
48205b261ecSmrg		    }
48305b261ecSmrg		    else
48405b261ecSmrg			error = BadAlloc;
48505b261ecSmrg		}
48605b261ecSmrg 		else
48705b261ecSmrg		{
48805b261ecSmrg		   clientErrorValue = newdash;
48905b261ecSmrg		   error = BadValue;
49005b261ecSmrg		}
49105b261ecSmrg		break;
49205b261ecSmrg	    }
49305b261ecSmrg	    case GCArcMode:
49405b261ecSmrg	    {
49505b261ecSmrg		unsigned int newarcmode;
49605b261ecSmrg		NEXTVAL(unsigned int, newarcmode);
49705b261ecSmrg		if (newarcmode <= ArcPieSlice)
49805b261ecSmrg		    pGC->arcMode = newarcmode;
49905b261ecSmrg		else
50005b261ecSmrg		{
50105b261ecSmrg		    clientErrorValue = newarcmode;
50205b261ecSmrg		    error = BadValue;
50305b261ecSmrg		}
50405b261ecSmrg		break;
50505b261ecSmrg	    }
50605b261ecSmrg	    default:
50705b261ecSmrg		clientErrorValue = maskQ;
50805b261ecSmrg		error = BadValue;
50905b261ecSmrg		break;
51005b261ecSmrg	}
51105b261ecSmrg    } /* end while mask && !error */
51205b261ecSmrg
51305b261ecSmrg    if (pGC->fillStyle == FillTiled && pGC->tileIsPixel)
51405b261ecSmrg    {
51505b261ecSmrg	if (!CreateDefaultTile (pGC))
51605b261ecSmrg	{
51705b261ecSmrg	    pGC->fillStyle = FillSolid;
51805b261ecSmrg	    error = BadAlloc;
51905b261ecSmrg	}
52005b261ecSmrg    }
52105b261ecSmrg    (*pGC->funcs->ChangeGC)(pGC, maskQ);
52205b261ecSmrg    return error;
52305b261ecSmrg}
52405b261ecSmrg
52505b261ecSmrg#undef NEXTVAL
52605b261ecSmrg#undef NEXT_PTR
52705b261ecSmrg
52805b261ecSmrg/* Publically defined entry to ChangeGC.  Just calls dixChangeGC and tells
52905b261ecSmrg * it that all of the entries are constants or IDs */
53005b261ecSmrg_X_EXPORT int
53105b261ecSmrgChangeGC(GC *pGC, BITS32 mask, XID *pval)
53205b261ecSmrg{
53305b261ecSmrg    return (dixChangeGC(NullClient, pGC, mask, pval, NULL));
53405b261ecSmrg}
53505b261ecSmrg
53605b261ecSmrg/* DoChangeGC(pGC, mask, pval, fPointer)
53705b261ecSmrg   mask is a set of bits indicating which values to change.
53805b261ecSmrg   pval contains an appropriate value for each mask.
53905b261ecSmrg   fPointer is true if the values for tiles, stipples, fonts or clipmasks
54005b261ecSmrg   are pointers instead of IDs.  Note: if you are passing pointers you
54105b261ecSmrg   MUST declare the array of values as type pointer!  Other data types
54205b261ecSmrg   may not be large enough to hold pointers on some machines.  Yes,
54305b261ecSmrg   this means you have to cast to (XID *) when you pass the array to
54405b261ecSmrg   DoChangeGC.  Similarly, if you are not passing pointers (fPointer = 0) you
54505b261ecSmrg   MUST declare the array as type XID (not unsigned long!), or again the wrong
54605b261ecSmrg   size data type may be used.  To avoid this cruftiness, use dixChangeGC
54705b261ecSmrg   above.
54805b261ecSmrg
54905b261ecSmrg   if there is an error, the value is marked as changed
55005b261ecSmrg   anyway, which is probably wrong, but infrequent.
55105b261ecSmrg
55205b261ecSmrgNOTE:
55305b261ecSmrg	all values sent over the protocol for ChangeGC requests are
55405b261ecSmrg32 bits long
55505b261ecSmrg*/
55605b261ecSmrg_X_EXPORT int
55705b261ecSmrgDoChangeGC(GC *pGC, BITS32 mask, XID *pval, int fPointer)
55805b261ecSmrg{
55905b261ecSmrg    if (fPointer)
56005b261ecSmrg    /* XXX might be a problem on 64 bit big-endian servers */
56105b261ecSmrg	return dixChangeGC(NullClient, pGC, mask, NULL, (ChangeGCValPtr)pval);
56205b261ecSmrg    else
56305b261ecSmrg	return dixChangeGC(NullClient, pGC, mask, pval, NULL);
56405b261ecSmrg}
56505b261ecSmrg
56605b261ecSmrg
56705b261ecSmrg/* CreateGC(pDrawable, mask, pval, pStatus)
56805b261ecSmrg   creates a default GC for the given drawable, using mask to fill
56905b261ecSmrg   in any non-default values.
57005b261ecSmrg   Returns a pointer to the new GC on success, NULL otherwise.
57105b261ecSmrg   returns status of non-default fields in pStatus
57205b261ecSmrgBUG:
57305b261ecSmrg   should check for failure to create default tile
57405b261ecSmrg
57505b261ecSmrg*/
57605b261ecSmrg_X_EXPORT GCPtr
5774642e01fSmrgCreateGC(DrawablePtr pDrawable, BITS32 mask, XID *pval, int *pStatus,
5784642e01fSmrg	 XID gcid, ClientPtr client)
57905b261ecSmrg{
58005b261ecSmrg    GCPtr pGC;
58105b261ecSmrg
5824642e01fSmrg    pGC = (GCPtr)xalloc(sizeof(GC));
58305b261ecSmrg    if (!pGC)
58405b261ecSmrg    {
58505b261ecSmrg	*pStatus = BadAlloc;
58605b261ecSmrg	return (GCPtr)NULL;
58705b261ecSmrg    }
58805b261ecSmrg
58905b261ecSmrg    pGC->pScreen = pDrawable->pScreen;
59005b261ecSmrg    pGC->depth = pDrawable->depth;
59105b261ecSmrg    pGC->alu = GXcopy; /* dst <- src */
59205b261ecSmrg    pGC->planemask = ~0;
59305b261ecSmrg    pGC->serialNumber = GC_CHANGE_SERIAL_BIT;
59405b261ecSmrg    pGC->funcs = 0;
5954642e01fSmrg    pGC->devPrivates = NULL;
59605b261ecSmrg    pGC->fgPixel = 0;
59705b261ecSmrg    pGC->bgPixel = 1;
59805b261ecSmrg    pGC->lineWidth = 0;
59905b261ecSmrg    pGC->lineStyle = LineSolid;
60005b261ecSmrg    pGC->capStyle = CapButt;
60105b261ecSmrg    pGC->joinStyle = JoinMiter;
60205b261ecSmrg    pGC->fillStyle = FillSolid;
60305b261ecSmrg    pGC->fillRule = EvenOddRule;
60405b261ecSmrg    pGC->arcMode = ArcPieSlice;
60505b261ecSmrg    if (mask & GCForeground)
60605b261ecSmrg    {
60705b261ecSmrg	/*
60805b261ecSmrg	 * magic special case -- ChangeGC checks for this condition
60905b261ecSmrg	 * and snags the Foreground value to create a pseudo default-tile
61005b261ecSmrg	 */
61105b261ecSmrg	pGC->tileIsPixel = FALSE;
61205b261ecSmrg	pGC->tile.pixmap = NullPixmap;
61305b261ecSmrg    }
61405b261ecSmrg    else
61505b261ecSmrg    {
61605b261ecSmrg	pGC->tileIsPixel = TRUE;
61705b261ecSmrg	pGC->tile.pixel = 0;
61805b261ecSmrg    }
61905b261ecSmrg
62005b261ecSmrg    pGC->patOrg.x = 0;
62105b261ecSmrg    pGC->patOrg.y = 0;
62205b261ecSmrg    pGC->subWindowMode = ClipByChildren;
62305b261ecSmrg    pGC->graphicsExposures = TRUE;
62405b261ecSmrg    pGC->clipOrg.x = 0;
62505b261ecSmrg    pGC->clipOrg.y = 0;
62605b261ecSmrg    pGC->clientClipType = CT_NONE;
62705b261ecSmrg    pGC->clientClip = (pointer)NULL;
62805b261ecSmrg    pGC->numInDashList = 2;
62905b261ecSmrg    pGC->dash = DefaultDash;
63005b261ecSmrg    pGC->dashOffset = 0;
63105b261ecSmrg    pGC->lastWinOrg.x = 0;
63205b261ecSmrg    pGC->lastWinOrg.y = 0;
63305b261ecSmrg
63405b261ecSmrg    /* use the default font and stipple */
63505b261ecSmrg    pGC->font = defaultFont;
63605b261ecSmrg    defaultFont->refcnt++;
63705b261ecSmrg    pGC->stipple = pGC->pScreen->PixmapPerDepth[0];
63805b261ecSmrg    pGC->stipple->refcnt++;
63905b261ecSmrg
6404642e01fSmrg    /* security creation/labeling check */
6414642e01fSmrg    *pStatus = XaceHook(XACE_RESOURCE_ACCESS, client, gcid, RT_GC, pGC,
6424642e01fSmrg			RT_NONE, NULL, DixCreateAccess|DixSetAttrAccess);
6434642e01fSmrg    if (*pStatus != Success)
6444642e01fSmrg	goto out;
6454642e01fSmrg
64605b261ecSmrg    pGC->stateChanges = (1 << (GCLastBit+1)) - 1;
64705b261ecSmrg    if (!(*pGC->pScreen->CreateGC)(pGC))
64805b261ecSmrg	*pStatus = BadAlloc;
64905b261ecSmrg    else if (mask)
65005b261ecSmrg        *pStatus = ChangeGC(pGC, mask, pval);
65105b261ecSmrg    else
65205b261ecSmrg	*pStatus = Success;
6534642e01fSmrg
6544642e01fSmrgout:
65505b261ecSmrg    if (*pStatus != Success)
65605b261ecSmrg    {
65705b261ecSmrg	if (!pGC->tileIsPixel && !pGC->tile.pixmap)
65805b261ecSmrg	    pGC->tileIsPixel = TRUE; /* undo special case */
65905b261ecSmrg	FreeGC(pGC, (XID)0);
66005b261ecSmrg	pGC = (GCPtr)NULL;
66105b261ecSmrg    }
66205b261ecSmrg
66305b261ecSmrg    return (pGC);
66405b261ecSmrg}
66505b261ecSmrg
66605b261ecSmrgstatic Bool
66705b261ecSmrgCreateDefaultTile (GCPtr pGC)
66805b261ecSmrg{
66905b261ecSmrg    XID		tmpval[3];
67005b261ecSmrg    PixmapPtr 	pTile;
67105b261ecSmrg    GCPtr	pgcScratch;
67205b261ecSmrg    xRectangle	rect;
67305b261ecSmrg    CARD16	w, h;
67405b261ecSmrg
67505b261ecSmrg    w = 1;
67605b261ecSmrg    h = 1;
67705b261ecSmrg    (*pGC->pScreen->QueryBestSize)(TileShape, &w, &h, pGC->pScreen);
67805b261ecSmrg    pTile = (PixmapPtr)
67905b261ecSmrg	    (*pGC->pScreen->CreatePixmap)(pGC->pScreen,
6804642e01fSmrg					  w, h, pGC->depth, 0);
68105b261ecSmrg    pgcScratch = GetScratchGC(pGC->depth, pGC->pScreen);
68205b261ecSmrg    if (!pTile || !pgcScratch)
68305b261ecSmrg    {
68405b261ecSmrg	if (pTile)
68505b261ecSmrg	    (*pTile->drawable.pScreen->DestroyPixmap)(pTile);
68605b261ecSmrg	if (pgcScratch)
68705b261ecSmrg	    FreeScratchGC(pgcScratch);
68805b261ecSmrg	return FALSE;
68905b261ecSmrg    }
69005b261ecSmrg    tmpval[0] = GXcopy;
69105b261ecSmrg    tmpval[1] = pGC->tile.pixel;
69205b261ecSmrg    tmpval[2] = FillSolid;
69305b261ecSmrg    (void)ChangeGC(pgcScratch, GCFunction | GCForeground | GCFillStyle,
69405b261ecSmrg		   tmpval);
69505b261ecSmrg    ValidateGC((DrawablePtr)pTile, pgcScratch);
69605b261ecSmrg    rect.x = 0;
69705b261ecSmrg    rect.y = 0;
69805b261ecSmrg    rect.width = w;
69905b261ecSmrg    rect.height = h;
70005b261ecSmrg    (*pgcScratch->ops->PolyFillRect)((DrawablePtr)pTile, pgcScratch, 1, &rect);
70105b261ecSmrg    /* Always remember to free the scratch graphics context after use. */
70205b261ecSmrg    FreeScratchGC(pgcScratch);
70305b261ecSmrg
70405b261ecSmrg    pGC->tileIsPixel = FALSE;
70505b261ecSmrg    pGC->tile.pixmap = pTile;
70605b261ecSmrg    return TRUE;
70705b261ecSmrg}
70805b261ecSmrg
70905b261ecSmrg_X_EXPORT int
71005b261ecSmrgCopyGC(GC *pgcSrc, GC *pgcDst, BITS32 mask)
71105b261ecSmrg{
71205b261ecSmrg    BITS32	index2;
71305b261ecSmrg    BITS32	maskQ;
71405b261ecSmrg    int 	error = 0;
71505b261ecSmrg
71605b261ecSmrg    if (pgcSrc == pgcDst)
71705b261ecSmrg	return Success;
71805b261ecSmrg    pgcDst->serialNumber |= GC_CHANGE_SERIAL_BIT;
71905b261ecSmrg    pgcDst->stateChanges |= mask;
72005b261ecSmrg    maskQ = mask;
72105b261ecSmrg    while (mask)
72205b261ecSmrg    {
72305b261ecSmrg	index2 = (BITS32) lowbit (mask);
72405b261ecSmrg	mask &= ~index2;
72505b261ecSmrg	switch (index2)
72605b261ecSmrg	{
72705b261ecSmrg	    case GCFunction:
72805b261ecSmrg		pgcDst->alu = pgcSrc->alu;
72905b261ecSmrg		break;
73005b261ecSmrg	    case GCPlaneMask:
73105b261ecSmrg		pgcDst->planemask = pgcSrc->planemask;
73205b261ecSmrg		break;
73305b261ecSmrg	    case GCForeground:
73405b261ecSmrg		pgcDst->fgPixel = pgcSrc->fgPixel;
73505b261ecSmrg		break;
73605b261ecSmrg	    case GCBackground:
73705b261ecSmrg		pgcDst->bgPixel = pgcSrc->bgPixel;
73805b261ecSmrg		break;
73905b261ecSmrg	    case GCLineWidth:
74005b261ecSmrg		pgcDst->lineWidth = pgcSrc->lineWidth;
74105b261ecSmrg		break;
74205b261ecSmrg	    case GCLineStyle:
74305b261ecSmrg		pgcDst->lineStyle = pgcSrc->lineStyle;
74405b261ecSmrg		break;
74505b261ecSmrg	    case GCCapStyle:
74605b261ecSmrg		pgcDst->capStyle = pgcSrc->capStyle;
74705b261ecSmrg		break;
74805b261ecSmrg	    case GCJoinStyle:
74905b261ecSmrg		pgcDst->joinStyle = pgcSrc->joinStyle;
75005b261ecSmrg		break;
75105b261ecSmrg	    case GCFillStyle:
75205b261ecSmrg		pgcDst->fillStyle = pgcSrc->fillStyle;
75305b261ecSmrg		break;
75405b261ecSmrg	    case GCFillRule:
75505b261ecSmrg		pgcDst->fillRule = pgcSrc->fillRule;
75605b261ecSmrg		break;
75705b261ecSmrg	    case GCTile:
75805b261ecSmrg		{
75905b261ecSmrg		    if (EqualPixUnion(pgcDst->tileIsPixel,
76005b261ecSmrg				      pgcDst->tile,
76105b261ecSmrg				      pgcSrc->tileIsPixel,
76205b261ecSmrg				      pgcSrc->tile))
76305b261ecSmrg		    {
76405b261ecSmrg			break;
76505b261ecSmrg		    }
76605b261ecSmrg		    if (!pgcDst->tileIsPixel)
76705b261ecSmrg			(* pgcDst->pScreen->DestroyPixmap)(pgcDst->tile.pixmap);
76805b261ecSmrg		    pgcDst->tileIsPixel = pgcSrc->tileIsPixel;
76905b261ecSmrg		    pgcDst->tile = pgcSrc->tile;
77005b261ecSmrg		    if (!pgcDst->tileIsPixel)
77105b261ecSmrg		       pgcDst->tile.pixmap->refcnt++;
77205b261ecSmrg		    break;
77305b261ecSmrg		}
77405b261ecSmrg	    case GCStipple:
77505b261ecSmrg		{
77605b261ecSmrg		    if (pgcDst->stipple == pgcSrc->stipple)
77705b261ecSmrg			break;
77805b261ecSmrg		    if (pgcDst->stipple)
77905b261ecSmrg			(* pgcDst->pScreen->DestroyPixmap)(pgcDst->stipple);
78005b261ecSmrg		    pgcDst->stipple = pgcSrc->stipple;
78105b261ecSmrg		    if (pgcDst->stipple)
78205b261ecSmrg			pgcDst->stipple->refcnt ++;
78305b261ecSmrg		    break;
78405b261ecSmrg		}
78505b261ecSmrg	    case GCTileStipXOrigin:
78605b261ecSmrg		pgcDst->patOrg.x = pgcSrc->patOrg.x;
78705b261ecSmrg		break;
78805b261ecSmrg	    case GCTileStipYOrigin:
78905b261ecSmrg		pgcDst->patOrg.y = pgcSrc->patOrg.y;
79005b261ecSmrg		break;
79105b261ecSmrg	    case GCFont:
79205b261ecSmrg		if (pgcDst->font == pgcSrc->font)
79305b261ecSmrg		    break;
79405b261ecSmrg		if (pgcDst->font)
79505b261ecSmrg		    CloseFont(pgcDst->font, (Font)0);
79605b261ecSmrg		if ((pgcDst->font = pgcSrc->font) != NullFont)
79705b261ecSmrg		    (pgcDst->font)->refcnt++;
79805b261ecSmrg		break;
79905b261ecSmrg	    case GCSubwindowMode:
80005b261ecSmrg		pgcDst->subWindowMode = pgcSrc->subWindowMode;
80105b261ecSmrg		break;
80205b261ecSmrg	    case GCGraphicsExposures:
80305b261ecSmrg		pgcDst->graphicsExposures = pgcSrc->graphicsExposures;
80405b261ecSmrg		break;
80505b261ecSmrg	    case GCClipXOrigin:
80605b261ecSmrg		pgcDst->clipOrg.x = pgcSrc->clipOrg.x;
80705b261ecSmrg		break;
80805b261ecSmrg	    case GCClipYOrigin:
80905b261ecSmrg		pgcDst->clipOrg.y = pgcSrc->clipOrg.y;
81005b261ecSmrg		break;
81105b261ecSmrg	    case GCClipMask:
81205b261ecSmrg		(* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
81305b261ecSmrg		break;
81405b261ecSmrg	    case GCDashOffset:
81505b261ecSmrg		pgcDst->dashOffset = pgcSrc->dashOffset;
81605b261ecSmrg		break;
81705b261ecSmrg	    case GCDashList:
81805b261ecSmrg		if (pgcSrc->dash == DefaultDash)
81905b261ecSmrg		{
82005b261ecSmrg		    if (pgcDst->dash != DefaultDash)
82105b261ecSmrg		    {
82205b261ecSmrg			xfree(pgcDst->dash);
82305b261ecSmrg			pgcDst->numInDashList = pgcSrc->numInDashList;
82405b261ecSmrg			pgcDst->dash = pgcSrc->dash;
82505b261ecSmrg		    }
82605b261ecSmrg		}
82705b261ecSmrg		else
82805b261ecSmrg		{
82905b261ecSmrg		    unsigned char *dash;
83005b261ecSmrg		    unsigned int i;
83105b261ecSmrg
83205b261ecSmrg		    dash = (unsigned char *)xalloc(pgcSrc->numInDashList *
83305b261ecSmrg						   sizeof(unsigned char));
83405b261ecSmrg		    if (dash)
83505b261ecSmrg		    {
83605b261ecSmrg			if (pgcDst->dash != DefaultDash)
83705b261ecSmrg			    xfree(pgcDst->dash);
83805b261ecSmrg			pgcDst->numInDashList = pgcSrc->numInDashList;
83905b261ecSmrg			pgcDst->dash = dash;
84005b261ecSmrg			for (i=0; i<pgcSrc->numInDashList; i++)
84105b261ecSmrg			    dash[i] = pgcSrc->dash[i];
84205b261ecSmrg		    }
84305b261ecSmrg		    else
84405b261ecSmrg			error = BadAlloc;
84505b261ecSmrg		}
84605b261ecSmrg		break;
84705b261ecSmrg	    case GCArcMode:
84805b261ecSmrg		pgcDst->arcMode = pgcSrc->arcMode;
84905b261ecSmrg		break;
85005b261ecSmrg	    default:
85105b261ecSmrg		clientErrorValue = maskQ;
85205b261ecSmrg		error = BadValue;
85305b261ecSmrg		break;
85405b261ecSmrg	}
85505b261ecSmrg    }
85605b261ecSmrg    if (pgcDst->fillStyle == FillTiled && pgcDst->tileIsPixel)
85705b261ecSmrg    {
85805b261ecSmrg	if (!CreateDefaultTile (pgcDst))
85905b261ecSmrg	{
86005b261ecSmrg	    pgcDst->fillStyle = FillSolid;
86105b261ecSmrg	    error = BadAlloc;
86205b261ecSmrg	}
86305b261ecSmrg    }
86405b261ecSmrg    (*pgcDst->funcs->CopyGC) (pgcSrc, maskQ, pgcDst);
86505b261ecSmrg    return error;
86605b261ecSmrg}
86705b261ecSmrg
86805b261ecSmrg/**
86905b261ecSmrg * does the diX part of freeing the characteristics in the GC.
87005b261ecSmrg *
87105b261ecSmrg *  \param value  must conform to DeleteType
87205b261ecSmrg */
87305b261ecSmrg_X_EXPORT int
87405b261ecSmrgFreeGC(pointer value, XID gid)
87505b261ecSmrg{
87605b261ecSmrg    GCPtr pGC = (GCPtr)value;
87705b261ecSmrg
87805b261ecSmrg    CloseFont(pGC->font, (Font)0);
87905b261ecSmrg    (* pGC->funcs->DestroyClip)(pGC);
88005b261ecSmrg
88105b261ecSmrg    if (!pGC->tileIsPixel)
88205b261ecSmrg	(* pGC->pScreen->DestroyPixmap)(pGC->tile.pixmap);
88305b261ecSmrg    if (pGC->stipple)
88405b261ecSmrg	(* pGC->pScreen->DestroyPixmap)(pGC->stipple);
88505b261ecSmrg
88605b261ecSmrg    (*pGC->funcs->DestroyGC) (pGC);
88705b261ecSmrg    if (pGC->dash != DefaultDash)
88805b261ecSmrg	xfree(pGC->dash);
8894642e01fSmrg    dixFreePrivates(pGC->devPrivates);
89005b261ecSmrg    xfree(pGC);
89105b261ecSmrg    return(Success);
89205b261ecSmrg}
89305b261ecSmrg
89405b261ecSmrg/* CreateScratchGC(pScreen, depth)
89505b261ecSmrg    like CreateGC, but doesn't do the default tile or stipple,
89605b261ecSmrgsince we can't create them without already having a GC.  any code
89705b261ecSmrgusing the tile or stipple has to set them explicitly anyway,
89805b261ecSmrgsince the state of the scratch gc is unknown.  This is OK
89905b261ecSmrgbecause ChangeGC() has to be able to deal with NULL tiles and
90005b261ecSmrgstipples anyway (in case the CreateGC() call has provided a
90105b261ecSmrgvalue for them -- we can't set the default tile until the
90205b261ecSmrgclient-supplied attributes are installed, since the fgPixel
90305b261ecSmrgis what fills the default tile.  (maybe this comment should
90405b261ecSmrggo with CreateGC() or ChangeGC().)
90505b261ecSmrg*/
90605b261ecSmrg
90705b261ecSmrg_X_EXPORT GCPtr
90805b261ecSmrgCreateScratchGC(ScreenPtr pScreen, unsigned depth)
90905b261ecSmrg{
91005b261ecSmrg    GCPtr pGC;
91105b261ecSmrg
9124642e01fSmrg    pGC = (GCPtr)xalloc(sizeof(GC));
91305b261ecSmrg    if (!pGC)
91405b261ecSmrg	return (GCPtr)NULL;
91505b261ecSmrg
91605b261ecSmrg    pGC->pScreen = pScreen;
91705b261ecSmrg    pGC->depth = depth;
91805b261ecSmrg    pGC->alu = GXcopy; /* dst <- src */
91905b261ecSmrg    pGC->planemask = ~0;
92005b261ecSmrg    pGC->serialNumber = 0;
9214642e01fSmrg    pGC->devPrivates = NULL;
92205b261ecSmrg    pGC->fgPixel = 0;
92305b261ecSmrg    pGC->bgPixel = 1;
92405b261ecSmrg    pGC->lineWidth = 0;
92505b261ecSmrg    pGC->lineStyle = LineSolid;
92605b261ecSmrg    pGC->capStyle = CapButt;
92705b261ecSmrg    pGC->joinStyle = JoinMiter;
92805b261ecSmrg    pGC->fillStyle = FillSolid;
92905b261ecSmrg    pGC->fillRule = EvenOddRule;
93005b261ecSmrg    pGC->arcMode = ArcPieSlice;
93105b261ecSmrg    pGC->font = defaultFont;
93205b261ecSmrg    if ( pGC->font)  /* necessary, because open of default font could fail */
93305b261ecSmrg	pGC->font->refcnt++;
93405b261ecSmrg    pGC->tileIsPixel = TRUE;
93505b261ecSmrg    pGC->tile.pixel = 0;
93605b261ecSmrg    pGC->stipple = NullPixmap;
93705b261ecSmrg    pGC->patOrg.x = 0;
93805b261ecSmrg    pGC->patOrg.y = 0;
93905b261ecSmrg    pGC->subWindowMode = ClipByChildren;
94005b261ecSmrg    pGC->graphicsExposures = TRUE;
94105b261ecSmrg    pGC->clipOrg.x = 0;
94205b261ecSmrg    pGC->clipOrg.y = 0;
94305b261ecSmrg    pGC->clientClipType = CT_NONE;
94405b261ecSmrg    pGC->dashOffset = 0;
94505b261ecSmrg    pGC->numInDashList = 2;
94605b261ecSmrg    pGC->dash = DefaultDash;
94705b261ecSmrg    pGC->lastWinOrg.x = 0;
94805b261ecSmrg    pGC->lastWinOrg.y = 0;
94905b261ecSmrg
95005b261ecSmrg    pGC->stateChanges = (1 << (GCLastBit+1)) - 1;
95105b261ecSmrg    if (!(*pScreen->CreateGC)(pGC))
95205b261ecSmrg    {
95305b261ecSmrg	FreeGC(pGC, (XID)0);
95405b261ecSmrg	pGC = (GCPtr)NULL;
95505b261ecSmrg    }
95605b261ecSmrg    return pGC;
95705b261ecSmrg}
95805b261ecSmrg
95905b261ecSmrgvoid
96005b261ecSmrgFreeGCperDepth(int screenNum)
96105b261ecSmrg{
96205b261ecSmrg    int i;
96305b261ecSmrg    ScreenPtr pScreen;
96405b261ecSmrg    GCPtr *ppGC;
96505b261ecSmrg
96605b261ecSmrg    pScreen = screenInfo.screens[screenNum];
96705b261ecSmrg    ppGC = pScreen->GCperDepth;
96805b261ecSmrg
96905b261ecSmrg    for (i = 0; i <= pScreen->numDepths; i++)
97005b261ecSmrg	(void)FreeGC(ppGC[i], (XID)0);
97105b261ecSmrg    pScreen->rgf = ~0L;
97205b261ecSmrg}
97305b261ecSmrg
97405b261ecSmrg
97505b261ecSmrgBool
97605b261ecSmrgCreateGCperDepth(int screenNum)
97705b261ecSmrg{
97805b261ecSmrg    int i;
97905b261ecSmrg    ScreenPtr pScreen;
98005b261ecSmrg    DepthPtr pDepth;
98105b261ecSmrg    GCPtr *ppGC;
98205b261ecSmrg
98305b261ecSmrg    pScreen = screenInfo.screens[screenNum];
98405b261ecSmrg    pScreen->rgf = 0;
98505b261ecSmrg    ppGC = pScreen->GCperDepth;
98605b261ecSmrg    /* do depth 1 separately because it's not included in list */
98705b261ecSmrg    if (!(ppGC[0] = CreateScratchGC(pScreen, 1)))
98805b261ecSmrg	return FALSE;
98905b261ecSmrg    ppGC[0]->graphicsExposures = FALSE;
99005b261ecSmrg    /* Make sure we don't overflow GCperDepth[] */
99105b261ecSmrg    if( pScreen->numDepths > MAXFORMATS )
99205b261ecSmrg	    return FALSE;
99305b261ecSmrg
99405b261ecSmrg    pDepth = pScreen->allowedDepths;
99505b261ecSmrg    for (i=0; i<pScreen->numDepths; i++, pDepth++)
99605b261ecSmrg    {
99705b261ecSmrg	if (!(ppGC[i+1] = CreateScratchGC(pScreen, pDepth->depth)))
99805b261ecSmrg	{
99905b261ecSmrg	    for (; i >= 0; i--)
100005b261ecSmrg		(void)FreeGC(ppGC[i], (XID)0);
100105b261ecSmrg	    return FALSE;
100205b261ecSmrg	}
100305b261ecSmrg	ppGC[i+1]->graphicsExposures = FALSE;
100405b261ecSmrg    }
100505b261ecSmrg    return TRUE;
100605b261ecSmrg}
100705b261ecSmrg
100805b261ecSmrgBool
100905b261ecSmrgCreateDefaultStipple(int screenNum)
101005b261ecSmrg{
101105b261ecSmrg    ScreenPtr pScreen;
101205b261ecSmrg    XID tmpval[3];
101305b261ecSmrg    xRectangle rect;
101405b261ecSmrg    CARD16 w, h;
101505b261ecSmrg    GCPtr pgcScratch;
101605b261ecSmrg
101705b261ecSmrg    pScreen = screenInfo.screens[screenNum];
101805b261ecSmrg
101905b261ecSmrg    w = 16;
102005b261ecSmrg    h = 16;
102105b261ecSmrg    (* pScreen->QueryBestSize)(StippleShape, &w, &h, pScreen);
102205b261ecSmrg    if (!(pScreen->PixmapPerDepth[0] =
10234642e01fSmrg			(*pScreen->CreatePixmap)(pScreen, w, h, 1, 0)))
102405b261ecSmrg	return FALSE;
102505b261ecSmrg    /* fill stipple with 1 */
102605b261ecSmrg    tmpval[0] = GXcopy; tmpval[1] = 1; tmpval[2] = FillSolid;
102705b261ecSmrg    pgcScratch = GetScratchGC(1, pScreen);
102805b261ecSmrg    if (!pgcScratch)
102905b261ecSmrg    {
103005b261ecSmrg	(*pScreen->DestroyPixmap)(pScreen->PixmapPerDepth[0]);
103105b261ecSmrg	return FALSE;
103205b261ecSmrg    }
103305b261ecSmrg    (void)ChangeGC(pgcScratch, GCFunction|GCForeground|GCFillStyle, tmpval);
103405b261ecSmrg    ValidateGC((DrawablePtr)pScreen->PixmapPerDepth[0], pgcScratch);
103505b261ecSmrg    rect.x = 0;
103605b261ecSmrg    rect.y = 0;
103705b261ecSmrg    rect.width = w;
103805b261ecSmrg    rect.height = h;
103905b261ecSmrg    (*pgcScratch->ops->PolyFillRect)((DrawablePtr)pScreen->PixmapPerDepth[0],
104005b261ecSmrg				     pgcScratch, 1, &rect);
104105b261ecSmrg    FreeScratchGC(pgcScratch);
104205b261ecSmrg    return TRUE;
104305b261ecSmrg}
104405b261ecSmrg
104505b261ecSmrgvoid
104605b261ecSmrgFreeDefaultStipple(int screenNum)
104705b261ecSmrg{
104805b261ecSmrg    ScreenPtr pScreen = screenInfo.screens[screenNum];
104905b261ecSmrg    (*pScreen->DestroyPixmap)(pScreen->PixmapPerDepth[0]);
105005b261ecSmrg}
105105b261ecSmrg
10524642e01fSmrgint
105305b261ecSmrgSetDashes(GCPtr pGC, unsigned offset, unsigned ndash, unsigned char *pdash)
105405b261ecSmrg{
105505b261ecSmrg    long i;
105605b261ecSmrg    unsigned char *p, *indash;
105705b261ecSmrg    BITS32 maskQ = 0;
105805b261ecSmrg
105905b261ecSmrg    i = ndash;
106005b261ecSmrg    p = pdash;
106105b261ecSmrg    while (i--)
106205b261ecSmrg    {
106305b261ecSmrg	if (!*p++)
106405b261ecSmrg	{
106505b261ecSmrg	    /* dash segment must be > 0 */
106605b261ecSmrg	    clientErrorValue = 0;
106705b261ecSmrg	    return BadValue;
106805b261ecSmrg	}
106905b261ecSmrg    }
107005b261ecSmrg
107105b261ecSmrg    if (ndash & 1)
107205b261ecSmrg	p = (unsigned char *)xalloc(2 * ndash * sizeof(unsigned char));
107305b261ecSmrg    else
107405b261ecSmrg	p = (unsigned char *)xalloc(ndash * sizeof(unsigned char));
107505b261ecSmrg    if (!p)
107605b261ecSmrg	return BadAlloc;
107705b261ecSmrg
107805b261ecSmrg    pGC->serialNumber |= GC_CHANGE_SERIAL_BIT;
107905b261ecSmrg    if (offset != pGC->dashOffset)
108005b261ecSmrg    {
108105b261ecSmrg	pGC->dashOffset = offset;
108205b261ecSmrg	pGC->stateChanges |= GCDashOffset;
108305b261ecSmrg	maskQ |= GCDashOffset;
108405b261ecSmrg    }
108505b261ecSmrg
108605b261ecSmrg    if (pGC->dash != DefaultDash)
108705b261ecSmrg	xfree(pGC->dash);
108805b261ecSmrg    pGC->numInDashList = ndash;
108905b261ecSmrg    pGC->dash = p;
109005b261ecSmrg    if (ndash & 1)
109105b261ecSmrg    {
109205b261ecSmrg	pGC->numInDashList += ndash;
109305b261ecSmrg	indash = pdash;
109405b261ecSmrg	i = ndash;
109505b261ecSmrg	while (i--)
109605b261ecSmrg	    *p++ = *indash++;
109705b261ecSmrg    }
109805b261ecSmrg    while(ndash--)
109905b261ecSmrg	*p++ = *pdash++;
110005b261ecSmrg    pGC->stateChanges |= GCDashList;
110105b261ecSmrg    maskQ |= GCDashList;
110205b261ecSmrg
110305b261ecSmrg    if (pGC->funcs->ChangeGC)
110405b261ecSmrg	(*pGC->funcs->ChangeGC) (pGC, maskQ);
110505b261ecSmrg    return Success;
110605b261ecSmrg}
110705b261ecSmrg
110805b261ecSmrg_X_EXPORT int
110905b261ecSmrgVerifyRectOrder(int nrects, xRectangle *prects, int ordering)
111005b261ecSmrg{
111105b261ecSmrg    xRectangle	*prectP, *prectN;
111205b261ecSmrg    int	i;
111305b261ecSmrg
111405b261ecSmrg    switch(ordering)
111505b261ecSmrg    {
111605b261ecSmrg      case Unsorted:
111705b261ecSmrg	  return CT_UNSORTED;
111805b261ecSmrg      case YSorted:
111905b261ecSmrg	  if(nrects > 1)
112005b261ecSmrg	  {
112105b261ecSmrg	      for(i = 1, prectP = prects, prectN = prects + 1;
112205b261ecSmrg		  i < nrects;
112305b261ecSmrg		  i++, prectP++, prectN++)
112405b261ecSmrg		  if(prectN->y < prectP->y)
112505b261ecSmrg		      return -1;
112605b261ecSmrg	  }
112705b261ecSmrg	  return CT_YSORTED;
112805b261ecSmrg      case YXSorted:
112905b261ecSmrg	  if(nrects > 1)
113005b261ecSmrg	  {
113105b261ecSmrg	      for(i = 1, prectP = prects, prectN = prects + 1;
113205b261ecSmrg		  i < nrects;
113305b261ecSmrg		  i++, prectP++, prectN++)
113405b261ecSmrg		  if((prectN->y < prectP->y) ||
113505b261ecSmrg		      ( (prectN->y == prectP->y) &&
113605b261ecSmrg		        (prectN->x < prectP->x) ) )
113705b261ecSmrg		      return -1;
113805b261ecSmrg	  }
113905b261ecSmrg	  return CT_YXSORTED;
114005b261ecSmrg      case YXBanded:
114105b261ecSmrg	  if(nrects > 1)
114205b261ecSmrg	  {
114305b261ecSmrg	      for(i = 1, prectP = prects, prectN = prects + 1;
114405b261ecSmrg		  i < nrects;
114505b261ecSmrg		  i++, prectP++, prectN++)
114605b261ecSmrg		  if((prectN->y != prectP->y &&
114705b261ecSmrg 		      prectN->y < prectP->y + (int) prectP->height) ||
114805b261ecSmrg		     ((prectN->y == prectP->y) &&
114905b261ecSmrg		      (prectN->height != prectP->height ||
115005b261ecSmrg		       prectN->x < prectP->x + (int) prectP->width)))
115105b261ecSmrg		      return -1;
115205b261ecSmrg	  }
115305b261ecSmrg	  return CT_YXBANDED;
115405b261ecSmrg    }
115505b261ecSmrg    return -1;
115605b261ecSmrg}
115705b261ecSmrg
11584642e01fSmrgint
115905b261ecSmrgSetClipRects(GCPtr pGC, int xOrigin, int yOrigin, int nrects,
116005b261ecSmrg             xRectangle *prects, int ordering)
116105b261ecSmrg{
116205b261ecSmrg    int			newct, size;
116305b261ecSmrg    xRectangle 		*prectsNew;
116405b261ecSmrg
116505b261ecSmrg    newct = VerifyRectOrder(nrects, prects, ordering);
116605b261ecSmrg    if (newct < 0)
116705b261ecSmrg	return(BadMatch);
116805b261ecSmrg    size = nrects * sizeof(xRectangle);
116905b261ecSmrg    prectsNew = (xRectangle *) xalloc(size);
117005b261ecSmrg    if (!prectsNew && size)
117105b261ecSmrg	return BadAlloc;
117205b261ecSmrg
117305b261ecSmrg    pGC->serialNumber |= GC_CHANGE_SERIAL_BIT;
117405b261ecSmrg    pGC->clipOrg.x = xOrigin;
117505b261ecSmrg    pGC->stateChanges |= GCClipXOrigin;
117605b261ecSmrg
117705b261ecSmrg    pGC->clipOrg.y = yOrigin;
117805b261ecSmrg    pGC->stateChanges |= GCClipYOrigin;
117905b261ecSmrg
118005b261ecSmrg    if (size)
118105b261ecSmrg	memmove((char *)prectsNew, (char *)prects, size);
118205b261ecSmrg    (*pGC->funcs->ChangeClip)(pGC, newct, (pointer)prectsNew, nrects);
118305b261ecSmrg    if (pGC->funcs->ChangeGC)
118405b261ecSmrg	(*pGC->funcs->ChangeGC) (pGC, GCClipXOrigin|GCClipYOrigin|GCClipMask);
118505b261ecSmrg    return Success;
118605b261ecSmrg}
118705b261ecSmrg
118805b261ecSmrg
118905b261ecSmrg/*
119005b261ecSmrg   sets reasonable defaults
119105b261ecSmrg   if we can get a pre-allocated one, use it and mark it as used.
119205b261ecSmrg   if we can't, create one out of whole cloth (The Velveteen GC -- if
119305b261ecSmrg   you use it often enough it will become real.)
119405b261ecSmrg*/
119505b261ecSmrg_X_EXPORT GCPtr
119605b261ecSmrgGetScratchGC(unsigned depth, ScreenPtr pScreen)
119705b261ecSmrg{
119805b261ecSmrg    int i;
119905b261ecSmrg    GCPtr pGC;
120005b261ecSmrg
120105b261ecSmrg    for (i=0; i<=pScreen->numDepths; i++)
120205b261ecSmrg        if ( pScreen->GCperDepth[i]->depth == depth &&
120305b261ecSmrg	     !(pScreen->rgf & (1L << (i+1)))
120405b261ecSmrg	   )
120505b261ecSmrg	{
120605b261ecSmrg	    pScreen->rgf |= (1L << (i+1));
120705b261ecSmrg            pGC = (pScreen->GCperDepth[i]);
120805b261ecSmrg
120905b261ecSmrg	    pGC->alu = GXcopy;
121005b261ecSmrg	    pGC->planemask = ~0;
121105b261ecSmrg	    pGC->serialNumber = 0;
121205b261ecSmrg	    pGC->fgPixel = 0;
121305b261ecSmrg	    pGC->bgPixel = 1;
121405b261ecSmrg	    pGC->lineWidth = 0;
121505b261ecSmrg	    pGC->lineStyle = LineSolid;
121605b261ecSmrg	    pGC->capStyle = CapButt;
121705b261ecSmrg	    pGC->joinStyle = JoinMiter;
121805b261ecSmrg	    pGC->fillStyle = FillSolid;
121905b261ecSmrg	    pGC->fillRule = EvenOddRule;
122005b261ecSmrg	    pGC->arcMode = ArcChord;
122105b261ecSmrg	    pGC->patOrg.x = 0;
122205b261ecSmrg	    pGC->patOrg.y = 0;
122305b261ecSmrg	    pGC->subWindowMode = ClipByChildren;
122405b261ecSmrg	    pGC->graphicsExposures = FALSE;
122505b261ecSmrg	    pGC->clipOrg.x = 0;
122605b261ecSmrg	    pGC->clipOrg.y = 0;
122705b261ecSmrg	    if (pGC->clientClipType != CT_NONE)
122805b261ecSmrg		(*pGC->funcs->ChangeClip) (pGC, CT_NONE, NULL, 0);
122905b261ecSmrg	    pGC->stateChanges = (1 << (GCLastBit+1)) - 1;
123005b261ecSmrg	    return pGC;
123105b261ecSmrg	}
123205b261ecSmrg    /* if we make it this far, need to roll our own */
123305b261ecSmrg    pGC = CreateScratchGC(pScreen, depth);
123405b261ecSmrg    if (pGC)
123505b261ecSmrg	pGC->graphicsExposures = FALSE;
123605b261ecSmrg    return pGC;
123705b261ecSmrg}
123805b261ecSmrg
123905b261ecSmrg/*
124005b261ecSmrg   if the gc to free is in the table of pre-existing ones,
124105b261ecSmrgmark it as available.
124205b261ecSmrg   if not, free it for real
124305b261ecSmrg*/
124405b261ecSmrg_X_EXPORT void
124505b261ecSmrgFreeScratchGC(GCPtr pGC)
124605b261ecSmrg{
124705b261ecSmrg    ScreenPtr pScreen = pGC->pScreen;
124805b261ecSmrg    int i;
124905b261ecSmrg
125005b261ecSmrg    for (i=0; i<=pScreen->numDepths; i++)
125105b261ecSmrg    {
125205b261ecSmrg        if ( pScreen->GCperDepth[i] == pGC)
125305b261ecSmrg	{
125405b261ecSmrg	    pScreen->rgf &= ~(1L << (i+1));
125505b261ecSmrg	    return;
125605b261ecSmrg	}
125705b261ecSmrg    }
125805b261ecSmrg    (void)FreeGC(pGC, (GContext)0);
125905b261ecSmrg}
1260