#include "x.h"
#include "../ega/ega.h"

/* Move bits not always on a byte boundry.  soff and doff are assumed
 * to be >= 0 and < 8.
 */
void
movebits(psrc, pdst, soff, doff, n, rop)
unsigned char _Far *psrc, *pdst;
int	soff, doff;
int	n;			/* number of bits */
int	rop;
{
	int bitstoshift = doff - soff;
	unsigned char temp;
	unsigned char mask;
	int nbytes;

	if (rop == GXcopy) {
		copybits(psrc, pdst, soff, doff, n);
		return;
	}
	if (rop == GXor) {
		orbits(psrc, pdst, soff, doff, n);
		return;
	}
	if (bitstoshift == 0) {
		if (soff) {
			mask = 0xff >> soff;
			n -= 8 - soff;
			if (n < 0)
				mask &= 0xff << -n;
			*pdst = (~mask & *pdst) |
			    (DoRop(rop, *psrc, *pdst) & mask);
			if (n <= 0)
				return;
			psrc++;
			pdst++;
		}
		nbytes = n >> 3;
		while (nbytes--) {
			*pdst = DoRop(rop, *psrc, *pdst);
			pdst++;
			psrc++;
		}
		n &= 7;
		if (n) {
			mask = 0xff >> n;
			*pdst = (mask & *pdst)
				| (DoRop(rop, *psrc, *pdst) & ~mask);
		}
		return;
	} else if (bitstoshift > 0) {
		mask = 0xff >> doff;
		temp = *psrc >> bitstoshift;
		n -= 8 - doff;
		if (n < 0)
			mask &= 0xff << -n;
		*pdst = (~mask & *pdst) | (DoRop(rop, temp, *pdst) & mask);
		if (n <= 0)
			return;
		pdst++;

		nbytes = n >> 3;
		while (nbytes--) {
			temp = *psrc << 8 - bitstoshift;
			psrc++;
			temp |= *psrc >> bitstoshift;
			*pdst = DoRop(rop, temp, *pdst);
			pdst++;
		}
		n &= 7;
		if (n == 0)
			return;
		temp = *psrc << 8 - bitstoshift;
		psrc++;
		if (n > bitstoshift)
			temp |= *psrc >> bitstoshift;
		mask = 0xff >> n;
		*pdst = (mask & *pdst) | (DoRop(rop, temp, *pdst) & ~mask);
	} else {
		bitstoshift = -bitstoshift;
		temp = *psrc << bitstoshift;
		psrc++;
		if (n > 8 - soff)
			temp |= *psrc >> 8 - bitstoshift;
		mask = 0xff >> doff;
		n -= 8 - doff;
		if (n < 0) {
			mask &= 0xff << -n;
		}
		*pdst = (~mask & *pdst) | (DoRop(rop, temp, *pdst) & mask);
		if (n <= 0)
			return;
		pdst++;
		nbytes = n >> 3;
		while (nbytes--) {
			temp = *psrc << bitstoshift;
			psrc++;
			temp |= *psrc >> 8 - bitstoshift;
			*pdst = DoRop(rop, temp, *pdst);
			pdst++;
		}
		n &= 7;
		if (n == 0)
			return;
		mask = 0xff >> n;
		temp = *psrc << bitstoshift;
		psrc++;
		if (n > 8 - bitstoshift)
			temp |= *psrc >> 8 - bitstoshift;
		*pdst = (mask & *pdst) | (DoRop(rop, temp, *pdst) & ~mask);
	}
}

#ifdef notdef
/*
 * Copy, no rop
 */
void
copybits(psrc, pdst, soff, doff, n)
unsigned char *psrc, *pdst;
int	soff, doff;
int	n;			/* number of bits */
{
	int bitstoshift = doff - soff;
	unsigned char temp;
	unsigned char mask;
	int nbytes;

	if (bitstoshift == 0) {
		if (soff) {
			mask = 0xff >> soff;
			n -= 8 - soff;
			if (n < 0)
				mask &= 0xff << -n;
			*pdst = (~mask & *pdst) | (*psrc & mask);
			if (n <= 0)
				return;
			psrc++;
			pdst++;
		}
		nbytes = n >> 3;
		while (nbytes--) {
			*pdst++ = *psrc++;
		}
		n &= 7;
		if (n) {
			mask = 0xff >> n;
			*pdst = (mask & *pdst) | (*psrc & ~mask);
		}
		return;
	} else if (bitstoshift > 0) {
		mask = 0xff >> doff;
		temp = *psrc >> bitstoshift;
		n -= 8 - doff;
		if (n < 0)
			mask &= 0xff << -n;
		*pdst = (~mask & *pdst) | (temp & mask);
		if (n <= 0)
			return;
		pdst++;

		nbytes = n >> 3;
		while (nbytes--) {
			temp = *psrc << 8 - bitstoshift;
			psrc++;
			temp |= *psrc >> bitstoshift;
			*pdst = temp;
			pdst++;
		}
		n &= 7;
		if (n == 0)
			return;
		temp = *psrc << 8 - bitstoshift;
		psrc++;
		if (n > bitstoshift)
			temp |= *psrc >> bitstoshift;
		mask = 0xff >> n;
		*pdst = (mask & *pdst) | (temp & ~mask);
	} else {
		bitstoshift = -bitstoshift;
		temp = *psrc << bitstoshift;
		psrc++;
		if (n > 8 - soff)
			temp |= *psrc >> 8 - bitstoshift;
		mask = 0xff >> doff;
		n -= 8 - doff;
		if (n < 0) {
			mask &= 0xff << -n;
			*pdst = (~mask & *pdst) |
			    (temp & mask);
			return;
		}
		if (n <= 0)
			return;
		*pdst = (~mask & *pdst) | (temp & mask);
		pdst++;
		nbytes = n >> 3;
		while (nbytes--) {
			temp = *psrc << bitstoshift;
			psrc++;
			temp |= *psrc >> 8 - bitstoshift;
			*pdst = temp;
			pdst++;
		}
		n &= 7;
		if (n == 0)
			return;
		mask = 0xff >> n;
		temp = *psrc << bitstoshift;
		psrc++;
		if (n > 8 - bitstoshift)
			temp |= *psrc >> 8 - bitstoshift;
		*pdst = (mask & *pdst) | (temp & ~mask);
	}
}
#endif
