//	Zinc Application Framework - Z_DSP.HPP
//	COPYRIGHT (C) 1990-1999.  All Rights Reserved.
//	Zinc Software Incorporated.  Pleasant Grove, Utah  USA

#if !defined(Z_DSP_HPP)
#define Z_DSP_HPP
#include <z_region.hpp>
#include <z_pal.hpp>
#include <z_list.hpp>

typedef long ZafCoordinate;

const int ZAF_HAIR_LINE	= -1;

// ----- ZafImageStruct -----------------------------------------------------

struct ZAF_EXPORT ZafImageStruct
{
	int width, height;
	ZafLogicalColor *array;
	bool staticArray;

	// --- Attributes ---
	// get
	bool StaticArray(void) const;
	// set
	bool SetStaticArray(bool staticArray);
};

// --- inline functions ---
inline bool ZafImageStruct::StaticArray(void) const { return (staticArray); }
inline bool ZafImageStruct::SetStaticArray(bool tStaticArray) { staticArray = tStaticArray; return (staticArray); }

// ----- ZafBitmapStruct ----------------------------------------------------

struct ZAF_EXPORT ZafBitmapStruct : public ZafImageStruct
{
	OSBitmapID handle;
	OSMaskID mask;
#	if defined(ZAF_MACINTOSH)
	OSMaskID monoHandle;
#	endif
	bool staticHandle;

	ZafBitmapStruct(void);
	ZafBitmapStruct(const ZafImageStruct &data);
	ZafBitmapStruct(int width, int height, ZafLogicalColor *array,
		bool staticArray);

	// --- Attributes ---
	// get
	bool StaticHandle(void) const;
	// set
	bool SetStaticHandle(bool staticHandle);
};

// --- inline functions ---
inline bool ZafBitmapStruct::StaticHandle(void) const { return (staticHandle); }
inline bool ZafBitmapStruct::SetStaticHandle(bool tStaticHandle) { staticHandle = tStaticHandle; return (staticHandle); }

// ----- ZafIconStruct ------------------------------------------------------

struct ZAF_EXPORT ZafIconStruct : public ZafImageStruct
{
	OSIconID handle;
	OSMaskID mask;
#	if defined(ZAF_MACINTOSH)
	OSBitmapID colorBitmap;
	OSMaskID monoBitmap;
#	endif
	bool staticHandle;

	ZafIconStruct(void);
	ZafIconStruct(const ZafImageStruct &data);
	ZafIconStruct(int width, int height, ZafLogicalColor *array,
		bool staticArray);

	// --- Attributes ---
	// get
	bool StaticHandle(void) const;
	// set
	bool SetStaticHandle(bool staticHandle);
};

// --- inline functions ---
inline bool ZafIconStruct::StaticHandle(void) const { return (staticHandle); }
inline bool ZafIconStruct::SetStaticHandle(bool tStaticHandle) { staticHandle = tStaticHandle; return (staticHandle); }

// ----- ZafMouseStruct -----------------------------------------------------

struct ZAF_EXPORT ZafMouseStruct : public ZafImageStruct
{
	// --- General members ---
	int hotSpotX, hotSpotY;

	OSMouseID handle;
	OSMaskID mask;
	bool staticHandle;

	ZafMouseStruct(void);
	ZafMouseStruct(const ZafImageStruct &data);
	ZafMouseStruct(int width, int height, ZafLogicalColor *array,
		int hotSpotX, int hotSpotY, bool staticArray);

	// --- Attributes ---
	// get
	bool StaticHandle(void) const;
	// set
	bool SetStaticHandle(bool staticHandle);
};

// --- inline functions ---
inline bool ZafMouseStruct::StaticHandle(void) const { return (staticHandle); }
inline bool ZafMouseStruct::SetStaticHandle(bool tStaticHandle) { staticHandle = tStaticHandle; return (staticHandle); }

// --------------------------------------------------------------------------
// ----- ZafDisplay ---------------------------------------------------------
// --------------------------------------------------------------------------

// The following constants are used in cell size computations.
#if defined(ZAF_MSWINDOWS)
#	if defined(ZAF_MSWINDOWS_3D)
const int ZAF_BORDER_SIZE					= 2; // Window object border thickness.
#	else
const int ZAF_BORDER_SIZE					= 1; // Window object border thickness.
#	endif
#elif defined(ZAF_MACINTOSH)
const int ZAF_BORDER_SIZE					= 1; // Window object border thickness.
#elif defined(ZAF_TEXT_MODE)
const int ZAF_BORDER_SIZE                   = 1; // Window object border thickness.
#else
const int ZAF_BORDER_SIZE					= 2; // Window object border thickness.
#endif
#if defined(ZAF_MOTIF)
const int ZAF_TEXT_MARGIN_SIZE				= 4; // Space between border and text.
#elif defined(ZAF_TEXT_MODE)
const int ZAF_TEXT_MARGIN_SIZE              = 0; // Space between border and text.
#else
const int ZAF_TEXT_MARGIN_SIZE				= 2; // Space between border and text.
#endif
#if defined(ZAF_MOTIF)
const int ZAF_FOCUS_SIZE					= 2; // Space reserved for focus indicator.
#else
const int ZAF_FOCUS_SIZE					= 0; // Space reserved for focus indicator.
#endif

const int ZAF_SHADOW_SIZE					= 2; // Space required for 3D shadows.
const int ZAF_MARGIN_SIZE					= 5; // Miscillaneouse margins.
const int ZAF_EDIT_MARGIN_SIZE				= 4; // Edit mode only.

// The following are old definitions and should not be used in new development.
#define ZAF_BORDER_WIDTH ZAF_BORDER_SIZE
#define ZAF_SHADOW_WIDTH ZAF_SHADOW_SIZE
#define ZAF_TEXT_MARGIN ZAF_TEXT_MARGIN_SIZE
#define ZAF_MARGIN_WIDTH ZAF_MARGIN_SIZE
#define ZAF_EDIT_MARGIN ZAF_EDIT_MARGIN_SIZE

#if defined(ZAF_TEXT_MODE)
const ZafLogicalColor       ZAF_MAXCOLORS       = 16;
#else
const ZafLogicalColor		ZAF_MAXCOLORS		= 252;
#endif
const ZafLogicalColor 		ZAF_CLR_USER_FIRST	= 32;	// This is the first color not reserved for use by ZAF.
const ZafLogicalFont		ZAF_MAXFONTS		= 10;
const int					ZAF_MAXIMAGES		= 2;
const ZafLogicalLineStyle	ZAF_MAXLINES		= 10;
const ZafLogicalMode		ZAF_MAXMODES		= 10;
const int					ZAF_MAXPALETTES		= 127;
const ZafLogicalFillPattern	ZAF_MAXPATTERNS		= 15;

#if defined(ZAF_MOTIF)
const ZafLogicalColor		ZAF_CLR_MDIINACTIVE	= ZAF_MAXCOLORS - 2;
const ZafLogicalColor		ZAF_CLR_MDIACTIVE	= ZAF_MAXCOLORS - 1;
#endif

enum ZafHzJustify
{
	ZAF_HZ_LEFT		= 0,
	ZAF_HZ_RIGHT	= 1,
	ZAF_HZ_CENTER	= 2
};

enum ZafVtJustify
{
	ZAF_VT_TOP		= 0,
	ZAF_VT_BOTTOM	= 1,
	ZAF_VT_CENTER	= 2
};

#if defined(ZAF_TEXT_MODE)
typedef ZafUInt16 ZafScreenCell;
#endif

#if defined(ZAF_INDEPENDENT) || defined(ZAF_CURSES)
enum ZafDeviceImageType
{
	ZAF_IMT_MOUSE_IMAGE,
	ZAF_IMT_CURSOR_IMAGE
};

#   if defined(ZAF_CURSES)
#	   	if defined(SCO_UNIX)
#	    	define attrib(foreground, background) (COLOR_PAIR(foreground << 3 | background))
#	   	else
#	    	define attrib(foreground, background) (0)
#	   	endif
#   elif defined(ZAF_MSDOS)
#	   	define attrib(foreground, background) (((background) << 4) + (foreground))
#   endif
#endif

// ----- Private class definition. Do not use! ------------------------------
class ZAF_EXPORT ZafRegionElement : public ZafElement
{
public:
	// --- General members ---
	OSWindowID screenID;
	ZafRegionStruct region;

	ZafRegionElement(OSWindowID screenID, const ZafRegionStruct &_region);
	ZafRegionElement(OSWindowID screenID, int left, int top, int right,
		int bottom, ZafCoordinateType type);
	~ZafRegionElement(void);

	void Assign(OSWindowID tScreenID, int left, int top, int right,
		int bottom, ZafCoordinateType type);

	// --- Element members ---
	ZafRegionElement *Next(void) const { return ((ZafRegionElement *)next); }
	ZafRegionElement *Previous(void) const { return ((ZafRegionElement *)previous); }
};

// ----- Private class definition. Do not use! ------------------------------
class ZAF_EXPORT ZafRegionList : public ZafList
{
public:
	// --- General members ---
	ZafRegionList(void);
	~ZafRegionList(void);
	void Split(OSWindowID screenID, const ZafRegionStruct &region, int allocateBelow = false);

	ZafRegionElement *Allocate(OSWindowID tScreenID, int left, int top, int right,
		int bottom, ZafCoordinateType type);
	ZafRegionElement *Allocate(OSWindowID tScreenID, ZafRegionStruct &region);
						
	// --- List members ---
	ZafRegionElement *Current(void) const { return ((ZafRegionElement *)current); }
	virtual void Destroy(void);
	ZafRegionElement *First(void) const { return ((ZafRegionElement *)first); }
	ZafRegionElement *Last(void) const { return ((ZafRegionElement *)last); }
protected:
	ZafList freeList;

    void Deallocate(ZafElement *element);
};


// ----- Private class definition. Do not use! ------------------------------
class ZafWindowObject;
class ZafUpdateRegionElement : public ZafElement
{
public:
	ZafUpdateRegionElement(ZafWindowObject *object, ZafRegionStruct &region);
//	ZafUpdateRegionElement();

	void AddRegion(ZafRegionStruct &region);
	ZafWindowObject *Object(void);
	ZafRegionList &List(void);
//	void SetValues(ZafWindowObject *object, ZafRegionStruct &region);

	ZafUpdateRegionElement *Next(void);

protected:
	ZafRegionList list;
	ZafWindowObject *object;
};

// ----- Private class definition. Do not use! ------------------------------
class ZafUpdateRegionList
{
public:
	ZafUpdateRegionList(void);
	~ZafUpdateRegionList(void);

	void Add(ZafUpdateRegionElement *element);
	void Subtract(ZafUpdateRegionElement *element);
	void Destroy(void);
	ZafUpdateRegionElement *First(void);

protected:
		ZafList list;
};

// ----- ZafDisplay ---------------------------------------------------------

enum ZafFontWeight
{
	ZAF_FNT_WEIGHT_NORMAL,
	ZAF_FNT_WEIGHT_BOLD
};

enum ZafFontSlant
{
	ZAF_FNT_SLANT_NORMAL,
	ZAF_FNT_SLANT_ITALIC
};

enum ZafFontPitch
{
	ZAF_FNT_PITCH_DEFAULT,
	ZAF_FNT_PITCH_FIXED,
	ZAF_FNT_PITCH_VARIABLE
};

enum ZafDisplayMode
{
	ZAF_DISPLAY_MONO,
	ZAF_DISPLAY_COLOR
};

class ZAF_EXPORT ZafDisplay
{
public:
	// Display properties.
	int columns, lines;
	int pixelsPerInchX, pixelsPerInchY;
	int preSpace, postSpace;

	// Coordinate conversion values.
	int cellWidth;
	int cellHeight;
	long miniNumeratorX;
	long miniDenominatorX;
	long miniNumeratorY;
	long miniDenominatorY;

	// --- General ---
	ZafDisplay(void);
	virtual ~ZafDisplay(void);

	// --- Coordinates ---
	// get
	int CellHeight(void) const;
	int CellWidth(void) const;
	long ConvertXValue(long value, ZafCoordinateType typeIn, ZafCoordinateType typeOut) const;
	long ConvertYValue(long value, ZafCoordinateType typeIn, ZafCoordinateType typeOut) const;
	ZafCoordinateType CoordinateType(void) const;
	virtual ZafCoordinateType SetCoordinateType(ZafCoordinateType coordinateType);
	void Origin(ZafCoordinate &x, ZafCoordinate &y) const;
	virtual void SetOrigin(ZafCoordinate x, ZafCoordinate y);
	int Scale(int *scaleNumerator = ZAF_NULLP(int), int *scaleDenominator = ZAF_NULLP(int)) const;
	// set
	void SetCellSize(int cellHeight, int cellWidth);
	virtual int SetScale(int scaleNumerator, int scaleDenominator);

	// --- Drawing Primitives ---
	// bitmap
	virtual ZafError Bitmap(ZafCoordinate column, ZafCoordinate line, ZafBitmapStruct &bitmap) = 0;
	virtual ZafError ConvertToOSBitmap(ZafBitmapStruct &bitmap);
	virtual ZafError ConvertToZafBitmap(ZafBitmapStruct &bitmap);
	virtual ZafError DestroyOSBitmap(ZafBitmapStruct &bitmap);
	virtual ZafError DestroyZafBitmap(ZafBitmapStruct &bitmap);
	static ZafError InitializeOSBitmap(ZafBitmapStruct &bitmap);
	static ZafError ResetOSBitmap(ZafBitmapStruct &bitmap, const ZafBitmapStruct &copy);
	// icon
	virtual ZafError Icon(ZafCoordinate column, ZafCoordinate line, ZafIconStruct &icon) = 0;
	virtual ZafError ConvertToOSIcon(ZafIconStruct &icon);
	virtual ZafError ConvertToZafIcon(ZafIconStruct &icon);
	virtual ZafError DestroyOSIcon(ZafIconStruct &icon);
	virtual ZafError DestroyZafIcon(ZafIconStruct &icon);
	static ZafError InitializeOSIcon(ZafIconStruct &icon);
	static ZafError ResetOSIcon(ZafIconStruct &icon, const ZafIconStruct &copy);
	// mouse
	virtual ZafError Mouse(ZafCoordinate column, ZafCoordinate line, ZafMouseStruct &mouse) = 0;
	virtual ZafError ConvertToOSMouse(ZafMouseStruct &mouse);
	virtual ZafError ConvertToZafMouse(ZafMouseStruct &mouse);
	virtual ZafError DestroyOSMouse(ZafMouseStruct &mouse);
	virtual ZafError DestroyZafMouse(ZafMouseStruct &mouse);
	static ZafError InitializeOSMouse(ZafMouseStruct &mouse);
	static ZafError ResetOSMouse(ZafMouseStruct &mouse, const ZafMouseStruct &copy);
	// text
	virtual ZafError Text(ZafCoordinate left, ZafCoordinate top, const ZafIChar *text, int length = -1,
		int hotKeyIndex = -1, bool fill = false) = 0;
	ZafError Text(const ZafRegionStruct &region,
		const ZafIChar *text, int length = -1,
		ZafHzJustify hzJustify = ZAF_HZ_LEFT,
		ZafVtJustify vtJustify = ZAF_VT_CENTER,
		int hotKeyIndex = -1, bool fill = false)
	{ return (Text(region.left, region.top, region.right, region.bottom,
		text, length, hzJustify, vtJustify, hotKeyIndex, fill)); }
	virtual ZafError Text(ZafCoordinate left, ZafCoordinate top, ZafCoordinate right, ZafCoordinate bottom,
		const ZafIChar *text, int length = -1,
		ZafHzJustify hzJustify = ZAF_HZ_LEFT,
		ZafVtJustify vtJustify = ZAF_VT_CENTER,
		int hotKeyIndex = -1, bool fill = false) = 0;
	virtual ZafRegionStruct TextSize(const ZafIChar *text, int length = -1) = 0;
	// graphics
	virtual ZafError Ellipse(ZafCoordinate left, ZafCoordinate top, ZafCoordinate right, ZafCoordinate bottom,
		float startAngle, float endAngle, int width = ZAF_HAIR_LINE, bool fill = false) = 0;
	virtual ZafError Line(ZafCoordinate column1, ZafCoordinate line1, ZafCoordinate column2, ZafCoordinate line2,
		int width = ZAF_HAIR_LINE) = 0;
	virtual ZafError Pixel(ZafCoordinate column, ZafCoordinate line,
		ZafLogicalColor color = ZAF_CLR_DEFAULT, ZafLogicalColor mono = ZAF_MONO_DEFAULT) = 0;
	virtual ZafError Polygon(int numPoints, const ZafCoordinate *polygonPoints,
		int width = ZAF_HAIR_LINE, bool fill = false, bool close = false) = 0;
	ZafError Rectangle(const ZafRegionStruct &region, int width = ZAF_HAIR_LINE,
		bool fill = false)
	{ return (Rectangle(region.left, region.top, region.right, region.bottom, width, fill)); }
	virtual ZafError Rectangle(ZafCoordinate left, ZafCoordinate top, ZafCoordinate right, ZafCoordinate bottom,
		int width = ZAF_HAIR_LINE, bool fill = false) = 0;
	virtual ZafError RegionCopy(const ZafRegionStruct &oldRegion,
		int newColumn, int newLine) = 0;
	virtual ZafError RectangleXORDiff(const ZafRegionStruct *oldRegion,
		const ZafRegionStruct *newRegion) = 0;

	// --- Drawing support ---
	virtual ZafDisplayMode DisplayMode(void) const;
	// get
	virtual ZafLogicalColor Background(void) const;
	virtual ZafRegionStruct ClipRegion(void) const;
	virtual ZafLogicalFont Font(void) const;
	virtual ZafLogicalColor Foreground(void) const;
	virtual ZafLogicalMode Mode(void) const;
	virtual ZafLogicalColor MonoBackground(void) const;
	virtual ZafLogicalColor MonoForeground(void) const;
	virtual ZafPaletteStruct Palette(void) const;
	virtual ZafLogicalFillPattern FillPattern(void) const;
	virtual ZafLogicalLineStyle LineStyle(void) const;
	// set
	virtual ZafLogicalColor SetBackground(ZafLogicalColor color);
	virtual ZafRegionStruct SetClipRegion(const ZafRegionStruct &region);
	virtual ZafLogicalFont SetFont(ZafLogicalFont font);
	virtual ZafLogicalColor SetForeground(ZafLogicalColor color);
	virtual ZafLogicalLineStyle SetLineStyle(ZafLogicalLineStyle line);
	virtual ZafLogicalMode SetMode(ZafLogicalMode mode);
	virtual ZafLogicalColor SetMonoBackground(ZafLogicalColor color);
	virtual ZafLogicalColor SetMonoForeground(ZafLogicalColor color);
	virtual ZafPaletteStruct SetPalette(ZafPaletteStruct palette);
	virtual ZafLogicalFillPattern SetFillPattern(ZafLogicalFillPattern pattern);

	// --- Table support ---
	virtual ZafLogicalColor AddColor(ZafLogicalColor index, ZafUInt8 red, ZafUInt8 green, ZafUInt8 blue) = 0;
	virtual ZafLogicalFont AddFont(ZafLogicalFont index, char *fontFamily, int pointSize,
		ZafFontWeight weight = ZAF_FNT_WEIGHT_NORMAL,
		ZafFontSlant slant = ZAF_FNT_SLANT_NORMAL,
		ZafFontPitch pitch = ZAF_FNT_PITCH_DEFAULT) = 0;
	virtual ZafError DestroyColor(ZafLogicalColor color) = 0;
	virtual ZafError DestroyFont(ZafLogicalFont font) = 0;
	virtual ZafError ColorInfo(ZafLogicalColor index, ZafUInt8 &red, ZafUInt8 &green, ZafUInt8 &blue) = 0;
	virtual ZafError FontInfo(ZafLogicalFont index, char *fontFamily, int bufferSize,
		int *pointSize, ZafFontWeight *weight = ZAF_NULLP(ZafFontWeight),
		ZafFontSlant *slant = ZAF_NULLP(ZafFontSlant),
		ZafFontPitch *pitch = ZAF_NULLP(ZafFontPitch),
		ZafCoordinate *averageCharWidth = ZAF_NULLP(ZafCoordinate),
		ZafCoordinate *height = ZAF_NULLP(ZafCoordinate),
		ZafCoordinate *leading = ZAF_NULLP(ZafCoordinate)) = 0;

	// --- Class identification ---
	static ZafClassNameChar ZAF_FARDATA displayType[];
	virtual ZafClassName DisplayType(void) const;

	// --- ScreenOS specific support members ---
	virtual ZafError BeginDraw(OSDisplayContext displayContext,
		OSDrawContext drawContext, const ZafRegionStruct &draw,
		const ZafRegionStruct &clip) = 0;
	virtual ZafError EndDraw(void) = 0;
	virtual OSDisplayContext DisplayContext(void) const = 0;
	virtual OSDrawContext DrawContext(void) const = 0;
	virtual OSDisplayContext RestoreDisplayContext(void) = 0;
	virtual OSDrawContext RestoreDrawContext(void) = 0;
	virtual OSDisplayContext SetDisplayContext(OSDisplayContext context) = 0;
	virtual OSDrawContext SetDrawContext(OSDrawContext context) = 0;

#if defined(ZAF_INDEPENDENT) || defined(ZAF_CURSES)
	virtual void SetDrawRegions(ZafRegionList *drawList,
		bool destroyDrawList = true);
#endif
protected:
	// --- General members ---
	ZafCoordinateType coordinateType;
	ZafDisplayMode displayMode;
	ZafLogicalMode mode;
	ZafCoordinate originX, originY;
	int scaleNumerator, scaleDenominator;
	ZafRegionStruct clipRegion;
	ZafPaletteStruct palette;
};

inline int ZafDisplay::CellHeight(void) const { return (cellHeight); }
inline int ZafDisplay::CellWidth(void) const { return (cellWidth); }
inline ZafCoordinateType ZafDisplay::CoordinateType(void) const { return (coordinateType); }
inline void ZafDisplay::SetCellSize(int setCellHeight, int setCellWidth)
{ cellHeight = setCellHeight; cellWidth = setCellWidth; }

extern ZAF_EXPORT ZafDisplay *zafDisplay;

#endif // Z_DSP_HPP

