/*------------------------------------------------------------------------
*
*
* Microsoft Word -- Graphics
*
* Bitmap manipulation
*
* Our motto is: Beware of swathing!
*
*-----------------------------------------------------------------------*/

#ifdef PCWORD

#include "word.h"
#include "gr.h"
#include "grconsts.h"
#include "grstruct.h"
#include "grprocs.h"

AssertData

#endif /* PCWORD */


#ifdef WIN

#include "word.h"
DEBUGASSERTSZ		 /* WIN - bogus macro for assert string */
/* #include "file.h" */
#include "ff.h" 
#include "grstruct.h"
#include "grtiff.h"
#include "pic.h"
#include "heap.h"
#include "debug.h"

#endif /* WIN */


#ifdef SLOW_STRBLT
#define DoStrBltRow(ppc, lpbSrc, lpbDst) \
			SlowStrBltRow(ppc, lpbSrc, lpbDst)
#else
#define DoStrBltRow(ppc, lpbSrc, lpbDst) \
				StrBltRow(ppc, *(char **)&(lpbSrc), *(char **)&(lpbDst))
#endif

#ifdef OPUS_X64
typedef BYTE FAR *PATPTR;
#else
typedef WORD PATPTR;
#endif

/*  %%Function:  TranslateBitmap  %%Owner:  bobz       */


TranslateBitmap(hpc)
PICT	**hpc;
/*
	* Purpose:	StretchBlt the current swath of the bitmap indicated by hpc
	* 			and perform any necessary color translation.
	* Method:	Handle each of the five cases separately.  Some of them
	* 			could be treated as the same case but for speed reasons
	* 			we treat them separately.
	*/
{
	PICT	*ppc;
	int		smh,
	smv;

	ppc = *hpc;
	smh = ppc->sm & smhMode;
	smv = ppc->sm & smvMode;
	if ((smh != smhExpand && smv != smvExpand)
			|| (smh != smhCompress && smv != smvCompress))
		{
		NormTransBitmap(hpc);
		}
	else  if (smv == smvCompress)		/* make it shorter & fatter */
		{
		ShortFatTransBitmap(hpc);
		}
	else  /* smh == smhCompress:			/* make it taller & thinner */		
		{
		TallThinTransBitmap(hpc);
		}
}


/*  %%Function:  SetupStretch  %%Owner:  bobz       */


SetupStretch(ppc)
PICT	*ppc;
/*
	* Purpose:	Set up the stretch-blt variables.
	*			Note that wRowRem is not set here.
	* Method:		The basic algorithm is as follows:
	* 
	* 				crwRepNorm = irwOutMax / irwInMax;
	* 				wRowDelta = irwOutMax % irwInMax;
	* 				
	* 				wRowRem = 0;
	* 
	* 				for each row
	* 					{
	* 					wRowRem += wRowDelta;
	* 					copy the row crwRepNorm times
	* 					if (wRowRem >= irwInMax)
	* 						{
	* 						copy the row one more time;
	* 						wRowRem -= irwInMax;
	* 						}
	* 					}
	* The algorithm for stretching a row horizontally is similar.
	*
		*
		* We also compute a reverse stretch-blt, as if we were going
	* from Out to In.  The algorithm is run in reverse:
	*
		* 				
	* 				crwRevRepNorm = irwInMax / irwOutMax;
	* 				wRevRowDelta = irwInMax % irwOutMax;
	* 				
	* 				wRevRowRem = 0;
	* 				
	* 				for each row
	* 					{
	* 					if (wRevRowRem < wRevRowDelta)
	* 						{
	* 						wRevRowRem += irwOutMax;
	* 						repeat(1);
	* 						}
	* 					repeat crwRevRepNorm times
	* 					wRevRowRem -= wRevRowDelta;
	* 					}
	* The reverse stretchblt is never run, but the variables are
	* used to determine which rows are in the swath.
	*/
{
	ppc->crwRepNorm = UDiv(ppc->irwOutMax, ppc->irwInMax, &ppc->wRowDelta);

	ppc->crwRevRepNorm = UDiv(ppc->irwInMax, ppc->irwOutMax, &ppc->wRevRowDelta);

	ppc->cbitRepNorm = UDiv(ppc->pixExt.h, ppc->vtExt.h, &ppc->wBitDelta);
}


/*  %%Function:  NormTransBitmap  %%Owner:  bobz       */



NormTransBitmap(hpc)
PICT	**hpc;
/*
	* Shrink the bitmap in one or both directions;
	* or expand it in one or both directions
	* (combinations of shrinking and expanding are handled elsewhere).
	* The process is performed in one pass:
	* 	For each source row
	* 		If this maps to a destination row
	*			Stretchblt the source to the destination
	*			For each extra copy of the row that is to be made,
	*				For each plane
	*					Increment the destination pointer
	*					Copy from the first destination to this row
	* 			Increment the pointer to the next destination row
	* 		Increment the pointer to the next source row
	*
		*/
{
	PICT		*ppc;
	int			irwIn,
	crwRep,
	wRowRem,
	ipl,
	crwDst;
	unsigned	irwOut;
	BOOL		fColorToMono;
	char HUGE	*hpbBits,
	HUGE	*hpbPat;
	char FAR	*lpbBits,
	FAR	*lpbSrc,
	FAR	*lpbDst,
	FAR	*lpbDstT,
	FAR	*lpbDstFirst,
	FAR	*lpbDstFirstT;
	PATPTR		psPat;
	BOOL		fAbort;

	ppc = *hpc;
	FreezeHeap();
	fAbort = fFalse;
	lpbBits = LpLockHp(hpbBits = HpOfSbIb(ppc->sbBits,0));

	Assert((ppc->irwOutMax <= ppc->irwInMax && ppc->pixExt.h <= ppc->vtExt.h)
			|| (ppc->irwOutMax >= ppc->irwInMax && ppc->pixExt.h >= ppc->vtExt.h));

	lpbSrc = lpbBits + ppc->ibIn;
	lpbDst = lpbBits;
	irwOut = ppc->irwOutMic;
	crwDst = ppc->irwOutMac - irwOut;
	Assert(crwDst > 0);
	fColorToMono = ppc->fColorDither || ppc->fGrayDither;
	if (fColorToMono)
		#ifdef OPUS_X64
		psPat = LpLockHp(hpbPat = HpOfSbIb(ppc->sbPat, 0));
		#else
		psPat = PsOfLp(LpLockHp(hpbPat = HpOfSbIb(ppc->sbPat, 0)));
		#endif

	/* compute crwRep and wRowRem for first row */
	wRowRem = ((long)ppc->wRowDelta * ((long)(int)ppc->irwInMic+1))
			% (int)ppc->irwInMax;
	crwRep = OutFromIn(ppc, ppc->irwInMic) - ppc->irwOutMic + 1;
	Assert(crwRep > 0);		/* else why did we read irwInMic? */

	for (irwIn = ppc->irwInMic; irwIn < ppc->irwInMac; ++irwIn)
		{
		if (irwIn != ppc->irwInMic)
			{
			wRowRem += ppc->wRowDelta;
			crwRep = ppc->crwRepNorm;
			if (wRowRem >= ppc->irwInMax)
				{
				++crwRep;
				wRowRem -= ppc->irwInMax;
				}
			}
		/* else we computed crwRep and wRowRem outside the loop */
		if (crwRep > 0)
			{

#ifdef PCWORD
			/* for WIN, this call could mess up the locked huge pointers,
			so we will check abort after the TranslateBitmap call
			*/

			if ((irwIn & 15) == 0 && FAbortRequest())
				{
				fAbort = fTrue;
				goto Done;
				}
#endif /* PCWORD */

			if (fColorToMono)
				{
				do 
					{
					MonoStrBltRow(ppc, lpbSrc, lpbDst, irwOut++, psPat);
					--crwDst;
					lpbDst += ppc->cbRowOut;
					} 
				while (--crwRep > 0 && crwDst > 0);
				}
			else
				{
				DoStrBltRow(ppc, lpbSrc, lpbDst);
				--crwDst;
				lpbDstFirst = lpbDst;
				lpbDst += ppc->cbRowOut;
				while (--crwRep > 0 && crwDst > 0)
					{
					lpbDstT = lpbDst;
					lpbDstFirstT = lpbDstFirst;
					for (ipl = 0; ipl < ppc->cplOut; ++ipl)
						{
						bltbx(lpbDstFirstT, lpbDstT, ppc->cbRowOut);
						lpbDstT += ppc->cbPlane;
						lpbDstFirstT += ppc->cbPlane;
						}
					lpbDst += ppc->cbRowOut;
					--crwDst;
					}
				}
			}
		lpbSrc += ppc->cbRowIn;
		}
	Assert(crwDst == 0);

Done:
	UnlockHp(hpbBits);
	if (fColorToMono)
		UnlockHp(hpbPat);
	MeltHeap();


#ifdef PCWORD
	if (fAbort)
		UserAbort();
#endif /* PCWORD */

}


/*  %%Function:  ShortFatTransBitmap  %%Owner:  bobz       */


ShortFatTransBitmap(hpc)
PICT		**hpc;
/*
	* Compress vertically and expand horizontally a bitmap.
	* This is done in two passes as follows:
	* 
	* Pass 1:
	* Set the source pointer to point to the last row
	* Set the destination pointer to point to the end of the plane - cbRowIn
	* Run the row stretchblt in reverse, copying from source to destination
	* 
	* Pass 2:
	* Set the destination pointer to the start of the plane
	* For each source row (starting with the first)
	* 		Stretchblt the row to the destination
	* 		Increment the source and destination pointers
	*/
{
	PICT		*ppc;
	int			irw,
	wRowRem,
	ipl;
	BOOL		fColorToMono;
	char HUGE	*hpbBits,
	HUGE	*hpbPat;
	char FAR	*lpbBits,
	FAR	*lpbSrc,
	FAR	*lpbDst,
	FAR	*lpbSrcT,
	FAR	*lpbDstT;
	PATPTR		psPat;
	BOOL		fAbort;
	Debug(int	crwDst);

	ppc = *hpc;
	FreezeHeap();
	fAbort = fFalse;
	lpbBits = LpLockHp(hpbBits = HpOfSbIb(ppc->sbBits,0));

	Assert(ppc->irwOutMax < ppc->irwInMax && ppc->pixExt.h > ppc->vtExt.h
			&& ppc->irwOutMac > ppc->irwOutMic);

	fColorToMono = ppc->fColorDither || ppc->fGrayDither;
	if (fColorToMono)
		#ifdef OPUS_X64
		psPat = LpLockHp(hpbPat = HpOfSbIb(ppc->sbPat, 0));
		#else
		psPat = PsOfLp(LpLockHp(hpbPat = HpOfSbIb(ppc->sbPat, 0)));
		#endif

	/* Pass 1 -- vertical compression */

	lpbSrc = lpbBits + ppc->ibIn
			+ ppc->cbRowIn * (ppc->irwInMac - ppc->irwInMic - 1);
	lpbDst = lpbBits + ppc->cbPlane - ppc->cbRowIn;
	Debug(crwDst = 0);

	/* compute what remainder would be *after* irwInMac-1'th row */
	wRowRem = ((long)ppc->wRowDelta * (long)(int)ppc->irwInMac)
			% (int)ppc->irwInMax;
	for (irw = ppc->irwInMac - 1; irw >= ppc->irwInMic; --irw)
		{
		if (wRowRem < ppc->wRowDelta)
			{
			wRowRem += ppc->irwInMax;
			lpbSrcT = lpbSrc;
			lpbDstT = lpbDst;
			for (ipl = 0; ipl < ppc->cplIn; ++ipl)
				{
				bltbx(lpbSrcT, lpbDstT, ppc->cbRowIn);
				lpbSrcT += ppc->cbPlane;
				lpbDstT += ppc->cbPlane;
				}
			lpbDst -= ppc->cbRowIn;
			Debug(++crwDst);
			}
		lpbSrc -= ppc->cbRowIn;
		wRowRem -= ppc->wRowDelta;
		}
	Debug(Assert(crwDst == ppc->irwOutMac - ppc->irwOutMic));


	/* Pass 2 -- horizontal expansion */

	lpbSrc = lpbDst + ppc->cbRowIn;
	lpbDst = lpbBits;

	for (irw = ppc->irwOutMic; irw < ppc->irwOutMac; ++irw)
		{
#ifdef PCWORD
		/* for WIN, this call could mess up the locked huge pointers,
		so we will check abort after the TranslateBitmap call
		*/

		if ((irw & 31) == 0 && FAbortRequest())
			{
			fAbort = fTrue;
			goto Done;
			}
#endif /* PCWORD */

		if (fColorToMono)
			MonoStrBltRow(ppc, lpbSrc, lpbDst, irw, psPat);
		else
			DoStrBltRow(ppc, lpbSrc, lpbDst);
		lpbSrc += ppc->cbRowIn;
		lpbDst += ppc->cbRowOut;
		}

Done:
	UnlockHp(hpbBits);
	if (fColorToMono)
		UnlockHp(hpbPat);
	MeltHeap();


#ifdef PCWORD
	if (fAbort)
		UserAbort();
#endif /* PCWORD */

}


/*  %%Function:  TallThinTransBitmap  %%Owner:  bobz       */


TallThinTransBitmap(hpc)
PICT		**hpc;
/*
	* Expand vertically and compress horizontally a bitmap.
	* This is done in two passes as follows:
	* 
	* Pass 1:
	* Compress the rows horizontally, copying them so they are at the start
	* of the planes.  Then copy them to the end of the plane, en masse.
	* 
	* Pass 2:
	* If the first input row was the last input row in the last swath,
	* finish mapping from it.  Then for each remaining input row
	* (going forwards), map it to its output rows.  The output rows
	* will start at the beginning of the planes.
	*
		* If we're translating a color bitmap to B&W, we have to modify this
	* somewhat.  In pass 1, when we do the compression (via StrBltRow)
	* don't do any color translation.  Then in pass 2, instead of
	* just copying each compressed source row to the destination rows,
	* perform a color translation on each one, via MonoStrBltRow.
	*
		* The reason we can't translate colors to patterns in the first
	* pass is that the patterning is based on output rows.  If the
	* patterning was done on input rows, the stretching would be
	* very conspicuous.
	*/
{
	PICT		*ppc;
	int			irwIn,
	crw,
	crwDst,
	wRowRem,
	crwRep,
	ipl,
	ico;
	unsigned	irwOut;
	BOOL		fColorToMono;			/* true if color --> B&W */
	unsigned	cbPlane,
	cbRowOut;
	char HUGE	*hpbBits,
	HUGE	*hpbPat;
	char FAR	*lpbBits,
	FAR	*lpbSrc,
	FAR	*lpbDst,
	FAR	*lpbSrcT,
	FAR	*lpbDstT;
	PATPTR		psPat;
	unsigned	cbIntermediate;
	BYTE		rgicoSav[16];			/* save real values here */
	int			cbitRepNormT,			/* ...while we munge around */
	wBitDeltaT,				/* ...with the PICT, */
	virtExtHT;				/* ...for color --> B&W */
	BOOL		fAbort;

	ppc = *hpc;
	FreezeHeap();
	fAbort = fFalse;
	lpbBits = LpLockHp(hpbBits = HpOfSbIb(ppc->sbBits,0));

	Assert(ppc->irwOutMax > ppc->irwInMax && ppc->pixExt.h < ppc->vtExt.h);

	cbPlane = ppc->cbPlane;
	cbRowOut = ppc->cbRowOut;
	fColorToMono = ppc->fColorDither || ppc->fGrayDither;
	if (fColorToMono)
		#ifdef OPUS_X64
		psPat = LpLockHp(hpbPat = HpOfSbIb(ppc->sbPat, 0));
		#else
		psPat = PsOfLp(LpLockHp(hpbPat = HpOfSbIb(ppc->sbPat, 0)));
		#endif


	/* Pass 1 -- horizontal compression */
	/* if color --> B&W, don't translate colors here */

	lpbSrc = lpbBits + ppc->ibIn;
	lpbDst = lpbBits;

	if (fColorToMono)
		{			/* inhibit color translation; only do compression */
		bltb(ppc->rgico, rgicoSav, 16);
		for (ico = 0; ico < 16; ++ico)
			ppc->rgico[ico] = ico;
		ppc->cplOut = ppc->cplIn;	/* don't save cplOut; we know it's 1 */
		}


	for (irwIn = ppc->irwInMic; irwIn < ppc->irwInMac; ++irwIn)
		{

#ifdef PCWORD
		/* for WIN, this call could mess up the locked huge pointers,
		so we will check abort after the TranslateBitmap call
		*/

		if ((irwIn & 31) == 0 && FAbortRequest())
			{
			fAbort = fTrue;
			goto Done;
			}
#endif /* PCWORD */

		DoStrBltRow(ppc, lpbSrc, lpbDst);
		lpbSrc += ppc->cbRowIn;
		lpbDst += cbRowOut;
		}

	/* Copy to end of plane */

	cbIntermediate = (ppc->irwInMac - ppc->irwInMic) * cbRowOut;
	lpbSrc = lpbBits;
	lpbDst = lpbBits + (cbPlane - cbIntermediate);

	for (ipl = ppc->cplOut; ipl > 0; --ipl)
		{
		bltbx(lpbSrc, lpbDst, cbIntermediate);
		lpbSrc += cbPlane;
		lpbDst += cbPlane;
		}

	/* Pass 2 -- vertical expansion */
	/* if color --> B&W, translate colors in this stage */

	if (fColorToMono)
		{				/* inhibit compression; only translate colors */
		cbitRepNormT = ppc->cbitRepNorm;
		ppc->cbitRepNorm = 1;
		wBitDeltaT = ppc->wBitDelta;
		ppc->wBitDelta = 0;
		virtExtHT = ppc->vtExt.h;
		ppc->vtExt.h = ppc->pixExt.h;
		bltb(rgicoSav, ppc->rgico, 16);		/* restore color mapping */
		ppc->cplOut = 1;
		}

	lpbSrc = lpbBits + (cbPlane - cbIntermediate);
	lpbDst = lpbBits;
	crwDst = ppc->irwOutMac - ppc->irwOutMic;
	Assert(crwDst > 0);

	irwOut = ppc->irwOutMic;

	/* compute crwRep and wRowRem for first row */
	wRowRem = ((long)ppc->wRowDelta * ((long)(int)ppc->irwInMic+1))
			% (int)ppc->irwInMax;
	crwRep = OutFromIn(ppc, ppc->irwInMic) - ppc->irwOutMic + 1;
	Assert(crwRep > 0);		/* else why did we read irwInMic? */


	for (irwIn = ppc->irwInMic; irwIn < ppc->irwInMac; ++irwIn)
		{
		if (irwIn != ppc->irwInMic)
			{
			wRowRem += ppc->wRowDelta;
			crwRep = ppc->crwRepNorm;
			if (wRowRem >= ppc->irwInMax)
				{
				++crwRep;
				wRowRem -= ppc->irwInMax;
				}
			}
		Assert(crwRep > 0);

#ifdef PCWORD
		/* for WIN, this call could mess up the locked huge pointers,
		so we will check abort after the TranslateBitmap call
		*/

		if ((irwIn & 31) == 0 && FAbortRequest())
			{
			fAbort = fTrue;
			goto Done;
			}
#endif /* PCWORD */

		while (crwRep > 0 && crwDst > 0)
			{
			if (fColorToMono)
				MonoStrBltRow(ppc, lpbSrc, lpbDst, irwOut++, psPat);
			else
				{
				lpbSrcT = lpbSrc;
				lpbDstT = lpbDst;
				for (ipl = 0; ipl < ppc->cplOut; ++ipl)
					{
					bltbx(lpbSrcT, lpbDstT, cbRowOut);
					lpbDstT += cbPlane;
					lpbSrcT += cbPlane;
					}
				}
			lpbDst += cbRowOut;
			--crwRep;
			--crwDst;
			}
		lpbSrc += ppc->cbRowOut;
		}
	Assert(crwDst == 0);
	if (fColorToMono)
		{				/* restore stretchblt values */
		ppc->cbitRepNorm = cbitRepNormT;
		ppc->wBitDelta = wBitDeltaT;
		ppc->vtExt.h = virtExtHT;
		}

Done:
	UnlockHp(hpbBits);
	if (fColorToMono)
		UnlockHp(hpbPat);
	MeltHeap();


#ifdef PCWORD
	if (fAbort)
		UserAbort();
#endif /* PCWORD */

}



#if defined(SLOW_STRBLT) || defined(OPUS_X64)

/*  %%Function:  SlowStrBltRow  %%Owner:  bobz       */

SlowStrBltRow(ppc, lpbSrc, lpbDst)
PICT		*ppc;
char FAR	*lpbSrc,
FAR	*lpbDst;
	/*
		* Stretchblts a single row, copying from lpbSrc to lpbDst.
		* Can handle compression and expansion.
		*/
{
	int		wRem,
	ibitSrc,
	ibitDst,
	virtSrc,
	cbitRep;
	int		ipl,
	cpl;
	BYTE FAR *rglpbSrc[4];		/* points to source planes */
	BYTE FAR *rglpbDst[4];		/* points to dest planes */
	BYTE	rgbSrc[4],			/* current byte in each source plane */
	rgbDst[4],			/* current byte in each dest plane */
	rgbCurPix[4],		/* only low bit is used in this array */
	*pbSrc,
			*pbDst,
			*pbCur,
			*pbSrcMac,
			*pbDstMac,
			*pbCurMac;
	BYTE	bT;
	BYTE FAR **plpbSrc,
			FAR **plpbDst;
	int		ico;				/* color number */

	pbSrcMac = &rgbSrc[ppc->cplIn];
	pbDstMac = &rgbDst[ppc->cplOut];
	pbCurMac = &rgbCurPix[ppc->cplOut];
	cpl = max(ppc->cplIn, ppc->cplOut);
	/* Note that this will initialize more pointers than used */
	/* if ppc->cplIn != ppc->cplOut. */
	for (ipl = 0, plpbSrc = rglpbSrc, plpbDst = rglpbDst; ipl < cpl; ++ipl)
		{
		*plpbSrc++ = lpbSrc;
		*plpbDst++ = lpbDst;
		lpbSrc += ppc->cbPlane;
		lpbDst += ppc->cbPlane;
		}

	ibitSrc = 0;
	ibitDst = 7;
	for (pbDst = rgbDst; pbDst < pbDstMac;)
		*pbDst++ = 0;
	wRem = 0;
	for (virtSrc = 0; virtSrc < ppc->vtExt.h; ++virtSrc)
		{
		wRem += ppc->wBitDelta;
		cbitRep = ppc->cbitRepNorm;
		if (wRem >= ppc->vtExt.h)
			{
			++cbitRep;
			wRem -= ppc->vtExt.h;
			}
		if (ibitSrc-- == 0)
			{
			for (pbSrc = rgbSrc, plpbSrc = rglpbSrc; pbSrc < pbSrcMac;)
				{
				*pbSrc++ = *(*plpbSrc)++;
				plpbSrc++;
				}
			ibitSrc = 7;
			}
		else
			{
			for (pbSrc = rgbSrc; pbSrc < pbSrcMac;)
				*pbSrc++ <<= 1;
			}
		if (cbitRep > 0)
			{
			ico = 0;
			for (pbSrc = pbSrcMac; pbSrc > rgbSrc;)
				{
				ico <<= 1;
				bT = (*--pbSrc & 0x80) ? 1 : 0;
				ico |= bT;
				}
			ico = ppc->rgico[ico];
			for (pbCur = rgbCurPix; pbCur < pbCurMac;)
				{
				*pbCur++ = ico & 0x01;
				ico >>= 1;
				}
			while (cbitRep-- > 0)
				{
				for (pbDst = rgbDst, pbCur = rgbCurPix; pbDst < pbDstMac;)
					*pbDst++ |= *pbCur++;
				if (ibitDst-- == 0)
					{
					for (pbDst = rgbDst, plpbDst = rglpbDst; pbDst < pbDstMac;)
						{
						*(*plpbDst)++ = *pbDst;
						plpbDst++;
						*pbDst++ = 0;
						}
					ibitDst = 7;
					}
				else
					{
					for (pbDst = rgbDst; pbDst < pbDstMac;)
						*pbDst++ <<= 1;
					}
				}
			}
		}
	if (ibitDst < 7)
		{
		for (pbDst = rgbDst, plpbDst = rglpbDst; pbDst < pbDstMac;)
			{
			**plpbDst++ = *pbDst++ << ibitDst;
			}
		}
}


#ifdef OPUS_X64
/* Keep the C++ GRBITX translation independent of the K&R-era private PICT
 * layout while still giving it the exact values used by this source file. */
void C_GetMonoStrBltInfo(ppc, rgw)
PICT *ppc;
unsigned *rgw;
{
	rgw[0] = ppc->cplIn;
	rgw[1] = ppc->cplOut;
	rgw[2] = ppc->cbPlane;
	rgw[3] = ppc->vtExt.h;
	rgw[4] = ppc->pixExt.h;
	rgw[5] = ppc->cbitRepNorm;
	rgw[6] = ppc->wBitDelta;
}
#endif


#endif



#ifdef PCWORD

/*  %%Function:  SendBitmap  		 %%Owner:  bobz       */

SendBitmap(hpc)
PICT	**hpc;
/*
	* Purpose:	Send the current swath of the bitmap indicated by hpc
	* 			to the output device.  This is only used for the screen.
	* Method:	Set up a bitmap structure for each plane, and call BitBlt.
	*			Clip to the bottom of the clipping rectangle.
	*/
{
	extern int		vlm;
	extern BOOL		vfMouse;

	unsigned	ipl,
	pen,
	irw;
	char HUGE	*hpBits;
	PICT		*ppc;
	GRECT		rcSrc,
			rcSwath;
	char FAR	*lpSave,
	FAR	*lpCur;
	GPOINT		pt;
	int			irwOutMac;
	unsigned	rgcoAvail[icoLim];
	GRECT		rcT;


	Assert(vfProcs & fBitBlt);
	CheckGrAbort();
	ppc = *hpc;

	hpBits = HpOfSbIb(ppc->sbBits, 0);
	lpSave = LpLockHp(hpBits);
	rcSrc.top = 0;					/* rcSrc.bottom is set below */
	rcSrc.left = 0;
	rcSrc.right = ppc->pixExt.h;
	irwOutMac = min(ppc->irwOutMac,
			grafPort.rectClip.bottom - ppc->pixOrg.v);
	pt.h = ppc->pixOrg.h;
	pt.v = ppc->pixOrg.v + ppc->irwOutMic;

	SetColor(0, coBlack);

	if (ppc->cplOut == 1)	/* monochrome -- use regular BitBlt */
		{
		rcSrc.bottom = irwOutMac - ppc->irwOutMic;
		Move(pt.h, pt.v);
		if (vfMouse && vlm == lmPreview)
			{
			rcT = rcSrc;
			OffsetRect(&rcT, pt.h, pt.v);
			MouseConditionalOff(&rcT);
			}
		BitBlt(&rcSrc, lpSave, ppc->cbRowOut, FALSE);
		}
	else		/* color -- use planar BitBlt */		
		{
		GRSetApa(apaSolid);			/* first wipe out area with black */
		rcSwath.top = ppc->pixOrg.v + ppc->irwOutMic;
		rcSwath.left = ppc->pixOrg.h;
		rcSwath.bottom = ppc->pixOrg.v + irwOutMac;
		rcSwath.right = rcSwath.left + ppc->pixExt.h;
		if (vlm == lmPreview)
			MouseConditionalOff(&rcSwath);
		VctrRect(&rcSwath, FALSE);

		bltbh(hpvdvCur->rgcoAvail, rgcoAvail, icoLim);

		rcSrc.bottom = 1;

		for (irw = ppc->irwOutMic; irw < irwOutMac; ++irw)
			{
			lpCur = lpSave;
			Move(pt.h, pt.v);
			for (ipl = 0, pen = 1; ipl < ppc->cplOut; ++ipl, pen <<= 1)
				{
				SetColor(pen, rgcoAvail[pen]);
				BitBlt(&rcSrc, lpCur, ppc->cbRowOut, TRUE);
				lpCur += ppc->cbPlane;
				}
			lpSave += ppc->cbRowOut;
			++pt.v;
			}
		}
	if (vlm == lmPreview)
		MouseShowCursor();
	UnlockHp(hpBits);
}


#endif /* PCWORD */


#ifdef PROFILE
/*  this is here so that appended native code does not appear in previous
	function in pcode profiles. */
Grbit_Last(){}
#endif /* PROFILE */

/* ADD NEW CODE *ABOVE* Grbit_Last() */
