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

#include "misc.h"
#include "windowstr.h"
#include "pixmapstr.h"
#include "gcstruct.h"
#include "regionst.h"
#include "scrnints.h"
#include "i8.h"
#include "../../mi/mi.h"
#include "../../../os/msdos/msdos.h"
#include "afidata.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
i8PaintWindow(pWin, prgn, what)
WindowPtr pWin;
RegionPtr prgn;
int what;
//above this line ok
{
    RegBoxPtr pbox;
    int i;
    int nrectFill, maxheight;
    DDXPointPtr		pptFirst;
    int			*pwFirst;
    DDXPointPtr ppt;
    int 	*pw;
    int height, width, xorg, yorg;
    Mask changes=0;
    Bool i8Fill =FALSE;	
    struct hspatt_data hspatt_data;
    u_char solid_patt[] = {'a','b'};
    u_char solid_color[] = {'a','b'};
    u_char *psrc, *pdst;
    struct aifpb aifpb;
    struct hline_data hline_data; 

    if (myGC == 0) {
	myGC = CreateGC((DrawablePtr)WindowTable[0],
		(BITS32)0, (XID *)0, &width);
//below this line ok
	if (myGC == 0)
		return;
	/* We don't need a few things in this GC */
	CloseFont((pointer)myGC->font, (Font)0);
	myGC->font = 0;
	if (myGC->stipple)
	    (* myGC->pScreen->DestroyPixmap)(myGC->stipple);
	myGC->stipple = 0;

	myGC->subWindowMode = IncludeInferiors;
	changes = GCFillStyle;
    }
    xorg = myGC->patOrg.x;
    yorg = myGC->patOrg.y;
    if (what == PW_BACKGROUND) {
	switch (pWin->backgroundState) {
	    case None:
		return;
	    case ParentRelative:
//above this line ok
		i8PaintWindow(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 { //end of PW_BACKGROUND
	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;
		} 
//		= (u_char)pWin->border.pixel;
//below this line ok

solid_fill:
		hspatt_data.length = 14;
		hspatt_data.width = 1;
		hspatt_data.height = 1;
		hspatt_data.flags = 0x80;	/* color */
		hspatt_data.patt_size = 1;
		hspatt_data.patt_def = &solid_patt;
		hspatt_data.patt_color = &solid_color;
		i8Fill = TRUE;
	} 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 (myGC->fillStyle == FillTiled &&
	myGC->tile.pixmap->drawable.width <= 32 &&
	myGC->tile.pixmap->drawable.height <= 32) {
	    hspatt_data.length = 14;
	    hspatt_data.width = (u_char)myGC->tile.pixmap->drawable.width;
	    hspatt_data.height = (u_char)myGC->tile.pixmap->drawable.height;
	    hspatt_data.flags = 0x80;	/* color */
	    hspatt_data.res = 0;
	    width = hspatt_data.width * hspatt_data.height;
	    hspatt_data.patt_size = (width + 7) / 8;
	    hspatt_data.patt_def = ALLOCATE_LOCAL(hspatt_data.patt_size);
	    if (!hspatt_data.patt_def)
		return;
	    hspatt_data.patt_color = ALLOCATE_LOCAL(width);
	    if (!hspatt_data.patt_color) {
		DEALLOCATE_LOCAL(hspatt_data.patt_def);
		return;
	    }
	    yorg = hspatt_data.height;
	    xorg = hspatt_data.width;
	    psrc = myGC->tile.pixmap->devPrivate.ptr;
	    pdst = hspatt_data.patt_color;
	    while (yorg--) {
		memcpy(pdst, psrc, xorg);
		pdst += xorg;
		psrc += myGC->tile.pixmap->devKind;
	    }
	    memset(hspatt_data.patt_def, 0xff, hspatt_data.patt_size);
	    i8Fill = TRUE;
    }

    nrectFill = REGION_NUM_RECTS(prgn);
    pbox = REGION_RECTS(prgn);

    if (i8Fill) {
	HSPATT(&hspatt_data);
	aifpb.length = 0;
	HBAR(&aifpb);
	while (nrectFill--) {
printf("Fill %d,%d to %d,%d\n", pbox->x1, pbox->y1, pbox->x2, pbox->y2);
	    hline_data.points[0].x = pbox->x1;
	    hline_data.points[4].x = pbox->x1;
	    hline_data.points[0].y = pbox->y1;
	    hline_data.points[4].y = pbox->y1;

	    hline_data.points[1].x = pbox->x2-1;
	    hline_data.points[1].y = pbox->y1;

	    hline_data.points[2].x = pbox->x2;
	    hline_data.points[2].y = pbox->y2;

	    hline_data.points[3].x = pbox->x1;
	    hline_data.points[3].y = pbox->y2;
	    hline_data.length = 20;
	    HLINE(&hline_data);
	    pbox++;
	}
	aifpb.length = 1;
	aifpb.params[0] = 0;
printf("call HEAR\n");
	HEAR(&aifpb);
	DEALLOCATE_LOCAL(hspatt_data.patt_def);
	DEALLOCATE_LOCAL(hspatt_data.patt_color);
printf("i8paint returns\n");
	return;
    }

    if (changes || xorg != pWin->drawable.x || yorg != pWin->drawable.y) {
	myGC->patOrg.x = pWin->drawable.x;
	myGC->patOrg.y = pWin->drawable.y;
	i8ValidateGC(myGC, changes, (DrawablePtr)WindowTable[0]);
    }

    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("i8paint: 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++;
	}
	i8FillSpans((DrawablePtr)WindowTable[0], myGC, height, pptFirst,
	    pwFirst, SPANS_SORTED|SPANS_TRECT, (BoxPtr)pbox);
	pbox++;
    }
out:
    DEALLOCATE_LOCAL(pwFirst);
    DEALLOCATE_LOCAL(pptFirst);
}
