/* Combined Purdue/PurduePlus patches, level 2.0, 1/17/89 */
/***********************************************************
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
and the Massachusetts Institute of Technology, Cambridge, Massachusetts.

                        All Rights Reserved

Permission to use, copy, modify, and distribute this software and its 
documentation for any purpose and without fee is hereby granted, 
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in 
supporting documentation, and that the names of Digital or MIT not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.  

DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.

******************************************************************/
/* Monochrome Frame Buffer definitions 
   written by drewry, september 1986
*/
#include <stdio.h>
#include <memory.h>
#include <conio.h>
#include "pixmap.h"
#include "region.h"
#include "gc.h"
#include "colormap.h"
#include "miscstruct.h"
#include "../../mi/mibstore.h"
#include "i8funcs.h"
#include "../common/ibmfuncs.h"

typedef struct _Window near * WindowPtr;
typedef struct _CharInfo *CharInfoPtr;

typedef struct {
	struct ai_funcs _far *ai_funcs;
	_segment	fb;	/* segment of frame buffer */
	int	devKind;	/* width of screen in bytes */
	u_char	curpage;	/* for 64k window to video memory */
	ColormapPtr	colormap;	/* current colormap */
	u_char	_far *saved_palette;
	u_char	_far *task_buffer;
} i8PrivScr;

extern i8PrivScr _near i8priv;

extern int InverseAlu[];
extern u_char near masktab[];

extern void near clearbits(u_char *, u_char *, int, int, int);
extern void near andbits(u_char *, u_char *, int, int, int);
extern void near andReversebits(u_char *, u_char *, int, int, int);
extern void near copybits(u_char *, u_char *, int, int, int);
extern void near andInvertedbits(u_char *, u_char *, int, int, int);
extern void near noopbits(u_char *, u_char *, int, int, int);
extern void near xorbits(u_char *, u_char *, int, int, int);
extern void near orbits(u_char *, u_char *, int, int, int);
extern void near norbits(u_char *, u_char *, int, int, int);
extern void near equivbits(u_char *, u_char *, int, int, int);
extern void near invertbits(u_char *, u_char *, int, int, int);
extern void near orReversebits(u_char *, u_char *, int, int, int);
extern void near copyInvertedbits(u_char *, u_char *, int, int, int);
extern void near orInvertedbits(u_char *, u_char *, int, int, int);
extern void near nandbits(u_char *, u_char *, int, int, int);
extern void near setbits(u_char *, u_char *, int, int, int);

int near i8Generation;
int near i8GCPrivateIndex;
int near i8ScrPrivateIndex;

typedef struct {
    unsigned char	rop;		/* reduction of rasterop to 1 of 3 */
    unsigned char	ropOpStip;	/* rop for opaque stipple */
    unsigned char	ropFillArea;	/*  == alu, rop, or ropOpStip */
    short	fExpose;		/* callexposure handling ? */
    short	freeCompClip;
    PixmapPtr	pRotatedTile;		/* tile/stipple  rotated to align */
    PixmapPtr	pRotatedStipple;	/* with window and using offsets */
    RegionPtr	pAbsClientRegion;	/* client region in screen coords */
    RegionPtr	pCompositeClip;		/* free this based on freeCompClip
					   flag rather than NULLness */
    void 	(near * FillArea)();	/* fills regions; look at the code */
    void	(near * movebits)(u_char *, u_char *, int, int, int);
    void	(near * movebytes)(u_char *psrc, u_char *pdst, int n);
    PixmapPtr	*ppPixmap;		/* pointer to tile/stipple ptr */
    short	flags;
    } i8PrivGC;
typedef i8PrivGC	*vgaPrivGCPtr;

/* freeCompositeClip values */
#define REPLACE_CC	0		/* compsite clip is a copy of a
					   pointer, so it doesn't need to 
					   be freed; just overwrite it.
					   this happens if there is no
					   client clip and the gc has
					   ClipByChildren in it.
					*/
#define FREE_CC		1		/* composite clip is a real
					   region that we need to free
					*/

#define RROP_BLACK	GXclear
#define RROP_WHITE	GXset
#define RROP_NOP	GXnoop
#define RROP_INVERT	GXinvert

/* out of clip region codes */
#define OUT_LEFT 0x08
#define OUT_RIGHT 0x04
#define OUT_ABOVE 0x02
#define OUT_BELOW 0x01

/* macros for egabitblt.c, vgafillsp.c
   these let the code do one switch on the rop per call, rather
than a switch on the rop per item (span or rectangle.)
*/

#define fnCLEAR(src, dst)	(0)
#define fnAND(src, dst) 	(src & dst)
#define fnANDREVERSE(src, dst)	(src & ~dst)
#define fnCOPY(src, dst)	(src)
#define fnANDINVERTED(src, dst)	(~src & dst)
#define fnNOOP(src, dst)	(dst)
#define fnXOR(src, dst)		(src ^ dst)
#define fnOR(src, dst)		(src | dst)
#define fnNOR(src, dst)		(~(src | dst))
#define fnEQUIV(src, dst)	(~src ^ dst)
#define fnINVERT(src, dst)	(~dst)
#define fnORREVERSE(src, dst)	(src | ~dst)
#define fnCOPYINVERTED(src, dst)(~src)
#define fnORINVERTED(src, dst)	(~src | dst)
#define fnNAND(src, dst)	(~(src & dst))
#define fnSET(src, dst)		(~0)

#ifndef PURDUE
/* Binary search to figure out what to do for the raster op.  It may
 * do 5 comparisons, but at least it does no function calls 
 * Special cases copy because it's so frequent 
 */
#define DoRop(alu, src, dst) \
( ((alu) == GXcopy) ? (src) : \
    (((alu) >= GXnor) ? \
     (((alu) >= GXcopyInverted) ? \
       (((alu) >= GXnand) ? \
         (((alu) == GXnand) ? ~((src) & (dst)) : ~0) : \
         (((alu) == GXcopyInverted) ? ~(src) : (~(src) | (dst)))) : \
       (((alu) >= GXinvert) ? \
	 (((alu) == GXinvert) ? ~(dst) : ((src) | ~(dst))) : \
	 (((alu) == GXnor) ? ~((src) | (dst)) : (~(src) ^ (dst)))) ) : \
     (((alu) >= GXandInverted) ? \
       (((alu) >= GXxor) ? \
	 (((alu) == GXxor) ? ((src) ^ (dst)) : ((src) | (dst))) : \
	 (((alu) == GXnoop) ? (dst) : (~(src) & (dst)))) : \
       (((alu) >= GXandReverse) ? \
	 (((alu) == GXandReverse) ? ((src) & ~(dst)) : (src)) : \
	 (((alu) == GXand) ? ((src) & (dst)) : 0)))  ) )
#else  /* PURDUE */
/*  Using a "switch" statement is much faster in most cases
 *  since the compiler can do a look-up table or multi-way branch
 *  instruction, depending on the architecture.  The result on
 *  A Sun 3/50 is at least 2.5 times faster, assuming a uniform
 *  distribution of RasterOp operation types.
 *
 *  However, doing some profiling on a running system reveals
 *  GXcopy is the operation over 99.5% of the time and
 *  GXcopy is the next most frequent (about .4%), so we make special
 *  checks for those first.
 *
 *  Note that this requires a change to the "calling sequence"
 *  since we can't engineer a "switch" statement to have an lvalue.
 */
#define DoRop(result, alu, src, dst) \
{ \
    if (alu == GXcopy) \
	result = fnCOPY (src, dst); \
    else if (alu == GXxor) \
        result = fnXOR (src, dst); \
    else \
	switch (alu) \
	{ \
	  case GXclear: \
	    result = fnCLEAR (src, dst); \
	    break; \
	  case GXand: \
	    result = fnAND (src, dst); \
	    break; \
	  case GXandReverse: \
	    result = fnANDREVERSE (src, dst); \
	    break; \
	  case GXandInverted: \
	    result = fnANDINVERTED (src, dst); \
	    break; \
	  case GXnoop: \
	    result = fnNOOP (src, dst); \
	    break; \
	  case GXor: \
	    result = fnOR (src, dst); \
	    break; \
	  case GXnor: \
	    result = fnNOR (src, dst); \
	    break; \
	  case GXequiv: \
	    result = fnEQUIV (src, dst); \
	    break; \
	  case GXinvert: \
	    result = fnINVERT (src, dst); \
	    break; \
	  case GXorReverse: \
	    result = fnORREVERSE (src, dst); \
	    break; \
	  case GXcopyInverted: \
	    result = fnCOPYINVERTED (src, dst); \
	    break; \
	  case GXorInverted: \
	    result = fnORINVERTED (src, dst); \
	    break; \
	  case GXnand: \
	    result = fnNAND (src, dst); \
	    break; \
	  case GXset: \
	    result = fnSET (src, dst); \
	    break; \
	} \
}
#endif  /* PURDUE */

#define DoRRop(alu, src, dst) \
(((alu) == RROP_BLACK) ? ((dst) & ~(src)) : \
 ((alu) == RROP_WHITE) ? ((dst) | (src)) : \
 ((alu) == RROP_INVERT) ? ((dst) ^ (src)) : \
  (dst))

extern char GXtoEGA[];

struct i8Cursor {
	struct _Screen *pScreen;
	struct _CursorBits *pBits;
	int pos_x, pos_y;
	u_char isUp;
	u_char validSaved;
	u_char reDraw;
	u_char shouldBeUp;
	BoxRec saved;		/* region under cursor saved */
	char *pSaved;		/* pointer to saved data */
	int save_size;		/* size in bytes of pSaved */
	int screen_width, screen_height;
	int depth;		/* useful bits in fore_color and back_color */
	u_char fore_color, back_color;
};

int	near mouse_X, near mouse_Y;

extern struct i8Cursor _near i8Cursor;

#define CUR_OVERLAP(X1,Y1,X2,Y2) ((i8Cursor.isUp || i8Cursor.validSaved) && \
				(X1) < i8Cursor.saved.x2 && \
				(X2) > i8Cursor.saved.x1 && \
				(Y1) < i8Cursor.saved.y2 && \
				(Y2) > i8Cursor.saved.y1)
