#include "X.h"
#include "Xmd.h"

#include "misc.h"
#include "windowstr.h"
#include "pixmapstr.h"
#include "gcstruct.h"
#include "regionstr.h"
#include "svga.h"
#include "../../mi/mi.h"
#include "../../../os/msdos/msdos.h"
#include "svgafuncs.h"
#include "mxfuncs.h"

/* Cheap hack:  I know there's only one visual, so I can use one GC for
 * everything. */
static GCPtr myGC = 0;
extern WindowPtr WindowTable[];

void
mxPaintWindow(pWin, prgn, what)
WindowPtr pWin;
RegionPtr prgn;
int what;
{
    RegBoxPtr pbox;
    int i;
    int nrectFill, maxheight;
    DDXPointPtr		pptFirst;
    int	*pwFirst, *pw;
    DDXPointPtr ppt;
    int height, width, xorg, yorg;

    pbox = REGION_RECTS(prgn);
    nrectFill = REGION_NUM_RECTS(prgn);
    if (!nrectFill)
	return;

    if (myGC == 0) {
	myGC = CreateGC((DrawablePtr)WindowTable[0],
		(BITS32)0, (XID *)0, &width);
	if (myGC == 0)
		return;
	myGC->subWindowMode = IncludeInferiors;
	myGC->stateChanges = GCFillStyle | GCSubwindowMode;
    }
    if (what == PW_BACKGROUND) {
	switch (pWin->backgroundState) {
	    case None:
		return;
	    case ParentRelative:
		mxPaintWindow(pWin->parent, prgn, what);
		return;
	    case BackgroundPixel:
		if (myGC->fgPixel != pWin->background.pixel) {
		    myGC->fgPixel = pWin->background.pixel;
		    myGC->stateChanges |= GCForeground;
		}
		if (myGC->fillStyle != FillSolid) {
		    myGC->fillStyle = FillSolid;
		    myGC->stateChanges |= GCFillStyle;
		}
		break;
	    case BackgroundPixmap:
		if (pWin->mxBackground) {
		    PixmapPtr pPixmap = pWin->mxBackground;

		    xorg = pWin->drawable.x;
		    yorg = pWin->drawable.y;
		    /* take shortcut */
		    do {
			svgaFillRect(pPixmap, xorg, yorg, *pbox);
			pbox++;
		    } while (--nrectFill);
		    return;
		} else
		{
		    if (myGC->tile.pixmap != pWin->background.pixmap) {
			myGC->tile.pixmap = pWin->background.pixmap;
			myGC->stateChanges |= GCTile;
		    }
		    if (myGC->fillStyle != FillTiled) {
			myGC->fillStyle = FillTiled;
			myGC->stateChanges |= GCFillStyle;
		    }
		}
		break;
	}
    } else {
	if (pWin->borderIsPixel) {
		if (myGC->fgPixel != pWin->border.pixel) {
		    myGC->fgPixel = pWin->border.pixel;
		    myGC->stateChanges |= GCForeground;
		}
		if (myGC->fillStyle != FillSolid) {
		    myGC->fillStyle = FillSolid;
		    myGC->stateChanges |= GCFillStyle;
		}
	} else {
		if (myGC->tile.pixmap != pWin->border.pixmap) {
		    myGC->tile.pixmap = pWin->border.pixmap;
		    myGC->stateChanges |= GCTile;
		}
		if (myGC->fillStyle != FillTiled) {
		    myGC->fillStyle = FillTiled;
		    myGC->stateChanges |= GCFillStyle;
		}
	}
    }
    myGC->patOrg.x = pWin->drawable.x;
    myGC->patOrg.y = pWin->drawable.y;

    maxheight = pbox->y2 - pbox->y1;
    height = nrectFill;
    while (--height) {
	pbox++;
	maxheight = max(maxheight, pbox->y2 - pbox->y1);
    }
    pptFirst = (DDXPointPtr) ALLOCATE_LOCAL(maxheight * sizeof(DDXPointRec));
    pwFirst = (int *) ALLOCATE_LOCAL(maxheight * sizeof(int));
    if(!pptFirst || !pwFirst) {
	printf("svgapaint: alloca failed\n");
	goto out;
    }

    if (myGC->stateChanges) {
	mxValidateGC(myGC, myGC->stateChanges, (DrawablePtr)WindowTable[0]);
	myGC->stateChanges = 0;
    }

    pbox = REGION_RECTS(prgn);
    while (nrectFill--) {
	ppt = pptFirst;
	pw = pwFirst;
	height = pbox->y2 - pbox->y1;
	width = pbox->x2 - pbox->x1;
	xorg = pbox->x1;
	yorg = pbox->y1;
	i = height;
	while(i--)
	{
	    *pw++ = width;
	    ppt->x = xorg;
	    ppt->y = yorg;
	    ppt++;
	    yorg++;
	}
	mxFillSpans((DrawablePtr)WindowTable[0], myGC, height, pptFirst,
	    pwFirst, SPANS_SORTED|SPANS_TRECT, (BoxPtr)pbox);
	pbox++;
    }
out:
    DEALLOCATE_LOCAL(pwFirst);
    DEALLOCATE_LOCAL(pptFirst);
}
