miexpose.c revision 05b261ec
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
4905b261ecSmrgCopyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
5005b261ecSmrg
5105b261ecSmrgPermission is hereby granted, free of charge, to any person obtaining a copy
5205b261ecSmrgof this software and associated documentation files (the "Software"), to deal
5305b261ecSmrgin the Software without restriction, including without limitation the rights
5405b261ecSmrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell
5505b261ecSmrgcopies of the Software.
5605b261ecSmrg
5705b261ecSmrgThe above copyright notice and this permission notice shall be included in
5805b261ecSmrgall copies or substantial portions of the Software.
5905b261ecSmrg
6005b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6105b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6205b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
6305b261ecSmrgDIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
6405b261ecSmrgBUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
6505b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
6605b261ecSmrgIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
6705b261ecSmrg
6805b261ecSmrgExcept as contained in this notice, the name of Digital Equipment Corporation
6905b261ecSmrgshall not be used in advertising or otherwise to promote the sale, use or other
7005b261ecSmrgdealings in this Software without prior written authorization from Digital
7105b261ecSmrgEquipment Corporation.
7205b261ecSmrg
7305b261ecSmrg******************************************************************/
7405b261ecSmrg
7505b261ecSmrg
7605b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
7705b261ecSmrg#include <dix-config.h>
7805b261ecSmrg#endif
7905b261ecSmrg
8005b261ecSmrg#include <X11/X.h>
8105b261ecSmrg#define NEED_EVENTS
8205b261ecSmrg#include <X11/Xproto.h>
8305b261ecSmrg#include <X11/Xprotostr.h>
8405b261ecSmrg
8505b261ecSmrg#include "misc.h"
8605b261ecSmrg#include "regionstr.h"
8705b261ecSmrg#include "scrnintstr.h"
8805b261ecSmrg#include "gcstruct.h"
8905b261ecSmrg#include "windowstr.h"
9005b261ecSmrg#include "pixmap.h"
9105b261ecSmrg#include "input.h"
9205b261ecSmrg
9305b261ecSmrg#include "dixstruct.h"
9405b261ecSmrg#include "mi.h"
9505b261ecSmrg#include <X11/Xmd.h>
9605b261ecSmrg
9705b261ecSmrg#include "globals.h"
9805b261ecSmrg
9905b261ecSmrg#ifdef PANORAMIX
10005b261ecSmrg#include "panoramiX.h"
10105b261ecSmrg#include "panoramiXsrv.h"
10205b261ecSmrg#endif
10305b261ecSmrg
10405b261ecSmrg/*
10505b261ecSmrg    machine-independent graphics exposure code.  any device that uses
10605b261ecSmrgthe region package can call this.
10705b261ecSmrg*/
10805b261ecSmrg
10905b261ecSmrg#ifndef RECTLIMIT
11005b261ecSmrg#define RECTLIMIT 25		/* pick a number, any number > 8 */
11105b261ecSmrg#endif
11205b261ecSmrg
11305b261ecSmrg/* miHandleExposures
11405b261ecSmrg    generate a region for exposures for areas that were copied from obscured or
11505b261ecSmrgnon-existent areas to non-obscured areas of the destination.  Paint the
11605b261ecSmrgbackground for the region, if the destination is a window.
11705b261ecSmrg
11805b261ecSmrgNOTE:
11905b261ecSmrg     this should generally be called, even if graphicsExposures is false,
12005b261ecSmrgbecause this is where bits get recovered from backing store.
12105b261ecSmrg
12205b261ecSmrgNOTE:
12305b261ecSmrg     added argument 'plane' is used to indicate how exposures from backing
12405b261ecSmrgstore should be accomplished. If plane is 0 (i.e. no bit plane), CopyArea
12505b261ecSmrgshould be used, else a CopyPlane of the indicated plane will be used. The
12605b261ecSmrgexposing is done by the backing store's GraphicsExpose function, of course.
12705b261ecSmrg
12805b261ecSmrg*/
12905b261ecSmrg
13005b261ecSmrg_X_EXPORT RegionPtr
13105b261ecSmrgmiHandleExposures(pSrcDrawable, pDstDrawable,
13205b261ecSmrg		  pGC, srcx, srcy, width, height, dstx, dsty, plane)
13305b261ecSmrg    DrawablePtr			pSrcDrawable;
13405b261ecSmrg    DrawablePtr			pDstDrawable;
13505b261ecSmrg    GCPtr 			pGC;
13605b261ecSmrg    int 			srcx, srcy;
13705b261ecSmrg    int 			width, height;
13805b261ecSmrg    int 			dstx, dsty;
13905b261ecSmrg    unsigned long		plane;
14005b261ecSmrg{
14105b261ecSmrg    ScreenPtr pscr;
14205b261ecSmrg    RegionPtr prgnSrcClip;	/* drawable-relative source clip */
14305b261ecSmrg    RegionRec rgnSrcRec;
14405b261ecSmrg    RegionPtr prgnDstClip;	/* drawable-relative dest clip */
14505b261ecSmrg    RegionRec rgnDstRec;
14605b261ecSmrg    BoxRec srcBox;		/* unclipped source */
14705b261ecSmrg    RegionRec rgnExposed;	/* exposed region, calculated source-
14805b261ecSmrg				   relative, made dst relative to
14905b261ecSmrg				   intersect with visible parts of
15005b261ecSmrg				   dest and send events to client,
15105b261ecSmrg				   and then screen relative to paint
15205b261ecSmrg				   the window background
15305b261ecSmrg				*/
15405b261ecSmrg    WindowPtr pSrcWin;
15505b261ecSmrg    BoxRec expBox;
15605b261ecSmrg    Bool extents;
15705b261ecSmrg
15805b261ecSmrg    /* This prevents warning about pscr not being used. */
15905b261ecSmrg    pGC->pScreen = pscr = pGC->pScreen;
16005b261ecSmrg
16105b261ecSmrg    /* avoid work if we can */
16205b261ecSmrg    if (!pGC->graphicsExposures &&
16305b261ecSmrg	(pDstDrawable->type == DRAWABLE_PIXMAP) &&
16405b261ecSmrg	((pSrcDrawable->type == DRAWABLE_PIXMAP) ||
16505b261ecSmrg	 (((WindowPtr)pSrcDrawable)->backStorage == NULL)))
16605b261ecSmrg	return NULL;
16705b261ecSmrg
16805b261ecSmrg    srcBox.x1 = srcx;
16905b261ecSmrg    srcBox.y1 = srcy;
17005b261ecSmrg    srcBox.x2 = srcx+width;
17105b261ecSmrg    srcBox.y2 = srcy+height;
17205b261ecSmrg
17305b261ecSmrg    if (pSrcDrawable->type != DRAWABLE_PIXMAP)
17405b261ecSmrg    {
17505b261ecSmrg	BoxRec TsrcBox;
17605b261ecSmrg
17705b261ecSmrg	TsrcBox.x1 = srcx + pSrcDrawable->x;
17805b261ecSmrg	TsrcBox.y1 = srcy + pSrcDrawable->y;
17905b261ecSmrg	TsrcBox.x2 = TsrcBox.x1 + width;
18005b261ecSmrg	TsrcBox.y2 = TsrcBox.y1 + height;
18105b261ecSmrg	pSrcWin = (WindowPtr) pSrcDrawable;
18205b261ecSmrg	if (pGC->subWindowMode == IncludeInferiors)
18305b261ecSmrg 	{
18405b261ecSmrg	    prgnSrcClip = NotClippedByChildren (pSrcWin);
18505b261ecSmrg	    if ((RECT_IN_REGION(pscr, prgnSrcClip, &TsrcBox)) == rgnIN)
18605b261ecSmrg	    {
18705b261ecSmrg		REGION_DESTROY(pscr, prgnSrcClip);
18805b261ecSmrg		return NULL;
18905b261ecSmrg	    }
19005b261ecSmrg	}
19105b261ecSmrg 	else
19205b261ecSmrg 	{
19305b261ecSmrg	    if ((RECT_IN_REGION(pscr, &pSrcWin->clipList, &TsrcBox)) == rgnIN)
19405b261ecSmrg		return NULL;
19505b261ecSmrg	    prgnSrcClip = &rgnSrcRec;
19605b261ecSmrg	    REGION_NULL(pscr, prgnSrcClip);
19705b261ecSmrg	    REGION_COPY(pscr, prgnSrcClip, &pSrcWin->clipList);
19805b261ecSmrg	}
19905b261ecSmrg	REGION_TRANSLATE(pscr, prgnSrcClip,
20005b261ecSmrg				-pSrcDrawable->x, -pSrcDrawable->y);
20105b261ecSmrg    }
20205b261ecSmrg    else
20305b261ecSmrg    {
20405b261ecSmrg	BoxRec	box;
20505b261ecSmrg
20605b261ecSmrg	if ((srcBox.x1 >= 0) && (srcBox.y1 >= 0) &&
20705b261ecSmrg	    (srcBox.x2 <= pSrcDrawable->width) &&
20805b261ecSmrg 	    (srcBox.y2 <= pSrcDrawable->height))
20905b261ecSmrg	    return NULL;
21005b261ecSmrg
21105b261ecSmrg	box.x1 = 0;
21205b261ecSmrg	box.y1 = 0;
21305b261ecSmrg	box.x2 = pSrcDrawable->width;
21405b261ecSmrg	box.y2 = pSrcDrawable->height;
21505b261ecSmrg	prgnSrcClip = &rgnSrcRec;
21605b261ecSmrg	REGION_INIT(pscr, prgnSrcClip, &box, 1);
21705b261ecSmrg	pSrcWin = (WindowPtr)NULL;
21805b261ecSmrg    }
21905b261ecSmrg
22005b261ecSmrg    if (pDstDrawable == pSrcDrawable)
22105b261ecSmrg    {
22205b261ecSmrg	prgnDstClip = prgnSrcClip;
22305b261ecSmrg    }
22405b261ecSmrg    else if (pDstDrawable->type != DRAWABLE_PIXMAP)
22505b261ecSmrg    {
22605b261ecSmrg	if (pGC->subWindowMode == IncludeInferiors)
22705b261ecSmrg	{
22805b261ecSmrg	    prgnDstClip = NotClippedByChildren((WindowPtr)pDstDrawable);
22905b261ecSmrg	}
23005b261ecSmrg	else
23105b261ecSmrg	{
23205b261ecSmrg	    prgnDstClip = &rgnDstRec;
23305b261ecSmrg	    REGION_NULL(pscr, prgnDstClip);
23405b261ecSmrg	    REGION_COPY(pscr, prgnDstClip,
23505b261ecSmrg				&((WindowPtr)pDstDrawable)->clipList);
23605b261ecSmrg	}
23705b261ecSmrg	REGION_TRANSLATE(pscr, prgnDstClip,
23805b261ecSmrg				 -pDstDrawable->x, -pDstDrawable->y);
23905b261ecSmrg    }
24005b261ecSmrg    else
24105b261ecSmrg    {
24205b261ecSmrg	BoxRec	box;
24305b261ecSmrg
24405b261ecSmrg	box.x1 = 0;
24505b261ecSmrg	box.y1 = 0;
24605b261ecSmrg	box.x2 = pDstDrawable->width;
24705b261ecSmrg	box.y2 = pDstDrawable->height;
24805b261ecSmrg	prgnDstClip = &rgnDstRec;
24905b261ecSmrg	REGION_INIT(pscr, prgnDstClip, &box, 1);
25005b261ecSmrg    }
25105b261ecSmrg
25205b261ecSmrg    /* drawable-relative source region */
25305b261ecSmrg    REGION_INIT(pscr, &rgnExposed, &srcBox, 1);
25405b261ecSmrg
25505b261ecSmrg    /* now get the hidden parts of the source box*/
25605b261ecSmrg    REGION_SUBTRACT(pscr, &rgnExposed, &rgnExposed, prgnSrcClip);
25705b261ecSmrg
25805b261ecSmrg    if (pSrcWin && pSrcWin->backStorage)
25905b261ecSmrg    {
26005b261ecSmrg	/*
26105b261ecSmrg	 * Copy any areas from the source backing store. Modifies
26205b261ecSmrg	 * rgnExposed.
26305b261ecSmrg	 */
26405b261ecSmrg	(* pSrcWin->drawable.pScreen->ExposeCopy) ((WindowPtr)pSrcDrawable,
26505b261ecSmrg					      pDstDrawable,
26605b261ecSmrg					      pGC,
26705b261ecSmrg					      &rgnExposed,
26805b261ecSmrg					      srcx, srcy,
26905b261ecSmrg					      dstx, dsty,
27005b261ecSmrg					      plane);
27105b261ecSmrg    }
27205b261ecSmrg
27305b261ecSmrg    /* move them over the destination */
27405b261ecSmrg    REGION_TRANSLATE(pscr, &rgnExposed, dstx-srcx, dsty-srcy);
27505b261ecSmrg
27605b261ecSmrg    /* intersect with visible areas of dest */
27705b261ecSmrg    REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, prgnDstClip);
27805b261ecSmrg
27905b261ecSmrg    /*
28005b261ecSmrg     * If we have LOTS of rectangles, we decide to take the extents
28105b261ecSmrg     * and force an exposure on that.  This should require much less
28205b261ecSmrg     * work overall, on both client and server.  This is cheating, but
28305b261ecSmrg     * isn't prohibited by the protocol ("spontaneous combustion" :-)
28405b261ecSmrg     * for windows.
28505b261ecSmrg     */
28605b261ecSmrg    extents = pGC->graphicsExposures &&
28705b261ecSmrg	      (REGION_NUM_RECTS(&rgnExposed) > RECTLIMIT) &&
28805b261ecSmrg	      (pDstDrawable->type != DRAWABLE_PIXMAP);
28905b261ecSmrg#ifdef SHAPE
29005b261ecSmrg    if (pSrcWin)
29105b261ecSmrg    {
29205b261ecSmrg	RegionPtr	region;
29305b261ecSmrg    	if (!(region = wClipShape (pSrcWin)))
29405b261ecSmrg    	    region = wBoundingShape (pSrcWin);
29505b261ecSmrg    	/*
29605b261ecSmrg     	 * If you try to CopyArea the extents of a shaped window, compacting the
29705b261ecSmrg     	 * exposed region will undo all our work!
29805b261ecSmrg     	 */
29905b261ecSmrg    	if (extents && pSrcWin && region &&
30005b261ecSmrg    	    (RECT_IN_REGION(pscr, region, &srcBox) != rgnIN))
30105b261ecSmrg	    	extents = FALSE;
30205b261ecSmrg    }
30305b261ecSmrg#endif
30405b261ecSmrg    if (extents)
30505b261ecSmrg    {
30605b261ecSmrg	WindowPtr pWin = (WindowPtr)pDstDrawable;
30705b261ecSmrg
30805b261ecSmrg	expBox = *REGION_EXTENTS(pscr, &rgnExposed);
30905b261ecSmrg	REGION_RESET(pscr, &rgnExposed, &expBox);
31005b261ecSmrg	/* need to clear out new areas of backing store */
31105b261ecSmrg	if (pWin->backStorage)
31205b261ecSmrg	    (void) (* pWin->drawable.pScreen->ClearBackingStore)(
31305b261ecSmrg					 pWin,
31405b261ecSmrg					 expBox.x1,
31505b261ecSmrg					 expBox.y1,
31605b261ecSmrg					 expBox.x2 - expBox.x1,
31705b261ecSmrg					 expBox.y2 - expBox.y1,
31805b261ecSmrg					 FALSE);
31905b261ecSmrg    }
32005b261ecSmrg    if ((pDstDrawable->type != DRAWABLE_PIXMAP) &&
32105b261ecSmrg	(((WindowPtr)pDstDrawable)->backgroundState != None))
32205b261ecSmrg    {
32305b261ecSmrg	WindowPtr pWin = (WindowPtr)pDstDrawable;
32405b261ecSmrg
32505b261ecSmrg	/* make the exposed area screen-relative */
32605b261ecSmrg	REGION_TRANSLATE(pscr, &rgnExposed,
32705b261ecSmrg				 pDstDrawable->x, pDstDrawable->y);
32805b261ecSmrg
32905b261ecSmrg	if (extents)
33005b261ecSmrg	{
33105b261ecSmrg	    /* PaintWindowBackground doesn't clip, so we have to */
33205b261ecSmrg	    REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, &pWin->clipList);
33305b261ecSmrg	}
33405b261ecSmrg	(*pWin->drawable.pScreen->PaintWindowBackground)(
33505b261ecSmrg			(WindowPtr)pDstDrawable, &rgnExposed, PW_BACKGROUND);
33605b261ecSmrg
33705b261ecSmrg	if (extents)
33805b261ecSmrg	{
33905b261ecSmrg	    REGION_RESET(pscr, &rgnExposed, &expBox);
34005b261ecSmrg	}
34105b261ecSmrg	else
34205b261ecSmrg	    REGION_TRANSLATE(pscr, &rgnExposed,
34305b261ecSmrg				     -pDstDrawable->x, -pDstDrawable->y);
34405b261ecSmrg    }
34505b261ecSmrg    if (prgnDstClip == &rgnDstRec)
34605b261ecSmrg    {
34705b261ecSmrg	REGION_UNINIT(pscr, prgnDstClip);
34805b261ecSmrg    }
34905b261ecSmrg    else if (prgnDstClip != prgnSrcClip)
35005b261ecSmrg    {
35105b261ecSmrg	REGION_DESTROY(pscr, prgnDstClip);
35205b261ecSmrg    }
35305b261ecSmrg
35405b261ecSmrg    if (prgnSrcClip == &rgnSrcRec)
35505b261ecSmrg    {
35605b261ecSmrg	REGION_UNINIT(pscr, prgnSrcClip);
35705b261ecSmrg    }
35805b261ecSmrg    else
35905b261ecSmrg    {
36005b261ecSmrg	REGION_DESTROY(pscr, prgnSrcClip);
36105b261ecSmrg    }
36205b261ecSmrg
36305b261ecSmrg    if (pGC->graphicsExposures)
36405b261ecSmrg    {
36505b261ecSmrg	/* don't look */
36605b261ecSmrg	RegionPtr exposed = REGION_CREATE(pscr, NullBox, 0);
36705b261ecSmrg	*exposed = rgnExposed;
36805b261ecSmrg	return exposed;
36905b261ecSmrg    }
37005b261ecSmrg    else
37105b261ecSmrg    {
37205b261ecSmrg	REGION_UNINIT(pscr, &rgnExposed);
37305b261ecSmrg	return NULL;
37405b261ecSmrg    }
37505b261ecSmrg}
37605b261ecSmrg
37705b261ecSmrg/* send GraphicsExpose events, or a NoExpose event, based on the region */
37805b261ecSmrg
37905b261ecSmrg_X_EXPORT void
38005b261ecSmrgmiSendGraphicsExpose (client, pRgn, drawable, major, minor)
38105b261ecSmrg    ClientPtr	client;
38205b261ecSmrg    RegionPtr	pRgn;
38305b261ecSmrg    XID		drawable;
38405b261ecSmrg    int	major;
38505b261ecSmrg    int	minor;
38605b261ecSmrg{
38705b261ecSmrg    if (pRgn && !REGION_NIL(pRgn))
38805b261ecSmrg    {
38905b261ecSmrg        xEvent *pEvent;
39005b261ecSmrg	xEvent *pe;
39105b261ecSmrg	BoxPtr pBox;
39205b261ecSmrg	int i;
39305b261ecSmrg	int numRects;
39405b261ecSmrg
39505b261ecSmrg	numRects = REGION_NUM_RECTS(pRgn);
39605b261ecSmrg	pBox = REGION_RECTS(pRgn);
39705b261ecSmrg	if(!(pEvent = (xEvent *)ALLOCATE_LOCAL(numRects * sizeof(xEvent))))
39805b261ecSmrg		return;
39905b261ecSmrg	pe = pEvent;
40005b261ecSmrg
40105b261ecSmrg	for (i=1; i<=numRects; i++, pe++, pBox++)
40205b261ecSmrg	{
40305b261ecSmrg	    pe->u.u.type = GraphicsExpose;
40405b261ecSmrg	    pe->u.graphicsExposure.drawable = drawable;
40505b261ecSmrg	    pe->u.graphicsExposure.x = pBox->x1;
40605b261ecSmrg	    pe->u.graphicsExposure.y = pBox->y1;
40705b261ecSmrg	    pe->u.graphicsExposure.width = pBox->x2 - pBox->x1;
40805b261ecSmrg	    pe->u.graphicsExposure.height = pBox->y2 - pBox->y1;
40905b261ecSmrg	    pe->u.graphicsExposure.count = numRects - i;
41005b261ecSmrg	    pe->u.graphicsExposure.majorEvent = major;
41105b261ecSmrg	    pe->u.graphicsExposure.minorEvent = minor;
41205b261ecSmrg	}
41305b261ecSmrg	TryClientEvents(client, pEvent, numRects,
41405b261ecSmrg			    (Mask)0, NoEventMask, NullGrab);
41505b261ecSmrg	DEALLOCATE_LOCAL(pEvent);
41605b261ecSmrg    }
41705b261ecSmrg    else
41805b261ecSmrg    {
41905b261ecSmrg        xEvent event;
42005b261ecSmrg	event.u.u.type = NoExpose;
42105b261ecSmrg	event.u.noExposure.drawable = drawable;
42205b261ecSmrg	event.u.noExposure.majorEvent = major;
42305b261ecSmrg	event.u.noExposure.minorEvent = minor;
42405b261ecSmrg	TryClientEvents(client, &event, 1,
42505b261ecSmrg	    (Mask)0, NoEventMask, NullGrab);
42605b261ecSmrg    }
42705b261ecSmrg}
42805b261ecSmrg
42905b261ecSmrg
43005b261ecSmrgvoid
43105b261ecSmrgmiSendExposures(pWin, pRgn, dx, dy)
43205b261ecSmrg    WindowPtr pWin;
43305b261ecSmrg    RegionPtr pRgn;
43405b261ecSmrg    int dx, dy;
43505b261ecSmrg{
43605b261ecSmrg    BoxPtr pBox;
43705b261ecSmrg    int numRects;
43805b261ecSmrg    xEvent *pEvent, *pe;
43905b261ecSmrg    int i;
44005b261ecSmrg
44105b261ecSmrg    pBox = REGION_RECTS(pRgn);
44205b261ecSmrg    numRects = REGION_NUM_RECTS(pRgn);
44305b261ecSmrg    if(!(pEvent = (xEvent *) ALLOCATE_LOCAL(numRects * sizeof(xEvent))))
44405b261ecSmrg	return;
44505b261ecSmrg
44605b261ecSmrg    for (i=numRects, pe = pEvent; --i >= 0; pe++, pBox++)
44705b261ecSmrg    {
44805b261ecSmrg	pe->u.u.type = Expose;
44905b261ecSmrg	pe->u.expose.window = pWin->drawable.id;
45005b261ecSmrg	pe->u.expose.x = pBox->x1 - dx;
45105b261ecSmrg	pe->u.expose.y = pBox->y1 - dy;
45205b261ecSmrg	pe->u.expose.width = pBox->x2 - pBox->x1;
45305b261ecSmrg	pe->u.expose.height = pBox->y2 - pBox->y1;
45405b261ecSmrg	pe->u.expose.count = i;
45505b261ecSmrg    }
45605b261ecSmrg
45705b261ecSmrg#ifdef PANORAMIX
45805b261ecSmrg    if(!noPanoramiXExtension) {
45905b261ecSmrg	int scrnum = pWin->drawable.pScreen->myNum;
46005b261ecSmrg	int x = 0, y = 0;
46105b261ecSmrg	XID realWin = 0;
46205b261ecSmrg
46305b261ecSmrg	if(!pWin->parent) {
46405b261ecSmrg	    x = panoramiXdataPtr[scrnum].x;
46505b261ecSmrg	    y = panoramiXdataPtr[scrnum].y;
46605b261ecSmrg	    pWin = WindowTable[0];
46705b261ecSmrg	    realWin = pWin->drawable.id;
46805b261ecSmrg	} else if (scrnum) {
46905b261ecSmrg	    PanoramiXRes *win;
47005b261ecSmrg	    win = PanoramiXFindIDByScrnum(XRT_WINDOW,
47105b261ecSmrg			pWin->drawable.id, scrnum);
47205b261ecSmrg	    if(!win) {
47305b261ecSmrg		DEALLOCATE_LOCAL(pEvent);
47405b261ecSmrg		return;
47505b261ecSmrg	    }
47605b261ecSmrg	    realWin = win->info[0].id;
47705b261ecSmrg	    pWin = LookupIDByType(realWin, RT_WINDOW);
47805b261ecSmrg	}
47905b261ecSmrg	if(x || y || scrnum)
48005b261ecSmrg	  for (i = 0; i < numRects; i++) {
48105b261ecSmrg	      pEvent[i].u.expose.window = realWin;
48205b261ecSmrg	      pEvent[i].u.expose.x += x;
48305b261ecSmrg	      pEvent[i].u.expose.y += y;
48405b261ecSmrg	  }
48505b261ecSmrg    }
48605b261ecSmrg#endif
48705b261ecSmrg
48805b261ecSmrg    DeliverEvents(pWin, pEvent, numRects, NullWindow);
48905b261ecSmrg
49005b261ecSmrg    DEALLOCATE_LOCAL(pEvent);
49105b261ecSmrg}
49205b261ecSmrg
49305b261ecSmrg_X_EXPORT void
49405b261ecSmrgmiWindowExposures(pWin, prgn, other_exposed)
49505b261ecSmrg    WindowPtr pWin;
49605b261ecSmrg    RegionPtr prgn, other_exposed;
49705b261ecSmrg{
49805b261ecSmrg    RegionPtr   exposures = prgn;
49905b261ecSmrg    if (pWin->backStorage && prgn)
50005b261ecSmrg	/*
50105b261ecSmrg	 * in some cases, backing store will cause a different
50205b261ecSmrg	 * region to be exposed than needs to be repainted
50305b261ecSmrg	 * (like when a window is mapped).  RestoreAreas is
50405b261ecSmrg	 * allowed to return a region other than prgn,
50505b261ecSmrg	 * in which case this routine will free the resultant
50605b261ecSmrg	 * region.  If exposures is null, then no events will
50705b261ecSmrg	 * be sent to the client; if prgn is empty
50805b261ecSmrg	 * no areas will be repainted.
50905b261ecSmrg	 */
51005b261ecSmrg	exposures = (*pWin->drawable.pScreen->RestoreAreas)(pWin, prgn);
51105b261ecSmrg    if ((prgn && !REGION_NIL(prgn)) ||
51205b261ecSmrg	(exposures && !REGION_NIL(exposures)) || other_exposed)
51305b261ecSmrg    {
51405b261ecSmrg	RegionRec   expRec;
51505b261ecSmrg	int	    clientInterested;
51605b261ecSmrg
51705b261ecSmrg	/*
51805b261ecSmrg	 * Restore from backing-store FIRST.
51905b261ecSmrg	 */
52005b261ecSmrg	clientInterested = (pWin->eventMask|wOtherEventMasks(pWin)) & ExposureMask;
52105b261ecSmrg	if (other_exposed)
52205b261ecSmrg	{
52305b261ecSmrg	    if (exposures)
52405b261ecSmrg	    {
52505b261ecSmrg		REGION_UNION(pWin->drawable.pScreen, other_exposed,
52605b261ecSmrg						  exposures,
52705b261ecSmrg					          other_exposed);
52805b261ecSmrg		if (exposures != prgn)
52905b261ecSmrg		    REGION_DESTROY(pWin->drawable.pScreen, exposures);
53005b261ecSmrg	    }
53105b261ecSmrg	    exposures = other_exposed;
53205b261ecSmrg	}
53305b261ecSmrg	if (clientInterested && exposures && (REGION_NUM_RECTS(exposures) > RECTLIMIT))
53405b261ecSmrg	{
53505b261ecSmrg	    /*
53605b261ecSmrg	     * If we have LOTS of rectangles, we decide to take the extents
53705b261ecSmrg	     * and force an exposure on that.  This should require much less
53805b261ecSmrg	     * work overall, on both client and server.  This is cheating, but
53905b261ecSmrg	     * isn't prohibited by the protocol ("spontaneous combustion" :-).
54005b261ecSmrg	     */
54105b261ecSmrg	    BoxRec box;
54205b261ecSmrg
54305b261ecSmrg	    box = *REGION_EXTENTS( pWin->drawable.pScreen, exposures);
54405b261ecSmrg	    if (exposures == prgn) {
54505b261ecSmrg		exposures = &expRec;
54605b261ecSmrg		REGION_INIT( pWin->drawable.pScreen, exposures, &box, 1);
54705b261ecSmrg		REGION_RESET( pWin->drawable.pScreen, prgn, &box);
54805b261ecSmrg	    } else {
54905b261ecSmrg		REGION_RESET( pWin->drawable.pScreen, exposures, &box);
55005b261ecSmrg		REGION_UNION( pWin->drawable.pScreen, prgn, prgn, exposures);
55105b261ecSmrg	    }
55205b261ecSmrg	    /* PaintWindowBackground doesn't clip, so we have to */
55305b261ecSmrg	    REGION_INTERSECT( pWin->drawable.pScreen, prgn, prgn, &pWin->clipList);
55405b261ecSmrg	    /* need to clear out new areas of backing store, too */
55505b261ecSmrg	    if (pWin->backStorage)
55605b261ecSmrg		(void) (* pWin->drawable.pScreen->ClearBackingStore)(
55705b261ecSmrg					     pWin,
55805b261ecSmrg					     box.x1 - pWin->drawable.x,
55905b261ecSmrg					     box.y1 - pWin->drawable.y,
56005b261ecSmrg					     box.x2 - box.x1,
56105b261ecSmrg					     box.y2 - box.y1,
56205b261ecSmrg					     FALSE);
56305b261ecSmrg	}
56405b261ecSmrg	if (prgn && !REGION_NIL(prgn))
56505b261ecSmrg	    (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, prgn, PW_BACKGROUND);
56605b261ecSmrg	if (clientInterested && exposures && !REGION_NIL(exposures))
56705b261ecSmrg	    miSendExposures(pWin, exposures,
56805b261ecSmrg			    pWin->drawable.x, pWin->drawable.y);
56905b261ecSmrg	if (exposures == &expRec)
57005b261ecSmrg	{
57105b261ecSmrg	    REGION_UNINIT( pWin->drawable.pScreen, exposures);
57205b261ecSmrg	}
57305b261ecSmrg	else if (exposures && exposures != prgn && exposures != other_exposed)
57405b261ecSmrg	    REGION_DESTROY( pWin->drawable.pScreen, exposures);
57505b261ecSmrg	if (prgn)
57605b261ecSmrg	    REGION_EMPTY( pWin->drawable.pScreen, prgn);
57705b261ecSmrg    }
57805b261ecSmrg    else if (exposures && exposures != prgn)
57905b261ecSmrg	REGION_DESTROY( pWin->drawable.pScreen, exposures);
58005b261ecSmrg}
58105b261ecSmrg
58205b261ecSmrg
58305b261ecSmrg/*
58405b261ecSmrg    this code is highly unlikely.  it is not haile selassie.
58505b261ecSmrg
58605b261ecSmrg    there is some hair here.  we can't just use the window's
58705b261ecSmrgclip region as it is, because if we are painting the border,
58805b261ecSmrgthe border is not in the client area and so we will be excluded
58905b261ecSmrgwhen we validate the GC, and if we are painting a parent-relative
59005b261ecSmrgbackground, the area we want to paint is in some other window.
59105b261ecSmrgsince we trust the code calling us to tell us to paint only areas
59205b261ecSmrgthat are really ours, we will temporarily give the window a
59305b261ecSmrgclipList the size of the whole screen and an origin at (0,0).
59405b261ecSmrgthis more or less assumes that ddX code will do translation
59505b261ecSmrgbased on the window's absolute position, and that ValidateGC will
59605b261ecSmrglook at clipList, and that no other fields from the
59705b261ecSmrgwindow will be used.  it's not possible to just draw
59805b261ecSmrgin the root because it may be a different depth.
59905b261ecSmrg
60005b261ecSmrgto get the tile to align correctly we set the GC's tile origin to
60105b261ecSmrgbe the (x,y) of the window's upper left corner, after which we
60205b261ecSmrgget the right bits when drawing into the root.
60305b261ecSmrg
60405b261ecSmrgbecause the clip_mask is being set to None, we may call DoChangeGC with
60505b261ecSmrgfPointer set true, thus we no longer need to install the background or
60605b261ecSmrgborder tile in the resource table.
60705b261ecSmrg*/
60805b261ecSmrg
60905b261ecSmrgstatic RESTYPE ResType = 0;
61005b261ecSmrgstatic int numGCs = 0;
61105b261ecSmrgstatic GCPtr	screenContext[MAXSCREENS];
61205b261ecSmrg
61305b261ecSmrg/*ARGSUSED*/
61405b261ecSmrgstatic int
61505b261ecSmrgtossGC (
61605b261ecSmrg    pointer value,
61705b261ecSmrg    XID id)
61805b261ecSmrg{
61905b261ecSmrg    GCPtr pGC = (GCPtr)value;
62005b261ecSmrg    screenContext[pGC->pScreen->myNum] = (GCPtr)NULL;
62105b261ecSmrg    FreeGC (pGC, id);
62205b261ecSmrg    numGCs--;
62305b261ecSmrg    if (!numGCs)
62405b261ecSmrg	ResType = 0;
62505b261ecSmrg
62605b261ecSmrg    return 0;
62705b261ecSmrg}
62805b261ecSmrg
62905b261ecSmrg
63005b261ecSmrg_X_EXPORT void
63105b261ecSmrgmiPaintWindow(pWin, prgn, what)
63205b261ecSmrgWindowPtr pWin;
63305b261ecSmrgRegionPtr prgn;
63405b261ecSmrgint what;
63505b261ecSmrg{
63605b261ecSmrg    int	status;
63705b261ecSmrg
63805b261ecSmrg    Bool usingScratchGC = FALSE;
63905b261ecSmrg    WindowPtr pRoot;
64005b261ecSmrg
64105b261ecSmrg#define FUNCTION	0
64205b261ecSmrg#define FOREGROUND	1
64305b261ecSmrg#define TILE		2
64405b261ecSmrg#define FILLSTYLE	3
64505b261ecSmrg#define ABSX		4
64605b261ecSmrg#define ABSY		5
64705b261ecSmrg#define CLIPMASK	6
64805b261ecSmrg#define SUBWINDOW	7
64905b261ecSmrg#define COUNT_BITS	8
65005b261ecSmrg
65105b261ecSmrg    ChangeGCVal gcval[7];
65205b261ecSmrg    ChangeGCVal newValues [COUNT_BITS];
65305b261ecSmrg
65405b261ecSmrg    BITS32 gcmask, index, mask;
65505b261ecSmrg    RegionRec prgnWin;
65605b261ecSmrg    DDXPointRec oldCorner;
65705b261ecSmrg    BoxRec box;
65805b261ecSmrg    WindowPtr	pBgWin;
65905b261ecSmrg    GCPtr pGC;
66005b261ecSmrg    int i;
66105b261ecSmrg    BoxPtr pbox;
66205b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
66305b261ecSmrg    xRectangle *prect;
66405b261ecSmrg    int numRects;
66505b261ecSmrg
66605b261ecSmrg    gcmask = 0;
66705b261ecSmrg
66805b261ecSmrg    if (what == PW_BACKGROUND)
66905b261ecSmrg    {
67005b261ecSmrg	switch (pWin->backgroundState) {
67105b261ecSmrg	case None:
67205b261ecSmrg	    return;
67305b261ecSmrg	case ParentRelative:
67405b261ecSmrg	    (*pWin->parent->drawable.pScreen->PaintWindowBackground)(pWin->parent, prgn, what);
67505b261ecSmrg	    return;
67605b261ecSmrg	case BackgroundPixel:
67705b261ecSmrg	    newValues[FOREGROUND].val = pWin->background.pixel;
67805b261ecSmrg	    newValues[FILLSTYLE].val  = FillSolid;
67905b261ecSmrg	    gcmask |= GCForeground | GCFillStyle;
68005b261ecSmrg	    break;
68105b261ecSmrg	case BackgroundPixmap:
68205b261ecSmrg	    newValues[TILE].ptr = (pointer)pWin->background.pixmap;
68305b261ecSmrg	    newValues[FILLSTYLE].val = FillTiled;
68405b261ecSmrg	    gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin;
68505b261ecSmrg	    break;
68605b261ecSmrg	}
68705b261ecSmrg    }
68805b261ecSmrg    else
68905b261ecSmrg    {
69005b261ecSmrg	if (pWin->borderIsPixel)
69105b261ecSmrg	{
69205b261ecSmrg	    newValues[FOREGROUND].val = pWin->border.pixel;
69305b261ecSmrg	    newValues[FILLSTYLE].val  = FillSolid;
69405b261ecSmrg	    gcmask |= GCForeground | GCFillStyle;
69505b261ecSmrg	}
69605b261ecSmrg	else
69705b261ecSmrg	{
69805b261ecSmrg	    newValues[TILE].ptr = (pointer)pWin->border.pixmap;
69905b261ecSmrg	    newValues[FILLSTYLE].val = FillTiled;
70005b261ecSmrg	    gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin;
70105b261ecSmrg	}
70205b261ecSmrg    }
70305b261ecSmrg
70405b261ecSmrg    prect = (xRectangle *)ALLOCATE_LOCAL(REGION_NUM_RECTS(prgn) *
70505b261ecSmrg					 sizeof(xRectangle));
70605b261ecSmrg    if (!prect)
70705b261ecSmrg	return;
70805b261ecSmrg
70905b261ecSmrg    newValues[FUNCTION].val = GXcopy;
71005b261ecSmrg    gcmask |= GCFunction | GCClipMask;
71105b261ecSmrg
71205b261ecSmrg    i = pScreen->myNum;
71305b261ecSmrg    pRoot = WindowTable[i];
71405b261ecSmrg
71505b261ecSmrg    pBgWin = pWin;
71605b261ecSmrg    if (what == PW_BORDER)
71705b261ecSmrg    {
71805b261ecSmrg	while (pBgWin->backgroundState == ParentRelative)
71905b261ecSmrg	    pBgWin = pBgWin->parent;
72005b261ecSmrg    }
72105b261ecSmrg
72205b261ecSmrg    if ((pWin->drawable.depth != pRoot->drawable.depth) ||
72305b261ecSmrg	(pWin->drawable.bitsPerPixel != pRoot->drawable.bitsPerPixel))
72405b261ecSmrg    {
72505b261ecSmrg	usingScratchGC = TRUE;
72605b261ecSmrg	pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen);
72705b261ecSmrg	if (!pGC)
72805b261ecSmrg	{
72905b261ecSmrg	    DEALLOCATE_LOCAL(prect);
73005b261ecSmrg	    return;
73105b261ecSmrg	}
73205b261ecSmrg	/*
73305b261ecSmrg	 * mash the clip list so we can paint the border by
73405b261ecSmrg	 * mangling the window in place, pretending it
73505b261ecSmrg	 * spans the entire screen
73605b261ecSmrg	 */
73705b261ecSmrg	if (what == PW_BORDER)
73805b261ecSmrg	{
73905b261ecSmrg	    prgnWin = pWin->clipList;
74005b261ecSmrg	    oldCorner.x = pWin->drawable.x;
74105b261ecSmrg	    oldCorner.y = pWin->drawable.y;
74205b261ecSmrg	    pWin->drawable.x = pWin->drawable.y = 0;
74305b261ecSmrg	    box.x1 = 0;
74405b261ecSmrg	    box.y1 = 0;
74505b261ecSmrg	    box.x2 = pScreen->width;
74605b261ecSmrg	    box.y2 = pScreen->height;
74705b261ecSmrg	    REGION_INIT(pScreen, &pWin->clipList, &box, 1);
74805b261ecSmrg	    pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
74905b261ecSmrg	    newValues[ABSX].val = pBgWin->drawable.x;
75005b261ecSmrg	    newValues[ABSY].val = pBgWin->drawable.y;
75105b261ecSmrg	}
75205b261ecSmrg	else
75305b261ecSmrg	{
75405b261ecSmrg	    newValues[ABSX].val = 0;
75505b261ecSmrg	    newValues[ABSY].val = 0;
75605b261ecSmrg	}
75705b261ecSmrg    } else {
75805b261ecSmrg	/*
75905b261ecSmrg	 * draw the background to the root window
76005b261ecSmrg	 */
76105b261ecSmrg	if (screenContext[i] == (GCPtr)NULL)
76205b261ecSmrg	{
76305b261ecSmrg	    if (!ResType && !(ResType = CreateNewResourceType(tossGC)))
76405b261ecSmrg		return;
76505b261ecSmrg	    screenContext[i] = CreateGC((DrawablePtr)pWin, (BITS32) 0,
76605b261ecSmrg					(XID *)NULL, &status);
76705b261ecSmrg	    if (!screenContext[i])
76805b261ecSmrg		return;
76905b261ecSmrg	    numGCs++;
77005b261ecSmrg	    if (!AddResource(FakeClientID(0), ResType,
77105b261ecSmrg			     (pointer)screenContext[i]))
77205b261ecSmrg	        return;
77305b261ecSmrg	}
77405b261ecSmrg	pGC = screenContext[i];
77505b261ecSmrg	newValues[SUBWINDOW].val = IncludeInferiors;
77605b261ecSmrg	newValues[ABSX].val = pBgWin->drawable.x;
77705b261ecSmrg	newValues[ABSY].val = pBgWin->drawable.y;
77805b261ecSmrg	gcmask |= GCSubwindowMode;
77905b261ecSmrg	pWin = pRoot;
78005b261ecSmrg    }
78105b261ecSmrg
78205b261ecSmrg    if (pWin->backStorage)
78305b261ecSmrg	(*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack);
78405b261ecSmrg
78505b261ecSmrg    mask = gcmask;
78605b261ecSmrg    gcmask = 0;
78705b261ecSmrg    i = 0;
78805b261ecSmrg    while (mask) {
78905b261ecSmrg    	index = lowbit (mask);
79005b261ecSmrg	mask &= ~index;
79105b261ecSmrg	switch (index) {
79205b261ecSmrg	case GCFunction:
79305b261ecSmrg	    if (pGC->alu != newValues[FUNCTION].val) {
79405b261ecSmrg		gcmask |= index;
79505b261ecSmrg		gcval[i++].val = newValues[FUNCTION].val;
79605b261ecSmrg	    }
79705b261ecSmrg	    break;
79805b261ecSmrg	case GCTileStipXOrigin:
79905b261ecSmrg	    if ( pGC->patOrg.x != newValues[ABSX].val) {
80005b261ecSmrg		gcmask |= index;
80105b261ecSmrg		gcval[i++].val = newValues[ABSX].val;
80205b261ecSmrg	    }
80305b261ecSmrg	    break;
80405b261ecSmrg	case GCTileStipYOrigin:
80505b261ecSmrg	    if ( pGC->patOrg.y != newValues[ABSY].val) {
80605b261ecSmrg		gcmask |= index;
80705b261ecSmrg		gcval[i++].val = newValues[ABSY].val;
80805b261ecSmrg	    }
80905b261ecSmrg	    break;
81005b261ecSmrg	case GCClipMask:
81105b261ecSmrg	    if ( pGC->clientClipType != CT_NONE) {
81205b261ecSmrg		gcmask |= index;
81305b261ecSmrg		gcval[i++].val = CT_NONE;
81405b261ecSmrg	    }
81505b261ecSmrg	    break;
81605b261ecSmrg	case GCSubwindowMode:
81705b261ecSmrg	    if ( pGC->subWindowMode != newValues[SUBWINDOW].val) {
81805b261ecSmrg		gcmask |= index;
81905b261ecSmrg		gcval[i++].val = newValues[SUBWINDOW].val;
82005b261ecSmrg	    }
82105b261ecSmrg	    break;
82205b261ecSmrg	case GCTile:
82305b261ecSmrg	    if (pGC->tileIsPixel || pGC->tile.pixmap != newValues[TILE].ptr)
82405b261ecSmrg 	    {
82505b261ecSmrg		gcmask |= index;
82605b261ecSmrg		gcval[i++].ptr = newValues[TILE].ptr;
82705b261ecSmrg	    }
82805b261ecSmrg	    break;
82905b261ecSmrg	case GCFillStyle:
83005b261ecSmrg	    if ( pGC->fillStyle != newValues[FILLSTYLE].val) {
83105b261ecSmrg		gcmask |= index;
83205b261ecSmrg		gcval[i++].val = newValues[FILLSTYLE].val;
83305b261ecSmrg	    }
83405b261ecSmrg	    break;
83505b261ecSmrg	case GCForeground:
83605b261ecSmrg	    if ( pGC->fgPixel != newValues[FOREGROUND].val) {
83705b261ecSmrg		gcmask |= index;
83805b261ecSmrg		gcval[i++].val = newValues[FOREGROUND].val;
83905b261ecSmrg	    }
84005b261ecSmrg	    break;
84105b261ecSmrg	}
84205b261ecSmrg    }
84305b261ecSmrg
84405b261ecSmrg    if (gcmask)
84505b261ecSmrg        dixChangeGC(NullClient, pGC, gcmask, NULL, gcval);
84605b261ecSmrg
84705b261ecSmrg    if (pWin->drawable.serialNumber != pGC->serialNumber)
84805b261ecSmrg	ValidateGC((DrawablePtr)pWin, pGC);
84905b261ecSmrg
85005b261ecSmrg    numRects = REGION_NUM_RECTS(prgn);
85105b261ecSmrg    pbox = REGION_RECTS(prgn);
85205b261ecSmrg    for (i= numRects; --i >= 0; pbox++, prect++)
85305b261ecSmrg    {
85405b261ecSmrg	prect->x = pbox->x1 - pWin->drawable.x;
85505b261ecSmrg	prect->y = pbox->y1 - pWin->drawable.y;
85605b261ecSmrg	prect->width = pbox->x2 - pbox->x1;
85705b261ecSmrg	prect->height = pbox->y2 - pbox->y1;
85805b261ecSmrg    }
85905b261ecSmrg    prect -= numRects;
86005b261ecSmrg    (*pGC->ops->PolyFillRect)((DrawablePtr)pWin, pGC, numRects, prect);
86105b261ecSmrg    DEALLOCATE_LOCAL(prect);
86205b261ecSmrg
86305b261ecSmrg    if (pWin->backStorage)
86405b261ecSmrg	(*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeNothing);
86505b261ecSmrg
86605b261ecSmrg    if (usingScratchGC)
86705b261ecSmrg    {
86805b261ecSmrg	if (what == PW_BORDER)
86905b261ecSmrg	{
87005b261ecSmrg	    REGION_UNINIT(pScreen, &pWin->clipList);
87105b261ecSmrg	    pWin->clipList = prgnWin;
87205b261ecSmrg	    pWin->drawable.x = oldCorner.x;
87305b261ecSmrg	    pWin->drawable.y = oldCorner.y;
87405b261ecSmrg	    pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
87505b261ecSmrg	}
87605b261ecSmrg	FreeScratchGC(pGC);
87705b261ecSmrg    }
87805b261ecSmrg}
87905b261ecSmrg
88005b261ecSmrg
88105b261ecSmrg/* MICLEARDRAWABLE -- sets the entire drawable to the background color of
88205b261ecSmrg * the GC.  Useful when we have a scratch drawable and need to initialize
88305b261ecSmrg * it. */
88405b261ecSmrg_X_EXPORT void
88505b261ecSmrgmiClearDrawable(pDraw, pGC)
88605b261ecSmrg    DrawablePtr	pDraw;
88705b261ecSmrg    GCPtr	pGC;
88805b261ecSmrg{
88905b261ecSmrg    XID fg = pGC->fgPixel;
89005b261ecSmrg    XID bg = pGC->bgPixel;
89105b261ecSmrg    xRectangle rect;
89205b261ecSmrg
89305b261ecSmrg    rect.x = 0;
89405b261ecSmrg    rect.y = 0;
89505b261ecSmrg    rect.width = pDraw->width;
89605b261ecSmrg    rect.height = pDraw->height;
89705b261ecSmrg    DoChangeGC(pGC, GCForeground, &bg, 0);
89805b261ecSmrg    ValidateGC(pDraw, pGC);
89905b261ecSmrg    (*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect);
90005b261ecSmrg    DoChangeGC(pGC, GCForeground, &fg, 0);
90105b261ecSmrg    ValidateGC(pDraw, pGC);
90205b261ecSmrg}
903