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

#include "misc.h"
#include "windowstr.h"
#include "pixmapstr.h"
#include "gcstruct.h"
#include "regionst.h"
#include "vga.h"
#include "../../mi/mi.h"
#include "../../../os/msdos/msdos.h"

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

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

    if (myGC == 0) {
	myGC = CreateGC((DrawablePtr)WindowTable[0],
		(BITS32)0, (XID *)0, &width);
	if (myGC == 0)
		return;
	myGC->subWindowMode = IncludeInferiors;
	changes = GCFillStyle;
    }
    xorg = myGC->lastWinOrg.x;
    yorg = myGC->lastWinOrg.y;
    if (what == PW_BACKGROUND) {
	switch (pWin->backgroundState) {
	    case None:
		return;
	    case ParentRelative:
		vgaPaintWindow(pWin->parent, prgn, what);
		return;
	    case BackgroundPixel:
		if (myGC->fgPixel != pWin->background.pixel) {
		    myGC->fgPixel = pWin->background.pixel;
		    changes |= GCForeground;
		}
		if (myGC->fillStyle != FillSolid) {
		    myGC->fillStyle = FillSolid;
		    changes |= GCFillStyle;
		}
		break;
	    case BackgroundPixmap:
		if (myGC->tile.pixmap != pWin->background.pixmap) {
		    myGC->tile.pixmap = pWin->background.pixmap;
		    changes |= GCTile;
		}
		if (myGC->fillStyle != FillTiled) {
		    myGC->fillStyle = FillTiled;
		    changes |= GCFillStyle;
		}
		break;
	}
    } else {
	if (pWin->borderIsPixel) {
		if (myGC->fgPixel != pWin->border.pixel) {
		    myGC->fgPixel = pWin->border.pixel;
		    changes |= GCForeground;
		}
		if (myGC->fillStyle != FillSolid) {
		    myGC->fillStyle = FillSolid;
		    changes |= GCFillStyle;
		}
	} else {
		if (myGC->tile.pixmap != pWin->border.pixmap) {
		    myGC->tile.pixmap = pWin->border.pixmap;
		    changes |= GCTile;
		}
		if (myGC->fillStyle != FillTiled) {
		    myGC->fillStyle = FillTiled;
		    changes |= GCFillStyle;
		}
	}
    }
    if (changes || xorg != pWin->drawable.x || yorg != pWin->drawable.y) {
	/* change coordinates of root window */
	WindowTable[0]->drawable.x = pWin->drawable.x;
	WindowTable[0]->drawable.y = pWin->drawable.y;
	vgaValidateGC(myGC, changes, (DrawablePtr)WindowTable[0]);
    }

    nrectFill = REGION_NUM_RECTS(prgn);
    pbox = REGION_RECTS(prgn);
    maxheight = 0;
    for (height = 0; height<nrectFill; 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("vgapaint: alloca failed\n");
	goto out;
    }

    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++;
	}
	vgaFillSpans((DrawablePtr)WindowTable[0], myGC, height, pptFirst,
	    pwFirst, 1, (BoxPtr)pbox);
	pbox++;
    }
out:
    /* restore root window to 0,0 */
    WindowTable[0]->drawable.x = 0;
    WindowTable[0]->drawable.y = 0;
    DEALLOCATE_LOCAL(pwFirst);
    DEALLOCATE_LOCAL(pptFirst);
}
