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

#include "misc.h"
#include "regionstr.h"
#include "gcstruct.h"
#include "windowstr.h"
#include "pixmapstr.h"
#include "scrnintstr.h"

#include "svga.h"

#include "servermd.h"
#include "../common/mouse.h"

typedef unsigned char u_char;
typedef unsigned short u_short;
typedef unsigned long u_long;

void
svgaGetSpans(pDrawable, wMax, ppt, pwidth, nspans, pdst)
    DrawablePtr		pDrawable;
    int			wMax;		/* largest value of all *pwidths */
    register DDXPointPtr ppt;
    int			*pwidth;
    int			nspans;
    unsigned char	*pdst;
{
    register DDXPointPtr pptLast;	/* one past last point to get */
    int 		widthSrc;	/* width of bitmap in bytes */
    int	 		srcBit;
    int			xEnd, w;

    pptLast = ppt + nspans;

    if (pDrawable->type == DRAWABLE_WINDOW)
    {
	svgaPrivScr *pPriv = (svgaPrivScr *)(pDrawable->pScreen->devPrivate);
	_segment		base;
	u_char _based(base)	*cp;
	u_long bytenum;
	u_char page;		/* which page on display */

	base = pPriv->fb;
	widthSrc = pPriv->devKind;
#ifdef DIRECT_MOUSE
	/* Turn cursor off */
	ConditionalOff(pDrawable->x, pDrawable->y,
	    pDrawable->x + pDrawable->width,
	    pDrawable->y + pDrawable->height);
#else
	if (CUR_OVERLAP(pDrawable->x, pDrawable->y,
	    pDrawable->x + pDrawable->width,
	    pDrawable->y + pDrawable->height))
		HideCursor();
#endif
	while(ppt < pptLast) {
	    xEnd = min(ppt->x + *pwidth, widthSrc);
	    bytenum = (u_long)ppt->y * widthSrc + ppt->x;
	    page = (u_char)(bytenum >> 16);
	    page &= 0xf;	/* just to be sure */
	    if (svgapriv.curpage != page) {
		svgapriv.curpage = page;
		SetPage();
	    }
	    w = xEnd - ppt->x;
	    cp = (u_char _based(base) *)(u_short)bytenum;
	    if ((u_short)cp > (u_short)(-w)) {
		memcpy(pdst, (char far *)cp, -(short)cp);
		w += (short)cp;
		cp = 0;
		svgapriv.curpage++;
		SetPage();
		memcpy(pdst - (short)bytenum, (char far *)cp, w);
	    } else
		memcpy(pdst, (char far *)cp, w);
	    pdst += PixmapBytePad(wMax, 8);
	    ppt++;
	    pwidth++;
	}
#ifdef DIRECT_MOUSE
	ShowCursor();
#endif
    }
    else
    {
	char *psrcBase, *psrc;

	psrcBase = ((PixmapPtr)pDrawable)->devPrivate.ptr;
	widthSrc = (int)(((PixmapPtr)pDrawable)->devKind);
	if (pDrawable->depth == 1) {	/* bitmap */
	    while(ppt < pptLast) {
		xEnd = min(ppt->x + *pwidth, widthSrc << 3);
		pwidth++;
		psrc = psrcBase + (ppt->y * widthSrc) + (ppt->x >> 3);
		w = xEnd - ppt->x;
		srcBit = ppt->x & 7;

		copybits((char _far *)psrc, pdst, srcBit, 0, w);
		pdst += PixmapBytePad(wMax, 1);
		ppt++;
	    }
	} else {
	    while(ppt < pptLast) {
		xEnd = min(ppt->x + *pwidth, widthSrc);
		pwidth++;
		psrc = psrcBase + (ppt->y * widthSrc) + ppt->x;
		w = xEnd - ppt->x;

		memcpy(pdst, (char far *)psrc, w);
		pdst += PixmapBytePad(wMax, 8);
		ppt++;
	    }
	}
    }
}
