//-----------------------------------------------------------------------------
// VST Plug-Ins SDK
// VSTGUI: Graphical User Interface Framework for VST plugins : 
//
// Version 3.0       $Date: 2006/02/08 17:31:19 $ 
//
// Added Motif/Windows vers.: Yvan Grabit              01.98
// Added Mac version        : Charlie Steinberg        02.98
// Added BeOS version       : Georges-Edouard Berenger 05.99
// Added new functions      : Matthias Juwan           12.01
// Added MacOSX version     : Arne Scheffler           02.03
// Added Quartz stuff		: Arne Scheffler           08.03
// Added Win Alpha Blending : Arne Scheffler           04.04
//
//-----------------------------------------------------------------------------
// VSTGUI LICENSE
// © 2004, Steinberg Media Technologies, All Rights Reserved
//-----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
// 
//   * Redistributions of source code must retain the above copyright notice, 
//     this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation 
//     and/or other materials provided with the distribution.
//   * Neither the name of the Steinberg Media Technologies nor the names of its
//     contributors may be used to endorse or promote products derived from this 
//     software without specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A  PARTICULAR PURPOSE ARE DISCLAIMED. 
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------

#ifndef __vstgui__
#include "vstgui.h"
#endif

#if !PLUGGUI
#ifndef __audioeffectx__
#include "audioeffectx.h"
#endif
#endif

#include "vstkeycode.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

//---Some defines-------------------------------------
#define USE_ALPHA_BLEND			QUARTZ || USE_LIBPNG
#define USE_CLIPPING_DRAWRECT	1
#define MAC_OLD_DRAG			1
#define NEW_UPDATE_MECHANISM	1
#define USE_VST_WINDOW			(!PLUGGUI && !VST_FORCE_DEPRECATED)

#if !WINDOWS
// For OS which allows a lot of Drawing contexts
#define USE_GLOBAL_CONTEXT 1
#endif

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#if USE_NAMESPACE
#define VSTGUI_CFrame				VSTGUI::CFrame
#define VSTGUI_CPoint				VSTGUI::CPoint
#define VSTGUI_CTextEdit			VSTGUI::CTextEdit
#define VSTGUI_CColor				VSTGUI::CColor
#define VSTGUI_CDrawContext			VSTGUI::CDrawContext
#define VSTGUI_COffscreenContext	VSTGUI::COffscreenContext
#define VSTGUI_COptionMenu			VSTGUI::COptionMenu
#define VSTGUI_COptionMenuScheme	VSTGUI::COptionMenuScheme
#define VSTGUI_CDragContainer		VSTGUI::CDragContainer
#else
#define VSTGUI_CFrame     CFrame
#define VSTGUI_CPoint     CPoint
#define VSTGUI_CTextEdit  CTextEdit
#define VSTGUI_CColor     CColor
#define VSTGUI_CDrawContext CDrawContext
#define VSTGUI_COffscreenContext COffscreenContext
#define VSTGUI_COptionMenu COptionMenu
#define VSTGUI_COptionMenuScheme COptionMenuScheme
#define VSTGUI_CDragContainer	CDragContainer
#endif

static VSTGUI_CDragContainer* gDragContainer = 0;

//---For Debugging------------------------
#if DEBUG

long gNbCBitmap = 0;
long gNbCView = 0;
long gNbCDrawContext = 0;
long gNbCOffscreenContext = 0;
long gBitmapAllocation = 0;
long gNbDC = 0;

#include <stdarg.h>

void DebugPrint (char *format, ...);
void DebugPrint (char *format, ...)
{
	char string[300];
	va_list marker;
	va_start (marker, format);
	vsprintf (string, format, marker);
	if (!string)
		strcpy (string, "Empty string\n");
	#if WINDOWS
	OutputDebugString (string);
	#elif MAC && !MACX
	Str255 pStr;
	c2pstrcpy (pStr, string);
	DebugStr (pStr);
	#else
	fprintf (stderr, string);
	#endif
}
#endif
//---End For Debugging------------------------

#if WINDOWS
static bool bSwapped_mouse_buttons = false; 
OSVERSIONINFOEX	gSystemVersion;

// Alpha blending for Windows using library : msimg32.dll
#define DYNAMICALPHABLEND   1

#define WIN32_LEAN_AND_MEAN 1
#include <windows.h>
#include <shlobj.h>
#include <shellapi.h>
#include <zmouse.h>
#include <commdlg.h>

#if DYNAMICALPHABLEND
typedef  BOOL (WINAPI *PFNALPHABLEND)(
  HDC hdcDest,                 // handle to destination DC
  int nXOriginDest,            // x-coord of upper-left corner
  int nYOriginDest,            // y-coord of upper-left corner
  int nWidthDest,              // destination width
  int nHeightDest,             // destination height
  HDC hdcSrc,                  // handle to source DC
  int nXOriginSrc,             // x-coord of upper-left corner
  int nYOriginSrc,             // y-coord of upper-left corner
  int nWidthSrc,               // source width
  int nHeightSrc,              // source height
  BLENDFUNCTION blendFunction  // alpha-blending function
);

PFNALPHABLEND pfnAlphaBlend = NULL;

typedef	BOOL (WINAPI *PFNTRANSPARENTBLT)(
  HDC hdcDest,        // handle to destination DC
  int nXOriginDest,   // x-coord of destination upper-left corner
  int nYOriginDest,   // y-coord of destination upper-left corner
  int nWidthDest,     // width of destination rectangle
  int hHeightDest,    // height of destination rectangle
  HDC hdcSrc,         // handle to source DC
  int nXOriginSrc,    // x-coord of source upper-left corner
  int nYOriginSrc,    // y-coord of source upper-left corner
  int nWidthSrc,      // width of source rectangle
  int nHeightSrc,     // height of source rectangle
  UINT crTransparent  // color to make transparent
);

PFNTRANSPARENTBLT	pfnTransparentBlt = NULL;
#endif

#if PLUGGUI
	extern HINSTANCE ghInst;
	inline HINSTANCE GetInstance () { return ghInst; }
#else
	extern void* hInstance;
	inline HINSTANCE GetInstance () { return (HINSTANCE)hInstance; }
#endif

static long   gUseCount = 0;
static char   gClassName[100] = {0};
static bool   InitWindowClass ();
static void   ExitWindowClass ();
LONG_PTR WINAPI WindowProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

static HANDLE CreateMaskBitmap (CDrawContext* pContext, CRect& rect, CColor transparentColor);
static void   DrawTransparent (CDrawContext* pContext, CRect& rect, const CPoint& offset, HDC hdcBitmap, POINT ptSize, HBITMAP pMask, COLORREF color);
static bool   checkResolveLink (const char* nativePath, char* resolved);
static void   *createDropTarget (VSTGUI_CFrame* pFrame);

BEGIN_NAMESPACE_VSTGUI
long        gStandardFontSize[] = { 12, 18, 14, 12, 11, 10, 9, 13 };
const char* gStandardFontName[] = {
	"Arial", "Arial", "Arial", 
	"Arial", "Arial", "Arial", 
	"Arial", "Symbol" };
END_NAMESPACE_VSTGUI

#if USE_LIBPNG
#include "png.h"
#endif

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#elif MOTIF

 #define USE_XPM     0
 #define TEST_REGION 0

 #if USE_XPM
  #include <X11/xpm.h>
 #endif

 #include <X11/Xlib.h>
 #include <Xm/DrawingA.h>
 #include <assert.h>
 #include <Xm/MwmUtil.h>
 #include <Xm/DialogS.h>
 #include <time.h>

 #if SGI
   #include <sys/syssgi.h>
 #elif SUN
 #elif LINUX
 #endif

 #define XDRAWPARAM pDisplay, (Window)pWindow, (GC)pSystemContext
 #define XWINPARAM  pDisplay, (Window)pWindow
 #define XGCPARAM   pDisplay, (GC)pSystemContext

// init the static variable about font
bool gFontInit = false;
XFontStruct *gFontStructs[] = {0, 0, 0, 0, 0, 0, 0};

struct SFontTable {char* name; char* string;};

static SFontTable gFontTable[] = {
  {"SystemFont",        "-adobe-helvetica-bold-r-*-*-12-*-*-*-*-*-*-*"},   // kSystemFont
  {"NormalFontVeryBig", "-adobe-helvetica-medium-r-*-*-18-*-*-*-*-*-*-*"}, // kNormalFontVeryBig
  {"NormalFontBig",     "-adobe-helvetica-medium-r-normal-*-14-*-*-*-*-*-*-*"}, // kNormalFontBig
  {"NormalFont",        "-adobe-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*"}, // kNormalFont
  {"NormalFontSmall",   "-adobe-helvetica-medium-r-*-*-10-*-*-*-*-*-*-*"}, // kNormalFontSmall
  {"NormalFontSmaller", "-adobe-helvetica-medium-r-*-*-9-*-*-*-*-*-*-*"},  // kNormalFontSmaller
  {"NormalFontVerySmall", "-adobe-helvetica-medium-r-*-*-8-*-*-*-*-*-*-*"}, // kNormalFontVerySmall
  {"SymbolFont",        "-adobe-symbol-medium-r-*-*-12-*-*-*-*-*-*-*"}     // kSymbolFont
};

long gStandardFontSize[] = { 12, 16, 14, 12, 10, 9, 8, 10 };

//-----------------------------------------------------------------------------
// declaration of different local functions
long convertPoint2Angle (CPoint &pm, CPoint &pt);

// callback for the frame
void _drawingAreaCallback (Widget widget, XtPointer clientData, XtPointer callData);
void _eventHandler (Widget w, XtPointer clientData, XEvent *event, char *p);
void _destroyCallback (Widget widget, XtPointer clientData, XtPointer callData);

// stuff for color
long getIndexColor8Bit (CColor color, Display *pDisplay, Colormap colormap);
long CDrawContext::nbNewColor = 0;
static CColor paletteNewColor[256];

//------ our user-defined XPM functions
bool xpmGetValues (char **ppDataXpm, long *pWidth, long *pHeight, long *pNcolor, long *pCpp);

 #if !USE_XPM
  #include "xpmloader.cpp"
 #endif

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#elif MAC
BEGIN_NAMESPACE_VSTGUI

long pSystemVersion;

#if MACX
//-----------------------------------------------------------------------------
#include <QuickTime/QuickTime.h>

#if QUARTZ
const char* gMacXfontNames[] = {
	"Helvetica",
	"Helvetica",
	"Helvetica",
	"Helvetica",
	"Helvetica",
	"Helvetica",
	"Helvetica",
	"Symbol"
};

#ifndef M_PI
#define	M_PI		3.14159265358979323846	/* pi */
#endif

static inline void QuartzSetLineDash (CGContextRef context, CLineStyle style, CCoord lineWidth);
static inline void QuartzSetupClip (CGContextRef context, const CRect clipRect);
static inline double radians (double degrees) { return degrees * M_PI / 180; }
CGColorSpaceRef GetGenericRGBColorSpace ();

typedef void (*CGContextStrokeLineSegmentsProc) (CGContextRef c, const CGPoint points[], size_t count);
typedef CGImageRef (*CGImageCreateWithImageInRectProc) (CGImageRef image, CGRect rect);
static CGImageCreateWithImageInRectProc _CGImageCreateWithImageInRect = NULL;
static CGContextStrokeLineSegmentsProc _CGContextStrokeLineSegments = NULL;

// cache graphics importer
static ComponentInstance bmpGI = 0;
static ComponentInstance pngGI = 0;
static ComponentInstance jpgGI = 0;
static ComponentInstance pictGI = 0;


#else
const unsigned char* gMacXfontNames[] = {
	"\pArial",
	"\pArial",
	"\pArial",
	"\pArial",
	"\pArial",
	"\pArial",
	"\pArial",
	"\pSymbol"
};
#endif

//-----------------------------------------------------------------------------
#else
#include <QDOffscreen.h>
#include <StandardFile.h>
#include <Navigation.h>
#include <PictUtils.h>
#endif

long gStandardFontSize[] = { 12, 18, 14, 12, 10, 9, 9, 12 };

long convertPoint2Angle (CPoint &pm, CPoint &pt);
void RectNormalize (Rect& rect);
void CRect2Rect (const CRect &cr, Rect &rr);
void Rect2CRect (Rect &rr, CRect &cr);
void CColor2RGBColor (const CColor &cc, RGBColor &rgb);
void RGBColor2CColor (const RGBColor &rgb, CColor &cc);

#if MAC_OLD_DRAG
static void install_drop (CFrame *frame);
static void remove_drop (CFrame *frame);
#endif

//-----------------------------------------------------------------------------
void RectNormalize (Rect& rect)
{
	if (rect.left > rect.right)
	{
		long temp = rect.right;
		rect.right = rect.left;
		rect.left = temp;
	}
	if (rect.top > rect.bottom)
	{
		long temp = rect.bottom;
		rect.bottom = rect.top;
		rect.top = temp;
	}
}

//-----------------------------------------------------------------------------
void CRect2Rect (const CRect &cr, Rect &rr)
{
	rr.left   = (short)cr.left;
	rr.right  = (short)cr.right;
	rr.top    = (short)cr.top;
	rr.bottom = (short)cr.bottom;
	RectNormalize (rr);
}

//-----------------------------------------------------------------------------
void Rect2CRect (Rect &rr, CRect &cr)
{
	cr.left   = rr.left;
	cr.right  = rr.right;
	cr.top    = rr.top;
	cr.bottom = rr.bottom;
}

//-----------------------------------------------------------------------------
void CColor2RGBColor (const CColor &cc, RGBColor &rgb)
{
	rgb.red   = cc.red   * 257;
	rgb.green = cc.green * 257;
	rgb.blue  = cc.blue  * 257;
}

//-----------------------------------------------------------------------------
void RGBColor2CColor (const RGBColor &rgb, CColor &cc)
{
	cc.red   = rgb.red   / 257;
	cc.green = rgb.green / 257;
	cc.blue  = rgb.blue  / 257;
}

END_NAMESPACE_VSTGUI
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#elif BEOS

#include <TranslationUtils.h>
#include <Resources.h>
#include <Bitmap.h>
#include <Region.h>
#include <View.h>
#include <Window.h>
#include <Message.h>
#include <Entry.h>
#include <Path.h>

//--------------------------
class PlugView: public BView
{
public:
	PlugView (BRect frame, CFrame* cframe);
	void Draw (BRect updateRect);
	void MouseDown (BPoint where);
	void MessageReceived (BMessage *msg);
private:
	CFrame*	cframe;
};

long convertPoint2Angle (CPoint &pm, CPoint &pt);

drawing_mode modeToPlatform [] = {
//  kCopyMode  kOrMode    kXorMode
	B_OP_COPY, B_OP_OVER, B_OP_INVERT
};

long gStandardFontSize[] = { 12, 18, 14, 12, 11, 10, 9, 12 };
const char*	standardFont  = "Swis721 BT";
const char* standardFontS = "Roman";
const char* systemFont    = "Swis721 BT";
const char* systemFontS   = "Bold";
const char* gStandardFontName[] = { systemFont,
	standardFont, standardFont, standardFont, standardFont, standardFont,
	standardFont };
const char* gStandardFontStyle[] = { systemFontS,
	standardFontS, standardFontS, standardFontS, standardFontS, standardFontS,
	standardFontS };
#endif

//-----------------------------------------------------------------------------
bool CRect::pointInside (const CPoint& where) const
{
	return where.h >= left && where.h < right && where.v >= top && where.v < bottom;
}

//-----------------------------------------------------------------------------
bool CRect::isEmpty () const 
{
	if (right <= left)
		return true;
	if (bottom <= top)
		return true;
	return false;
}

//-----------------------------------------------------------------------------
void CRect::bound (const CRect& rect)
{
	if (left < rect.left)
		left = rect.left;
	if (top < rect.top)
		top = rect.top;
	if (right > rect.right)
		right = rect.right;
	if (bottom > rect.bottom)
		bottom = rect.bottom;
	if (bottom < top)
		bottom = top;
	if (right < left)
		right = left;
}

BEGIN_NAMESPACE_VSTGUI

CColor kTransparentCColor = {255, 255, 255, 0};
CColor kBlackCColor  = {0,     0,   0, 255};
CColor kWhiteCColor  = {255, 255, 255, 255};
CColor kGreyCColor   = {127, 127, 127, 255};
CColor kRedCColor    = {255,   0,   0, 255};
CColor kGreenCColor  = {0  , 255,   0, 255};
CColor kBlueCColor   = {0  ,   0, 255, 255};
CColor kYellowCColor = {255, 255,   0, 255};
CColor kMagentaCColor= {255,   0, 255, 255};
CColor kCyanCColor   = {0  , 255, 255, 255};

#define kDragDelay 0

//-----------------------------------------------------------------------------
// CDrawContext Implementation
//-----------------------------------------------------------------------------
/**
 * CDrawContext constructor.
 * @param inFrame the parent CFrame
 * @param inSystemContext the platform system context, can be NULL
 * @param inWindow the platform window object
 */
CDrawContext::CDrawContext (CFrame *inFrame, void *inSystemContext, void *inWindow)
: pSystemContext (inSystemContext)
, pWindow (inWindow)
, pFrame (inFrame)
, fontSize (-1)
, fontStyle (0)
, fontId (kNumStandardFonts)
, frameWidth (0)
, lineStyle (kLineOnOffDash)
, drawMode (kAntialias)
#if WINDOWS
, pBrush (0), pFont (0), pPen (0)
, pOldBrush (0), pOldFont (0), pOldPen (0)
#elif MAC && !QUARTZ
, bInitialized (false)
#endif
{
	#if DEBUG
	gNbCDrawContext++;
	#endif

	// initialize values
	if (pFrame)
		pFrame->getViewSize (clipRect);
	else
		clipRect (0, 0, 1000, 1000);

	const CColor notInitalized = {0, 0, 0, 0};
	frameColor = notInitalized;
	fillColor  = notInitalized;
	fontColor  = notInitalized;

	// offsets use by offscreen
	offset (0, 0);
	offsetScreen (0, 0);

#if WINDOWS
	pHDC = 0;
	if (!pSystemContext && pWindow)
		pSystemContext = pHDC = GetDC ((HWND)pWindow);

	if (pSystemContext)
	{
		pOldBrush  = GetCurrentObject ((HDC)pSystemContext, OBJ_BRUSH);
		pOldPen    = GetCurrentObject ((HDC)pSystemContext, OBJ_PEN);
		pOldFont   = GetCurrentObject ((HDC)pSystemContext, OBJ_FONT);
		SetBkMode ((HDC)pSystemContext, TRANSPARENT);
	}
	iPenStyle = PS_SOLID;

	// get position 
	if (pWindow)
	{
		RECT  rctTempWnd;
		GetWindowRect ((HWND)pWindow, &rctTempWnd);
		offsetScreen.h = rctTempWnd.left;
		offsetScreen.v = rctTempWnd.top;
	}

#elif MAC
	#if QUARTZ
	if (pFrame && (pSystemContext || pWindow))
	{
		HIRect bounds;
		HIViewGetFrame ((HIViewRef)pFrame->getPlatformControl (), &bounds);
		if (pWindow || !pSystemContext)
		{
			WindowAttributes attr;
			GetWindowAttributes ((WindowRef)pWindow, &attr);
			if (attr & kWindowCompositingAttribute)
			{
				HIViewRef contentView;
				HIViewFindByID (HIViewGetRoot ((WindowRef)pWindow), kHIViewWindowContentID, &contentView);
				if (HIViewGetSuperview ((HIViewRef)pFrame->getPlatformControl ()) != contentView)
					HIViewConvertRect (&bounds, (HIViewRef)pFrame->getPlatformControl (), contentView);
				bounds.origin.x += pFrame->hiScrollOffset.x;
				bounds.origin.y += pFrame->hiScrollOffset.y;
			}
		}
		offsetScreen.x = (CCoord)bounds.origin.x;
		offsetScreen.y = (CCoord)bounds.origin.y;
		clipRect (0, 0, (CCoord)bounds.size.width, (CCoord)bounds.size.height);
		clipRect.offset (pFrame->hiScrollOffset.x, pFrame->hiScrollOffset.y);
	}
	gCGContext = 0;
	if (pSystemContext)
	{
		gCGContext = (CGContextRef) pSystemContext;
		CGContextSaveGState (gCGContext); // save the original state
		CGContextScaleCTM (gCGContext, 1, -1);
		CGContextSetShouldAntialias (gCGContext, false);
		CGContextSetFillColorSpace (gCGContext, GetGenericRGBColorSpace ());
		CGContextSetStrokeColorSpace (gCGContext, GetGenericRGBColorSpace ()); 
		CGContextSaveGState (gCGContext);
		setClipRect (clipRect);
		if (pFrame)
			pFrame->setDrawContext (this);
	}
	else if (pWindow)
	{
		GrafPtr port = GetWindowPort ((WindowRef)pWindow);
		OSStatus err = QDBeginCGContext (port, &gCGContext);
		if (err == noErr)
		{
			CGContextSaveGState (gCGContext); // save the original state
			SyncCGContextOriginWithPort (gCGContext, port);
			Rect rect;
			GetPortBounds (port, &rect);
			CGContextTranslateCTM (gCGContext, 0, rect.bottom - rect.top);
			CGContextTranslateCTM (gCGContext, offsetScreen.x, -offsetScreen.y);
			CGContextTranslateCTM (gCGContext, -pFrame->hiScrollOffset.x, pFrame->hiScrollOffset.y);
			CGContextSetShouldAntialias (gCGContext, false);
			CGContextSetFillColorSpace (gCGContext, GetGenericRGBColorSpace ());
			CGContextSetStrokeColorSpace (gCGContext, GetGenericRGBColorSpace ());
			CGContextScaleCTM (gCGContext, 1, -1);
			QuartzSetupClip (gCGContext, clipRect);
			CGContextScaleCTM (gCGContext, 1, -1);
			CGContextSaveGState (gCGContext);
			setClipRect (clipRect);
			if (pFrame)
				pFrame->setDrawContext (this);
		}
	}
	if (gCGContext)
	{
		CGAffineTransform cgCTM = CGAffineTransformMake (1.0, 0.0, 0.0, -1.0, 0.0, 0.0);
		CGContextSetTextMatrix (gCGContext, cgCTM);
	}
	needToSynchronizeCGContext = false;

	#else
	pSystemContext = pWindow;

	#endif
	
#elif MOTIF 
	if (pFrame)
		pDisplay = pFrame->getDisplay ();
	
	// set the current font
	if (pSystemContext)
		setFont (kNormalFont);
	else
		fprintf (stderr, "Error in CDrawContext::CDrawContext : pSystemContext must not be Null!!!\n");

#elif BEOS
	pView = (BView*) pSystemContext;
	if (pView)
		pView->LockLooper ();

#endif

	if (1 || pSystemContext)
	{
		// set the default values
		setFrameColor (kWhiteCColor);
		setLineStyle (kLineSolid);
		setLineWidth (1);
#if !MOTIF
		setFillColor (kBlackCColor);
		setFontColor (kWhiteCColor);
#endif
		setFont (kSystemFont);
		setDrawMode (kCopyMode);
	}
}

//-----------------------------------------------------------------------------
CDrawContext::~CDrawContext ()
{
	#if DEBUG
	gNbCDrawContext--;
	#endif

#if WINDOWS
	if (pOldBrush)
		SelectObject ((HDC)pSystemContext, pOldBrush);
	if (pOldPen)
		SelectObject ((HDC)pSystemContext, pOldPen);
	if (pOldFont)
		SelectObject ((HDC)pSystemContext, pOldFont);
	
	if (pBrush)
		DeleteObject (pBrush);
	if (pPen)
		DeleteObject (pPen);
	if (pFont)
		DeleteObject (pFont);
  
	if (pHDC)
	{
		ReleaseDC ((HWND)pWindow, pHDC);
		#if DEBUG
		gNbDC--;
		#endif
	}

#elif (MAC && QUARTZ)
	if (gCGContext)
	{
		CGContextRestoreGState (gCGContext); // restore the original state
		CGContextRestoreGState (gCGContext); // we need to do it twice !!!
		CGContextSynchronize (gCGContext);
		if (!pSystemContext && pWindow)
			QDEndCGContext (GetWindowPort ((WindowRef)pWindow), &gCGContext);
		if (pFrame)
			pFrame->setDrawContext (0);
	}
#elif MOTIF
#elif BEOS
	if (pView)
	{
		pView->Flush ();
		pView->UnlockLooper ();
	}
#endif
}

//-----------------------------------------------------------------------------
void CDrawContext::setLineStyle (CLineStyle style)
{
	if (lineStyle == style)
		return;

	lineStyle = style;

#if WINDOWS
	switch (lineStyle) 
	{
	case kLineOnOffDash: 
		iPenStyle = PS_DOT;
		break;
	default:
		iPenStyle = PS_SOLID;
		break;
	}
	
	LOGPEN logPen = {iPenStyle, {frameWidth, frameWidth}, 
					 RGB (frameColor.red, frameColor.green, frameColor.blue)};
	
	HANDLE newPen = CreatePenIndirect (&logPen);
	SelectObject ((HDC)pSystemContext, newPen);
	if (pPen)
		DeleteObject (pPen);
	pPen = newPen;

#elif MAC
	#if QUARTZ

	// nothing to do here

	#else
	CGrafPtr OrigPort;
	GDHandle OrigDevice;
	if (pWindow)
	{
		GetGWorld (&OrigPort, &OrigDevice);
		SetGWorld (getPort (), NULL);
		PenState penState;
		GetPenState (&penState);
		switch (lineStyle) 
		{
		case kLineOnOffDash:
			StuffHex (&penState.pnPat, "\pF0F0F0F00F0F0F0F"); // dashed line 4 pixel
			break;
		default:
			StuffHex (&penState.pnPat, "\pFFFFFFFFFFFFFFFF");
			break;
		}
		SetPenState (&penState);
		SetGWorld (OrigPort, OrigDevice);
	}
	#endif

#elif MOTIF
	long line_width;
	long line_style;
	if (frameWidth == 1)
		line_width = 0;
	else 
		line_width = frameWidth;

	switch (lineStyle)
	{
	case kLineOnOffDash:
		line_style = LineOnOffDash;
		break;
	default:
		line_style = LineSolid;
		break;
	}
	
	XSetLineAttributes (XGCPARAM, line_width, line_style, CapNotLast, JoinRound);
#endif
}

//-----------------------------------------------------------------------------
void CDrawContext::setLineWidth (CCoord width)
{
	if (frameWidth == width)
		return;

	frameWidth = width;
	
#if WINDOWS
	LOGPEN logPen = {iPenStyle, {frameWidth, frameWidth},
					 RGB (frameColor.red, frameColor.green, frameColor.blue)};
	
	HANDLE newPen = CreatePenIndirect (&logPen);
	SelectObject ((HDC)pSystemContext, newPen);
	if (pPen)
		DeleteObject (pPen);
	pPen = newPen;
	
#elif MAC
	#if QUARTZ
	if (gCGContext)
		CGContextSetLineWidth (gCGContext, width);
	#else
	CGrafPtr OrigPort;
	GDHandle OrigDevice;
	if (pWindow)
	{
		GetGWorld (&OrigPort, &OrigDevice);
		SetGWorld (getPort (), NULL);
		PenState penState;
		GetPenState (&penState);
		penState.pnSize.h = width;
		penState.pnSize.v = width;
		SetPenState (&penState);
		SetGWorld (OrigPort, OrigDevice);
	}
	#endif
#elif MOTIF
	setLineStyle (lineStyle);
#endif
}

//-----------------------------------------------------------------------------
void CDrawContext::setDrawMode (CDrawMode mode)
{
	if (drawMode == mode)
		return;

	drawMode = mode;

#if WINDOWS
	long iMode = 0;
	switch (drawMode) 
	{
	case kXorMode :
		iMode = R2_NOTXORPEN; // Pixel is the inverse of the R2_XORPEN color (final pixel = ~ (pen ^ screen pixel)).
		break;
	case kOrMode :
		iMode = R2_MERGEPEN; // Pixel is a combination of the pen color and the screen color (final pixel = pen | screen pixel).
		break;
	default:
		iMode = R2_COPYPEN;
		break;
	}
	SetROP2 ((HDC)pSystemContext, iMode);

#elif MAC
	#if QUARTZ
	// quartz only support antialias
	if (gCGContext)
			CGContextSetShouldAntialias (gCGContext, drawMode == kAntialias ? true : false);

	#else
	if (pWindow)
	{
		CGrafPtr OrigPort;
		GDHandle OrigDevice;
		GetGWorld (&OrigPort, &OrigDevice);
		SetGWorld (getPort (), NULL);
		long iMode = 0;

		switch (drawMode) 
		{
		case kXorMode :
			iMode = patXor;
			break;
		case kOrMode :
			iMode = patOr;
			break;
		default:
			iMode = patCopy;
		}
		PenMode (mode);
		
		SetGWorld (OrigPort, OrigDevice);
	}
	#endif

#elif MOTIF
	long iMode = 0;
	switch (drawMode) 
	{
	case kXorMode :
		iMode = GXinvert;
		break;
	case kOrMode :
		iMode = GXor;
		break;
	default:
		iMode = GXcopy;
	}
	((XGCValues*)pSystemContext)->function = iMode;
	XChangeGC (XGCPARAM, GCFunction, (XGCValues*)pSystemContext);
#endif
}

//------------------------------------------------------------------------------
void CDrawContext::setClipRect (const CRect &clip)
{
	CRect _clip (clip);
	_clip.offset (offset.h, offset.v);

	if (clipRect == _clip)
		return;

	clipRect = _clip;

#if MAC
	#if QUARTZ
	if (0 && gCGContext)
	{
		CGContextRestoreGState (gCGContext);
		CGContextSaveGState (gCGContext);
		CGContextScaleCTM (gCGContext, 1, -1);
		CGRect cgClipRect = CGRectMake (clipRect.left, clipRect.top, clipRect.width ()-1.f, clipRect.height ()-1.f);
		CGContextClipToRect (gCGContext, cgClipRect);
		CGContextScaleCTM (gCGContext, 1, -1);
		setLineWidth (frameWidth);
		setLineStyle (lineStyle);
		setFrameColor (frameColor);
		setFillColor (fillColor);
		setFont (fontId, fontSize);
		setDrawMode (drawMode);
	}
	
	#else
	Rect r;
	CRect2Rect (_clip, r);

	CGrafPtr OrigPort;
	GDHandle OrigDevice;
	GetGWorld (&OrigPort, &OrigDevice);
	SetGWorld (getPort (), NULL);
	ClipRect (&r);
	SetGWorld (OrigPort, OrigDevice);
	#endif

#elif WINDOWS
	RECT r = {clipRect.left, clipRect.top, clipRect.right, clipRect.bottom};
	HRGN hRgn  = CreateRectRgn (r.left, r.top, r.right, r.bottom);
	SelectClipRgn ((HDC)pSystemContext, hRgn);
	DeleteObject (hRgn);

#elif MOTIF
	XRectangle r;
	r.x = 0;
	r.y = 0;
	r.width  = clipRect.right - clipRect.left;
	r.height = clipRect.bottom - clipRect.top;
	XSetClipRectangles (XGCPARAM, clipRect.left, clipRect.top, &r, 1, Unsorted); 

#elif BEOS
	clipping_rect r = {clipRect.left, clipRect.top, clipRect.right - 1, clipRect.bottom - 1};	
	BRegion region;
	region.Set (r);
	pView->ConstrainClippingRegion (&region);
#endif
}

//------------------------------------------------------------------------------
void CDrawContext::resetClipRect ()
{
	CRect newClip;
	if (pFrame)
		pFrame->getViewSize (newClip);
	else
		newClip (0, 0, 1000, 1000);

#if (MAC && QUARTZ)
	if (0 && gCGContext)
	{
		CGContextRestoreGState (gCGContext);
		CGContextScaleCTM (gCGContext, 1, -1);
		CGRect cgClipRect = CGRectMake (newClip.left, newClip.top, newClip.width (), newClip.height ());
		CGContextClipToRect (gCGContext, cgClipRect);
		CGContextScaleCTM (gCGContext, 1, -1);
		CGContextSaveGState (gCGContext);
		setLineWidth (frameWidth);
		setLineStyle (lineStyle);
		setFrameColor (frameColor);
		setFillColor (fillColor);
		setFont (fontId, fontSize);
		setDrawMode (drawMode);
	}

#elif MAC || WINDOWS || MOTIF
	setClipRect (newClip);

#elif BEOS
	pView->ConstrainClippingRegion (NULL);
#endif

	clipRect = newClip;
}

//-----------------------------------------------------------------------------
void CDrawContext::moveTo (const CPoint &_point)
{
	CPoint point (_point);
	point.offset (offset.h, offset.v);

#if WINDOWS
	MoveToEx ((HDC)pSystemContext, point.h, point.v, NULL);
  
#elif MAC
	#if QUARTZ
	#else
	CGrafPtr OrigPort;
	GDHandle OrigDevice;
	GetGWorld (&OrigPort, &OrigDevice); // get current GrafPort
	SetGWorld (getPort (), NULL);       // activate our GWorld
	MoveTo (point.h, point.v);
	SetGWorld (OrigPort, OrigDevice);
	#endif
  	penLoc = point;
  	
#elif MOTIF || BEOS
	penLoc = point;
#endif
}

//-----------------------------------------------------------------------------
void CDrawContext::lineTo (const CPoint& _point)
{
	CPoint point (_point);
	point.offset (offset.h, offset.v);

#if WINDOWS
	LineTo ((HDC)pSystemContext, point.h, point.v);
	
#elif MAC
	#if QUARTZ
	CGContextRef context = beginCGContext (true);
	{
		QuartzSetLineDash (context, lineStyle, frameWidth);

		CGContextBeginPath (context);
		CGContextMoveToPoint (context, penLoc.h, penLoc.v);
		CGContextAddLineToPoint (context, point.h, point.v);
		CGContextDrawPath (context, kCGPathStroke);
		releaseCGContext (context);
	}
	penLoc = point;
	#else
	CGrafPtr OrigPort;
	GDHandle OrigDevice;
	GetGWorld (&OrigPort, &OrigDevice); // get current GrafPort
	SetGWorld (getPort (), NULL);       // activate our GWorld
	RGBColor col;
	CColor2RGBColor (frameColor, col);
	RGBForeColor (&col);
	#if 1
	if (point.v == penLoc.v)
	{
		CPoint old = point;
		if (point.h > penLoc.h)
			point.h--;
		else
			point.h++;
		penLoc = old;
		LineTo (point.h, point.v);
		MoveTo (penLoc.h, penLoc.v);
	}
	else if (point.h == penLoc.h)
	{
		CPoint old = point;
		if (point.v > penLoc.v)
			point.v--;
		else
			point.v++;
		penLoc = old;
		LineTo (point.h, point.v);
		MoveTo (penLoc.h, penLoc.v);
	}
	else
	{
		penLoc = point;	
		LineTo (point.h, point.v);
	}
	#else
	if (point.v > penLoc.v)
		point.v--;
	else if (point.v < penLoc.v)
		point.v++;
	if (point.h > penLoc.h)
		point.h--;
	else if (point.h < penLoc.h)
		point.h++;
	penLoc = point;
	LineTo (point.h, point.v);
	#endif
	SetGWorld (OrigPort, OrigDevice);
	#endif

#elif MOTIF
	CPoint start (penLoc);
	CPoint end (point);
	if (start.h == end.h)
	{
		if (start.v < -5)
			start.v = -5;
		else if (start.v > 10000)
			start.v = 10000;
		
		if (end.v < -5)
			end.v = -5;
		else if (end.v > 10000)
			end.v = 10000;
	}
	if (start.v == end.v)
	{
		if (start.h < -5)
			start.h = -5;
		else if (start.h > 10000)
			start.h = 10000;
		
		if (end.h < -5)
			end.h = -5;
		else if (end.h > 10000)
			end.h = 10000;
	}
	XDrawLine (XDRAWPARAM, start.h, start.v, end.h, end.v);
	
	// keep trace of the new position
	penLoc = point;

#elif BEOS
	rgb_color c = { frameColor.red, frameColor.green, frameColor.blue, 255 };
	pView->SetHighColor (c);
	pView->SetDrawingMode (modeToPlatform [drawMode]);
	pView->SetPenSize (frameWidth);
	lineFromTo (penLoc, point);
	penLoc = point;
#endif
}

//-----------------------------------------------------------------------------
void CDrawContext::drawLines (const CPoint* points, const long& numLines)
{
	#if QUARTZ
	CGContextRef context = beginCGContext (true);
	if (context) 
	{
		QuartzSetLineDash (context, lineStyle, frameWidth);

		#ifdef MAC_OS_X_VERSION_10_4
		if (_CGContextStrokeLineSegments)
		{
			CGPoint* cgPoints = new CGPoint[numLines*2];
			for (long i = 0; i < numLines * 2; i += 2)
			{
				cgPoints[i].x = points[i].x + offset.x;
				cgPoints[i+1].x = points[i+1].x + offset.x;
				cgPoints[i].y = points[i].y + offset.y;
				cgPoints[i+1].y = points[i+1].y + offset.y;
			}
			_CGContextStrokeLineSegments (context, cgPoints, numLines*2);
			delete [] cgPoints;
		}
		else
		#endif
		{
			CGContextBeginPath (context);
			for (long i = 0; i < numLines * 2; i += 2)
			{
				CGContextMoveToPoint (context, points[i].x + offset.x, points[i].y + offset.y);
				CGContextAddLineToPoint (context, points[i+1].x + offset.x, points[i+1].y + offset.y);
			}
			CGContextDrawPath (context, kCGPathStroke);
		}
		releaseCGContext (context);
	}

	#else
	// default implementation, when no platform optimized code is implemented
	for (long i = 0; i < numLines * 2; i+=2)
	{
		moveTo (points[i]);
		lineTo (points[i+1]);
	}
	#endif
}

//-----------------------------------------------------------------------------
void CDrawContext::drawPolygon (const CPoint *pPoints, long numberOfPoints, const CDrawStyle drawStyle)
{
#if MAC && QUARTZ
	CGContextRef context = beginCGContext (true);
	{
		CGPathDrawingMode m;
		switch (drawStyle)
		{
			case kDrawFilled : m = kCGPathFill; break;
			case kDrawFilledAndStroked : m = kCGPathFillStroke; break;
			default : m = kCGPathStroke; break;
		}

		QuartzSetLineDash (context, lineStyle, frameWidth);

		CGContextBeginPath (context);
		CGContextMoveToPoint (context, pPoints[0].h + offset.h, pPoints[0].v + offset.v);
		for (long i = 1; i < numberOfPoints; i++)
			CGContextAddLineToPoint (context, pPoints[i].h + offset.h, pPoints[i].v + offset.v);
		CGContextDrawPath (context, m);
		releaseCGContext (context);
	}
#else
	if (drawStyle == kDrawFilled || drawStyle == kDrawFilledAndStroked)
		fillPolygon (pPoints, numberOfPoints);
	if (drawStyle == kDrawStroked || drawStyle == kDrawFilledAndStroked)
		polyLine (pPoints, numberOfPoints);
#endif
}

//-----------------------------------------------------------------------------
void CDrawContext::polyLine (const CPoint *pPoints, long numberOfPoints)
{
#if WINDOWS
	POINT points[30];
	POINT *polyPoints;
	bool allocated = false;

	if (numberOfPoints > 30)
	{
		polyPoints = (POINT*)new char [numberOfPoints * sizeof (POINT)];
		if (!polyPoints)
			return;
		allocated = true;
	}
	else
		polyPoints = points;

	for (long i = 0; i < numberOfPoints; i++)
	{
		polyPoints[i].x = pPoints[i].h + offset.h;
		polyPoints[i].y = pPoints[i].v + offset.v;
	}

	Polyline ((HDC)pSystemContext, polyPoints, numberOfPoints);

	if (allocated)
		delete[] polyPoints;

#elif MAC
	#if QUARTZ
	drawPolygon (pPoints, numberOfPoints);

	#else
	CGrafPtr OrigPort;
	GDHandle OrigDevice;
	GetGWorld (&OrigPort, &OrigDevice);
	SetGWorld (getPort (), NULL);
	RGBColor col;
	CColor2RGBColor (frameColor, col);
	RGBForeColor (&col);
	MoveTo (pPoints[0].h, pPoints[0].v);
	for (long i = 1; i < numberOfPoints; i++)
		LineTo (pPoints[i].h + offset.h, pPoints[i].v + offset.v);
	SetGWorld (OrigPort, OrigDevice);
	#endif

#elif MOTIF
	XPoint* pt = (XPoint*)malloc (numberOfPoints * sizeof (XPoint));
	if (!pt)
		return;
	for (long i = 0; i < numberOfPoints; i++)
	{
		pt[i].x = (short)pPoints[i].h + offset.h;
		pt[i].y = (short)pPoints[i].v + offset.v;
	}
	
	XDrawLines (XDRAWPARAM, pt, numberOfPoints, CoordModeOrigin);

	free (pt);

#elif BEOS
	rgb_color c = { frameColor.red, frameColor.green, frameColor.blue, 255 };
	pView->SetHighColor (c);
	pView->SetDrawingMode (modeToPlatform [drawMode]);
	pView->SetPenSize (frameWidth);

	CPoint begin (pPoints[0]);
	begin.offset (offset.h, offset.v);
	CPoint end;
	for (long i = 1; i < numberOfPoints; i++)
	{
		end = pPoints[i];
		end.offset (offset.h, offset.v);
		lineFromTo (begin, end);
		begin = end;
	}
#endif
}

//-----------------------------------------------------------------------------
void CDrawContext::fillPolygon (const CPoint *pPoints, long numberOfPoints)
{
	// Don't draw boundary
#if WINDOWS
	POINT points[30];
	POINT *polyPoints;
	bool allocated = false;

	if (numberOfPoints > 30)
	{
		polyPoints = (POINT*)new char [numberOfPoints * sizeof (POINT)];
		if (!polyPoints)
			return;
		allocated = true;
	}
	else
		polyPoints = points;

	for (long i = 0; i < numberOfPoints; i++)
	{
		polyPoints[i].x = pPoints[i].h + offset.h;
		polyPoints[i].y = pPoints[i].v + offset.v;
	}

	HANDLE nullPen = GetStockObject (NULL_PEN);
	HANDLE oldPen  = SelectObject ((HDC)pSystemContext, nullPen);
	Polygon ((HDC)pSystemContext, polyPoints, numberOfPoints);
	SelectObject ((HDC)pSystemContext, oldPen);

	if (allocated)
		delete[] polyPoints;

#elif MAC
	#if QUARTZ
	drawPolygon (pPoints, numberOfPoints, kDrawFilled);

	#else
	CGrafPtr   OrigPort;
	GDHandle   OrigDevice;
	PolyHandle thePoly;
	RGBColor	col;
	
	GetGWorld (&OrigPort, &OrigDevice);
	SetGWorld (getPort (), NULL);
	CColor2RGBColor (fillColor, col);
	RGBForeColor (&col);
	thePoly = OpenPoly ();              // start recording 
	polyLine (pPoints, numberOfPoints); // draw polygon
	LineTo (pPoints[0].h + offset.h, pPoints[0].v + offset.v);  // close the boundary
	ClosePoly ();                       // stop recording 
	
	PixPatHandle pixPatHandle = NewPixPat ();
	CColor2RGBColor (fillColor, col);
	MakeRGBPat (pixPatHandle, &col);    // create pixel pattern with fill color
	
	FillCPoly (thePoly, pixPatHandle);  // fill inside 
	KillPoly (thePoly);                 // deallocate all memory used here 
	DisposePixPat (pixPatHandle);
	SetGWorld (OrigPort, OrigDevice);
	#endif
	
#elif MOTIF
	// convert the points
	XPoint* pt = (XPoint*)malloc (numberOfPoints * sizeof (XPoint));
	for (long i = 0; i < numberOfPoints; i++)
	{
		pt[i].x = (short)pPoints[i].h + offset.h;
		pt[i].y = (short)pPoints[i].v + offset.v;
	}
	
	XFillPolygon (XDRAWPARAM, pt, numberOfPoints, Convex, CoordModeOrigin);

	free (pt);

#elif BEOS
	BPoint bpoints[30];
	BPoint* polyPoints;
	bool allocated = false;
	
	if (numberOfPoints > 30)
	{
		polyPoints = new BPoint [numberOfPoints];
		if (!polyPoints)
			return;
		allocated = true;
	}	
	else
		polyPoints = bpoints;
			
	for (long i = 0; i < numberOfPoints; i++)
		polyPoints[i].Set (pPoints[i].h + offset.h, pPoints[i].v + offset.v);

	rgb_color c = { fillColor.red, fillColor.green, fillColor.blue, 255 };
	pView->SetHighColor (c);
	pView->SetDrawingMode (modeToPlatform [drawMode]);
	pView->FillPolygon (polyPoints, numberOfPoints);

	if (allocated)
		delete[] polyPoints;
#endif
}

//-----------------------------------------------------------------------------
void CDrawContext::drawRect (const CRect &_rect, const CDrawStyle drawStyle)
{
	CRect rect (_rect);
	rect.offset (offset.h, offset.v);

#if WINDOWS
	if (drawStyle == kDrawFilled || drawStyle == kDrawFilledAndStroked)
	{
		RECT wr = {rect.left, rect.top, rect.right, rect.bottom};
		HANDLE nullPen = GetStockObject (NULL_PEN);
		HANDLE oldPen  = SelectObject ((HDC)pSystemContext, nullPen);
		FillRect ((HDC)pSystemContext, &wr, (HBRUSH)pBrush);
		SelectObject ((HDC)pSystemContext, oldPen);
	}
	if (drawStyle == kDrawStroked || drawStyle == kDrawFilledAndStroked)
	{
		MoveToEx ((HDC)pSystemContext, rect.left, rect.top, NULL);
		LineTo ((HDC)pSystemContext, rect.right-1, rect.top);
		LineTo ((HDC)pSystemContext, rect.right-1, rect.bottom-1);
		LineTo ((HDC)pSystemContext, rect.left, rect.bottom-1);
		LineTo ((HDC)pSystemContext, rect.left, rect.top);
	}
	
#elif MAC
	#if QUARTZ
	CGContextRef context = beginCGContext (true);
	{
		CGPathDrawingMode m;
		switch (drawStyle)
		{
			case kDrawFilled : m = kCGPathFill; break;
			case kDrawFilledAndStroked : m = kCGPathFillStroke; break;
			default : m = kCGPathStroke; break;
		}

		CGRect r = CGRectMake (rect.left, rect.top+1, rect.width () - 1, rect.height () - 1);

		QuartzSetLineDash (context, lineStyle, frameWidth);

		CGContextBeginPath (context);
		CGContextMoveToPoint (context, r.origin.x, r.origin.y);
		CGContextAddLineToPoint (context, r.origin.x + r.size.width, r.origin.y);
		CGContextAddLineToPoint (context, r.origin.x + r.size.width, r.origin.y + r.size.height);
		CGContextAddLineToPoint (context, r.origin.x, r.origin.y + r.size.height);
		CGContextClosePath (context);

		CGContextDrawPath (context, m);

		releaseCGContext (context);
	}
	#else
	CGrafPtr OrigPort;
	GDHandle OrigDevice;
	GetGWorld (&OrigPort, &OrigDevice);	// get current GrafPort
	SetGWorld (getPort (), NULL);       // activate our GWorld
	
	if (drawStyle == kDrawFilled || drawStyle == kDrawFilledAndStroked)
	{
		Rect rr;
		RGBColor col;
		CColor2RGBColor (fillColor, col);
		RGBForeColor (&col);
		CRect2Rect (rect, rr);
		FillRect (&rr, &fillPattern);
	}
	if (drawStyle == kDrawStroked || drawStyle == kDrawFilledAndStroked)
	{
		RGBColor col;
		CColor2RGBColor (frameColor, col);
		RGBForeColor (&col);
		MoveTo (rect.left, rect.top);
		LineTo (rect.right-1, rect.top);
		LineTo (rect.right-1, rect.bottom-1);
		LineTo (rect.left, rect.bottom-1);
		LineTo (rect.left, rect.top);
	}
	SetGWorld (OrigPort, OrigDevice);
	#endif

#elif MOTIF
	XDrawRectangle (XDRAWPARAM, rect.left, rect.top, rect.width (), rect.height ());

#elif BEOS
	rgb_color c = { frameColor.red, frameColor.green, frameColor.blue, 255 };
	pView->SetHighColor (c);
	pView->SetDrawingMode (modeToPlatform [drawMode]);
	BRect r (rect.left, rect.top, rect.right, rect.bottom);
	pView->SetPenSize (frameWidth);
	pView->StrokeRect (r);

#endif
}

//-----------------------------------------------------------------------------
void CDrawContext::fillRect (const CRect &_rect)
{
	CRect rect (_rect);
	rect.offset (offset.h, offset.v);

	// Don't draw boundary
#if WINDOWS
	RECT wr = {rect.left + 1, rect.top + 1, rect.right, rect.bottom};
	HANDLE nullPen = GetStockObject (NULL_PEN);
	HANDLE oldPen  = SelectObject ((HDC)pSystemContext, nullPen);
	FillRect ((HDC)pSystemContext, &wr, (HBRUSH)pBrush);
	SelectObject ((HDC)pSystemContext, oldPen);

#elif MAC
	#if QUARTZ
	CGContextRef context = beginCGContext (true);
	{
		CGRect r = CGRectMake (rect.left, rect.top, rect.width (), rect.height ());
		CGContextFillRect (context, r);
		releaseCGContext (context);
	}
	#else
	Rect     rr;
	CGrafPtr OrigPort;
	GDHandle OrigDevice;
	GetGWorld (&OrigPort, &OrigDevice);
	SetGWorld (getPort (), NULL);
	RGBColor col;
	CColor2RGBColor (fillColor, col);
	RGBForeColor (&col);
	CRect2Rect (rect, rr);
	rr.left++;
	rr.top++;
	FillRect (&rr, &fillPattern);
	SetGWorld (OrigPort, OrigDevice);
	#endif

#elif MOTIF
	XFillRectangle (XDRAWPARAM, rect.left + 1, rect.top + 1, rect.width () - 1, rect.height () - 1);

#elif BEOS
	rgb_color c = { fillColor.red, fillColor.green, fillColor.blue, 255 };
	pView->SetHighColor (c);
	pView->SetDrawingMode (modeToPlatform [drawMode]);
	BRect r (rect.left + 1, rect.top + 1, rect.right - 1, rect.bottom - 1);
	pView->FillRect (r);
#endif
}

//-----------------------------------------------------------------------------
void CDrawContext::drawEllipse (const CRect &_rect, const CDrawStyle drawStyle)
{
	#if QUARTZ
	CRect rect (_rect);
	rect.offset (offset.h, offset.v);

	CGContextRef context = beginCGContext (true);
	{
		CGPathDrawingMode m;
		switch (drawStyle)
		{
			case kDrawFilled : m = kCGPathFill; break;
			case kDrawFilledAndStroked : m = kCGPathFillStroke; break;
			default : m = kCGPathStroke; break;
		}
		if (rect.width () != rect.height ())
		{
			CGContextSaveGState (context);

			QuartzSetLineDash (context, lineStyle, frameWidth);

			CGContextBeginPath (context);

			CGRect cgRect = CGRectMake (rect.left, rect.top, rect.width (), rect.height ());
			CGPoint center = CGPointMake (CGRectGetMidX (cgRect), CGRectGetMidY (cgRect));
			float a = CGRectGetWidth (cgRect) / 2;
			float b = CGRectGetHeight (cgRect) / 2;

		    CGContextTranslateCTM (context, center.x, center.y);
		    CGContextScaleCTM (context, a, b);
		    CGContextMoveToPoint (context, 1, 0);
		    CGContextAddArc (context, 0, 0, 1, radians (0), radians (360), 0);

			CGContextClosePath (context);
			CGContextRestoreGState (context);
			CGContextDrawPath (context, m);
		}
		else
		{
			float radius = rect.width () * 0.5f;
			CGContextBeginPath (context);
			CGContextAddArc (context, rect.left + radius, rect.top + radius, radius, radians (0), radians (360), 0);
			CGContextClosePath (context);
			CGContextDrawPath (context, m);
		}
		releaseCGContext (context);
	}

	#else
	CPoint point (_rect.left + (_rect.right - _rect.left) / 2, _rect.top);
	drawArc (_rect, point, point);
	#endif
}

//-----------------------------------------------------------------------------
void CDrawContext::fillEllipse (const CRect &_rect)
{
	CRect rect (_rect);
	rect.offset (offset.h, offset.v);

	// Don't draw boundary
#if WINDOWS
	HANDLE nullPen = GetStockObject (NULL_PEN);
	HANDLE oldPen  = SelectObject ((HDC)pSystemContext, nullPen);
	Ellipse ((HDC)pSystemContext, rect.left + 1, rect.top + 1, rect.right + 1, rect.bottom + 1);
	SelectObject ((HDC)pSystemContext, oldPen);

#elif QUARTZ
	CGContextRef context = beginCGContext (true);
	{
		CGContextSaveGState (context);
		CGContextBeginPath (context);

		CGRect cgRect = CGRectMake (rect.left, rect.top, rect.width (), rect.height ());
		CGPoint center = CGPointMake (CGRectGetMidX (cgRect), CGRectGetMidY (cgRect));
		float a = CGRectGetWidth (cgRect) / 2;
		float b = CGRectGetHeight (cgRect) / 2;

	    CGContextTranslateCTM (context, center.x, center.y);
	    CGContextScaleCTM (context, a, b);
	    CGContextMoveToPoint (context, 1, 0);
	    CGContextAddArc (context, 0, 0, 1, radians (0), radians (360), 0);

		CGContextClosePath (context);
		CGContextRestoreGState (context);
		CGContextDrawPath (context, kCGPathFill);
		releaseCGContext (context);
	}

#else
	CPoint point (_rect.left + ((_rect.right - _rect.left) / 2), _rect.top);
	fillArc (_rect, point, point);
#endif
}

//-----------------------------------------------------------------------------
void CDrawContext::drawPoint (const CPoint &_point, CColor color)
{
	CPoint point (_point);

#if WINDOWS
	point.offset (offset.h, offset.v);
	SetPixel ((HDC)pSystemContext, point.h, point.v, RGB(color.red, color.green, color.blue));

#elif MOTIF
	CColor oldframecolor = frameColor;
	setFrameColor (color);
	XDrawPoint (XDRAWPARAM, point.h, point.v);
	setFrameColor (oldframecolor);

#elif MAC
	CCoord oldframeWidth = frameWidth;
	CColor oldframecolor = frameColor;
	setLineWidth (1);
	setFrameColor (color);
	CPoint point2 (point);
	point2.h++;
	moveTo (point);
	lineTo (point2);
	
	setFrameColor (oldframecolor);
	setLineWidth (oldframeWidth);

#else
	int oldframeWidth = frameWidth;
	CColor oldframecolor = frameColor;
	setLineWidth (1);
	setFrameColor (color);
	moveTo (point);
	lineTo (point);
	
	setFrameColor (oldframecolor);
	setLineWidth (oldframeWidth);
#endif
}

//-----------------------------------------------------------------------------
CColor CDrawContext::getPoint (const CPoint& _point)
{
	CPoint point (_point);
	point.offset (offset.h, offset.v);
	CColor color = kBlackCColor;

	#if WINDOWS
	COLORREF c  = GetPixel ((HDC)pSystemContext, point.h, point.v);
	color.red   = GetRValue (c);
	color.green = GetGValue (c);
	color.blue  = GetBValue (c);

	#elif MAC
	#if QUARTZ
	// no quartz equivalent
	
	#else
	CGrafPtr OrigPort;
	GDHandle OrigDevice;
	GetGWorld (&OrigPort, &OrigDevice);
	SetGWorld (getPort (), NULL);
	RGBColor cPix;
	GetCPixel (point.h, point.v, &cPix);
	RGBColor2CColor (cPix, color);
	SetGWorld (OrigPort, OrigDevice);
	#endif
	#endif

	return color;
}

//-----------------------------------------------------------------------------
void CDrawContext::floodFill (const CPoint& _start)
{
	CPoint start (_start);
	start.offset (offset.h, offset.v);

	#if WINDOWS
	COLORREF c = GetPixel ((HDC)pSystemContext, start.h, start.v);
	ExtFloodFill ((HDC)pSystemContext, start.h, start.v, c, FLOODFILLSURFACE);
	
	#elif MAC
	#if QUARTZ
	// no quartz equivalent
	
	#else
	CGrafPtr oldPort;
	GDHandle oldDevice;
	GetGWorld (&oldPort, &oldDevice);
	SetGWorld (getPort (), 0);
	
	Rect r;
	GetPortBounds (getPort (), &r);
	GWorldPtr pMask;
	OSErr err = NewGWorld ((GWorldPtr*)&pMask, 1, &r, 0, 0, 0); // create monochrome GWorld
	if (!err)
	{
		// generate fill mask
		PixMapHandle srcBits = GetGWorldPixMap (getPort ());
		PixMapHandle dstBits = GetGWorldPixMap (pMask);
		if (srcBits && dstBits)
		{
			LockPixels (srcBits);
			LockPixels (dstBits);
		
			SeedCFill ((BitMapPtr)*srcBits, (BitMapPtr)*dstBits, &r, &r, start.h, start.v, 0, 0);

			// fill destination
			RGBColor oldForeColor, oldBackColor;
			GetForeColor (&oldForeColor);
			GetBackColor (&oldBackColor);
		
			::BackColor (whiteColor);
		
			RGBColor col;
			CColor2RGBColor (fillColor, col);
			RGBForeColor (&col);		
		
			CopyMask ((BitMapPtr)*dstBits, (BitMapPtr)*dstBits, (BitMapPtr)*srcBits, &r, &r, &r);
		
			RGBForeColor (&oldForeColor);
			RGBBackColor (&oldBackColor);

			// cleanup
			UnlockPixels (srcBits);
			UnlockPixels (dstBits);
		}
		
		DisposeGWorld (pMask);
	}

	SetGWorld (oldPort, oldDevice);
	#endif
	#endif
}

#if QUARTZ
void addOvalToPath(CGContextRef c, CPoint center, float a, float b, float start_angle, float end_angle)
{
	CGContextSaveGState (c);
	CGContextTranslateCTM (c, center.x, center.y);
	CGContextScaleCTM (c, a, b);

	CGContextMoveToPoint (c, cos (radians (start_angle)), sin (radians (start_angle)));

	CGContextAddArc(c, 0, 0, 1, radians (start_angle), radians (end_angle), 1);

	CGContextRestoreGState(c);
}
#endif

//-----------------------------------------------------------------------------
void CDrawContext::drawArc (const CRect &_rect, const float _startAngle, const float _endAngle, const CDrawStyle drawStyle) // in degree
{
	CRect rect (_rect);
	rect.offset (offset.h, offset.v);

	#if WINDOWS
	float startRad = (float)(k2PI * _startAngle / 360.f);
	float endRad   = (float)(k2PI * _endAngle / 360.f);
	
	CPoint point1, point2;
	long midX = _rect.width () / 2;
	long midY = _rect.height () / 2;

	point1.x = (long)(midX + midX * cosf (startRad));
	point1.y = (long)(midY - midY * sinf (startRad));
	point2.x = (long)(midX + midX * cosf (endRad));
	point2.y = (long)(midY - midY * sinf (endRad));
	point1.offset (offset.h, offset.v);
	point2.offset (offset.h, offset.v);

	if (drawStyle == kDrawFilled || drawStyle == kDrawFilledAndStroked)
	{
		HANDLE nullPen = GetStockObject (NULL_PEN);
		HANDLE oldPen  = SelectObject ((HDC)pSystemContext, nullPen);
		Pie ((HDC)pSystemContext, rect.left, rect.top, rect.right + 1, rect.bottom + 1, 
				 point1.h, point1.v, point2.h, point2.v);
		SelectObject ((HDC)pSystemContext, oldPen);
	}
	if (drawStyle == kDrawStroked || drawStyle == kDrawFilledAndStroked)
	{
		Arc ((HDC)pSystemContext, rect.left, rect.top, rect.right + 1, rect.bottom + 1, 
				 point1.h, point1.v, point2.h, point2.v);
	}

	#elif MOTIF

	XDrawArc (XDRAWPARAM, rect.left, rect.top, rect.width (), rect.height (),
						_startAngle * 64, _endAngle * 64);

	#elif MAC

	#if QUARTZ
	CGContextRef context = beginCGContext (true);
	{
		CGPathDrawingMode m;
		switch (drawStyle)
		{
			case kDrawFilled : m = kCGPathFill; break;
			case kDrawFilledAndStroked : m = kCGPathFillStroke; break;
			default : m = kCGPathStroke; break;
		}
		QuartzSetLineDash (context, lineStyle, frameWidth);

		CGContextBeginPath (context);
		addOvalToPath (context, CPoint (rect.left + rect.width () / 2, rect.top + rect.height () / 2), rect.width () / 2, rect.height () / 2, -_startAngle, -_endAngle);

		CGContextDrawPath (context, m);
		releaseCGContext (context);
	}
	#else
	Rect     rr;
	CGrafPtr OrigPort;
	GDHandle OrigDevice;
	GetGWorld (&OrigPort, &OrigDevice);
	SetGWorld (getPort (), NULL);
	RGBColor col;
	CColor2RGBColor (frameColor, col);
	RGBForeColor (&col);
	CRect2Rect (rect, rr);
	FrameArc (&rr, 90 - _startAngle, -_endAngle);
	SetGWorld (OrigPort, OrigDevice);
	#endif

	#elif BEOS
	rgb_color c = { frameColor.red, frameColor.green, frameColor.blue, 255 };
	pView->SetHighColor (c);
	pView->SetDrawingMode (modeToPlatform [drawMode]);
	BRect r (rect.left, rect.top, rect.right, rect.bottom);
	pView->SetPenSize (frameWidth);
	pView->StrokeArc (r, _startAngle, _endAngle);

	#endif
}

//-----------------------------------------------------------------------------
void CDrawContext::drawArc (const CRect &_rect, const CPoint &_point1, const CPoint &_point2)
{
	CRect rect (_rect);
	rect.offset (offset.h, offset.v);
	CPoint point1 (_point1);
	point1.offset (offset.h, offset.v);
	CPoint point2 (_point2);
	point2.offset (offset.h, offset.v);

	// draws from point1 to point2 counterclockwise
#if WINDOWS
	Arc ((HDC)pSystemContext, rect.left, rect.top, rect.right + 1, rect.bottom + 1, 
			 point1.h, point1.v, point2.h, point2.v);

#elif MAC || MOTIF || BEOS
	
	int	angle1, angle2;
	if ((point1.v == point2.v) && (point1.h == point2.h))
	{
		angle1 = 0;
		angle2 = 23040; // 360 * 64
	}
	else
	{
		CPoint pm ((rect.left + rect.right) / 2, (rect.top + rect.bottom) / 2);
		angle1 = convertPoint2Angle (pm, point1);
		angle2 = convertPoint2Angle (pm, point2) - angle1;
		if (angle2 < 0)
			angle2 += 23040; // 360 * 64
	}

#if MAC

	#if QUARTZ
	angle1 /= 64;
	angle2 /= 64;
	CGContextRef context = beginCGContext (true);
	{
		QuartzSetLineDash (context, lineStyle, frameWidth);

		CGContextBeginPath (context);
		addOvalToPath (context, CPoint (rect.left + rect.width () / 2, rect.top + rect.height () / 2), rect.width () / 2, rect.height () / 2, 90-angle1, (90-angle1)-angle2);
		CGContextDrawPath (context, kCGPathStroke);
		releaseCGContext (context);
	}
	#else
	Rect     rr;
	CGrafPtr OrigPort;
	GDHandle OrigDevice;
	GetGWorld (&OrigPort, &OrigDevice);
	SetGWorld (getPort (), NULL);
	RGBColor col;
	CColor2RGBColor (frameColor, col);
	RGBForeColor (&col);
	CRect2Rect (rect, rr);
	FrameArc (&rr, 90 - (angle1 / 64), -angle2 / 64);
	SetGWorld (OrigPort, OrigDevice);
	#endif
	        
#elif MOTIF
	XDrawArc (XDRAWPARAM, rect.left, rect.top, rect.width (), rect.height (),
						angle1, angle2);

#elif BEOS
	rgb_color c = { frameColor.red, frameColor.green, frameColor.blue, 255 };
	pView->SetHighColor (c);
	pView->SetDrawingMode (modeToPlatform [drawMode]);
	BRect r (rect.left, rect.top, rect.right, rect.bottom);
	pView->SetPenSize (frameWidth);
	pView->StrokeArc (r, angle1 / 64, angle2 / 64);
#endif	

#endif
}

//-----------------------------------------------------------------------------
void CDrawContext::fillArc (const CRect &_rect, const CPoint &_point1, const CPoint &_point2)
{
	CRect rect (_rect);
	rect.offset (offset.h, offset.v);
	CPoint point1 (_point1);
	point1.offset (offset.h, offset.v);
	CPoint point2 (_point2);
	point2.offset (offset.h, offset.v);

	// Don't draw boundary
#if WINDOWS
	HANDLE nullPen = GetStockObject (NULL_PEN);
	HANDLE oldPen  = SelectObject ((HDC)pSystemContext, nullPen);
	Pie ((HDC)pSystemContext, offset.h + rect.left + 1, offset.v + rect.top + 1, offset.h + rect.right, offset.v + rect.bottom, 
			 point1.h, point1.v, point2.h, point2.v);
	SelectObject ((HDC)pSystemContext, oldPen);

#elif MAC || MOTIF || BEOS
	
	int	angle1, angle2;
	if ((point1.v == point2.v) && (point1.h == point2.h))
	{
		angle1 = 0;
		angle2 = 23040; // 360 * 64
	}
	else
	{
		CPoint pm ((rect.left + rect.right) / 2, (rect.top + rect.bottom) / 2);
		angle1 = convertPoint2Angle (pm, point1);
		angle2 = convertPoint2Angle (pm, point2);
	}

#if MAC
	#if QUARTZ
	angle1 /= 64;
	angle2 /= 64;
	CGContextRef context = beginCGContext (true);
	{
		CGContextBeginPath (context);
		addOvalToPath (context, CPoint (rect.left + rect.width () / 2, rect.top + rect.height () / 2), rect.width () / 2, rect.height () / 2, -angle1, -angle2);
		CGContextClosePath (context);
		CGContextDrawPath (context, kCGPathFill);
		releaseCGContext (context);
	}
	
	#else
	Rect     rr;
	CGrafPtr OrigPort;
	GDHandle OrigDevice;
	GetGWorld (&OrigPort, &OrigDevice);
	SetGWorld (getPort (), NULL);
	RGBColor col;
	CColor2RGBColor (fillColor, col);
	RGBForeColor (&col);
	CRect2Rect (rect, rr);
	
	angle2 = angle2 - angle1;
	if (angle2 < 0)
		angle2 = -angle2;
	FillArc (&rr, 90 - (angle1 / 64), -angle2 / 64, &fillPattern);

	SetGWorld (OrigPort, OrigDevice);
	#endif
        
#elif MOTIF
	XFillArc (XDRAWPARAM, rect.left, rect.top, rect.width (), rect.height (),
				angle1, angle2);

#elif BEOS
	rgb_color c = { fillColor.red, fillColor.green, fillColor.blue, 255 };
	pView->SetHighColor (c);
	pView->SetDrawingMode (modeToPlatform [drawMode]);
	BRect r (rect.left + 1, rect.top + 1, rect.right - 1, rect.bottom - 1);
	pView->FillArc (r, angle1 / 64, angle2 / 64);

#endif
#endif
}

//-----------------------------------------------------------------------------
void CDrawContext::setFontColor (const CColor color)
{
	fontColor = color;
	
#if WINDOWS
	SetTextColor ((HDC)pSystemContext, RGB (fontColor.red, fontColor.green, fontColor.blue));
	
#elif MAC
	#if QUARTZ
	// on quartz the fill color is the font color

	#else
	RGBColor col;
	CGrafPtr OrigPort;
	GDHandle OrigDevice;
	if (pWindow)
	{
		GetGWorld (&OrigPort, &OrigDevice);
		SetGWorld (getPort (), NULL);
		CColor2RGBColor (fontColor, col);
		RGBForeColor (&col);
		SetGWorld (OrigPort, OrigDevice);
	}
	#endif
        
#elif MOTIF
	setFrameColor (fontColor);

#endif
}

//-----------------------------------------------------------------------------
void CDrawContext::setFrameColor (const CColor color)
{
	if (frameColor == color)
		return;
		
	frameColor = color;

#if WINDOWS
	LOGPEN logPen = {iPenStyle, {frameWidth, frameWidth}, 
					 RGB (frameColor.red, frameColor.green, frameColor.blue)};
	
	HANDLE newPen = CreatePenIndirect (&logPen);
	SelectObject ((HDC)pSystemContext, newPen);
	if (pPen)
		DeleteObject (pPen);
	pPen = newPen;

#elif MAC
	#if QUARTZ
	if (gCGContext)
		CGContextSetRGBStrokeColor (gCGContext, color.red/255.f, color.green/255.f, color.blue/255.f, color.alpha/255.f);
	#else
	RGBColor col;
	CGrafPtr OrigPort;
	GDHandle OrigDevice;
	if (pWindow)
	{
		GetGWorld (&OrigPort, &OrigDevice);
		SetGWorld (getPort (), NULL);
		CColor2RGBColor (frameColor, col);
		RGBForeColor (&col);
		SetGWorld (OrigPort, OrigDevice);
	}
	#endif
        
#elif MOTIF
	XSetForeground (XGCPARAM, getIndexColor (frameColor));
#endif
}

//-----------------------------------------------------------------------------
void CDrawContext::setFillColor (const CColor color)
{
	if (fillColor == color)
		return;

	fillColor = color;

#if WINDOWS
 	SetBkColor ((HDC)pSystemContext, RGB (color.red, color.green, color.blue));
	LOGBRUSH logBrush = {BS_SOLID, RGB (color.red, color.green, color.blue), 0 };
	HANDLE newBrush = CreateBrushIndirect (&logBrush);
	if (newBrush == 0)
	{
		DWORD err = GetLastError ();
		return;
	}
	SelectObject ((HDC)pSystemContext, newBrush);
	if (pBrush)
		DeleteObject (pBrush);
	pBrush = newBrush;
	
#elif MAC
	#if QUARTZ
	if (gCGContext)
		CGContextSetRGBFillColor (gCGContext, color.red/255.f, color.green/255.f, color.blue/255.f, color.alpha/255.f);
	#else
	RGBColor col;
	CGrafPtr OrigPort;
	GDHandle OrigDevice;
	if (pWindow)
	{
		GetGWorld (&OrigPort, &OrigDevice);
		SetGWorld (getPort (), NULL);
		CColor2RGBColor (fillColor, col);
		RGBForeColor (&col);
		SetGWorld (OrigPort, OrigDevice);
	}
	#endif
        
#elif MOTIF
	// set the background for the text
	XSetBackground (XGCPARAM, getIndexColor (fillColor));
	
	// set the foreground for the fill
	setFrameColor (fillColor);
#endif
}

//-----------------------------------------------------------------------------
void CDrawContext::setFont (CFont fontID, const long size, long style)
{
	if (fontID < 0 || fontID >= kNumStandardFonts)
		fontID = kSystemFont;

	if (fontId == fontID && fontSize == (size != 0 ? size : gStandardFontSize[fontID]) && fontStyle == style)
		return;

	fontStyle = style;
	fontId = fontID;
	if (size != 0)
		fontSize = size;
	else
		fontSize = gStandardFontSize[fontID];

#if WINDOWS
	LOGFONT logfont = {0};

	if (style & kBoldFace)
		logfont.lfWeight = FW_BOLD;
	else
		logfont.lfWeight = FW_NORMAL;
	if (style & kItalicFace)
		logfont.lfItalic = true;
	if (style & kUnderlineFace)
		logfont.lfUnderline = true;
	
	logfont.lfHeight         = -fontSize;
	logfont.lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
	strcpy (logfont.lfFaceName, gStandardFontName[fontID]);

	if (fontID == kSymbolFont)
		logfont.lfPitchAndFamily = DEFAULT_PITCH | FF_DECORATIVE;
	else if (fontID == kSystemFont)
		logfont.lfWeight     = FW_BOLD;
  
	logfont.lfClipPrecision = CLIP_STROKE_PRECIS;
	logfont.lfOutPrecision  = OUT_STRING_PRECIS;
	logfont.lfQuality 	    = DEFAULT_QUALITY;
	logfont.lfCharSet       = ANSI_CHARSET;

	HANDLE newFont = CreateFontIndirect (&logfont);
	SelectObject ((HDC)pSystemContext, newFont);
	if (pFont)
		DeleteObject (pFont);
	pFont = newFont;
  
#elif MAC
	#if QUARTZ
	char myMacXFontName[255];
	strcpy(myMacXFontName, gMacXfontNames[fontId]);
	if (style & kBoldFace)
		strcat(myMacXFontName, " Bold");
	if (style & kItalicFace)
		strcat(myMacXFontName, " Italic");
	if (style & kUnderlineFace)
		strcat(myMacXFontName, " Underline");
	
	if (gCGContext)
		CGContextSelectFont (gCGContext, (const char*)myMacXFontName, fontSize, kCGEncodingMacRoman);
	#else
	CGrafPtr OrigPort;
	GDHandle OrigDevice;
	if (pWindow)
	{
		GetGWorld (&OrigPort, &OrigDevice);
		SetGWorld (getPort (), NULL);
		
		TextFace (style); // normal, bold, italic, underline...
   		TextMode (0);
		TextSize (fontSize);
		
		#if MACX
		short familyID;
		
		GetFNum (gMacXfontNames[fontID], &familyID);

		TextFont (familyID);
		
		#else
		if (fontID == kSymbolFont)
			TextFont (kFontIDSymbol);
		else if (fontID == kSystemFont)
			TextFont (0);	// system
		else if (fontID == kNormalFontSmaller)
			TextFont (kFontIDGeneva);	// Geneva
		else
			TextFont (kFontIDHelvetica);
		#endif
		
		GetFontInfo (&fontInfoStruct);
		SetGWorld (OrigPort, OrigDevice);
	}
	#endif
        
#elif MOTIF
	XSetFont (XGCPARAM, gFontStructs[fontID]->fid);
	
	// keep trace of the current font
	pFontInfoStruct = gFontStructs[fontID];

#elif BEOS
	font.SetFamilyAndStyle (gStandardFontName[fontID], gStandardFontStyle[fontID]);
	font.SetSize (fontSize);
	pView->SetFont (&font, B_FONT_FAMILY_AND_STYLE | B_FONT_SIZE);
#endif
}

//------------------------------------------------------------------------------
CCoord CDrawContext::getStringWidth (const char *pStr)
{
	CCoord result = 0;

	#if MAC
	#if QUARTZ
	CGContextRef context = beginCGContext (true);
	if (context)
	{
		CGContextSetTextDrawingMode (context, kCGTextInvisible);
		CGContextSetTextPosition (context, 0.f, 0.f);
		CGContextShowText (context, pStr, strlen (pStr));
		CGPoint p = CGContextGetTextPosition (context);
		result = (CCoord)p.x;
		releaseCGContext (context);
	}
	#else
	CGrafPtr OrigPort;
	GDHandle OrigDevice;
	GetGWorld (&OrigPort, &OrigDevice);
	SetGWorld (getPort (), NULL);

	result = (long)TextWidth (pStr, 0, strlen (pStr));

	SetGWorld (OrigPort, OrigDevice);
	#endif
        
	#elif WINDOWS
	SIZE size;
	GetTextExtentPoint32 ((HDC)pSystemContext, pStr, (int)strlen (pStr), &size);
	result = (long)size.cx;

	#elif MOTIF
	result = (long)XTextWidth (pFontInfoStruct, pStr, strlen (pStr));
	
	#elif BEOS
	result = (long)(ceil (pView->StringWidth (pStr)));
	#endif

	return result;
}

//-----------------------------------------------------------------------------
void CDrawContext::drawString (const char *string, const CRect &_rect,
							 const short opaque, const CHoriTxtAlign hAlign)
{
	if (!string)
		return;
	
	CRect rect (_rect);
	rect.offset (offset.h, offset.v);

#if WINDOWS
	// set the visibility mask
	SetBkMode ((HDC)pSystemContext, opaque ? OPAQUE : TRANSPARENT);

	RECT Rect = {rect.left, rect.top, rect.right, rect.bottom};
	UINT flag = DT_VCENTER + DT_SINGLELINE + DT_NOPREFIX;
	switch (hAlign)
	{
	case kCenterText:
		// without DT_SINGLELINE no vertical center alignment here
		DrawText ((HDC)pSystemContext, string, (int)strlen (string), &Rect, flag + DT_CENTER);
		break;
		
	case kRightText:
		DrawText ((HDC)pSystemContext, string, (int)strlen (string), &Rect, flag + DT_RIGHT);
		break;
		
	default : // left adjust
		Rect.left++;
		DrawText ((HDC)pSystemContext, string, (int)strlen (string), &Rect, flag + DT_LEFT);
	}

	SetBkMode ((HDC)pSystemContext, TRANSPARENT);

#elif MAC
	#if QUARTZ
	CGContextRef context = beginCGContext (true);
	if (context)
	{
		CCoord strWidth = getStringWidth (string);
		rect.bottom -= rect.height ()/2 - fontSize / 2 + 1;
		switch (hAlign)
		{
			case kCenterText:
			{
				rect.left += rect.width () / 2 - strWidth/2;
				break;
			}
			case kRightText:
				rect.left = rect.right - strWidth;
				break;
			default : // left adjust
				rect.left++;
		}

		CGContextSetShouldAntialias (context, true);
		CGContextSetTextDrawingMode (context, kCGTextFill);
		CGContextSetRGBFillColor (context, fontColor.red/255.f, fontColor.green/255.f, fontColor.blue/255.f, fontColor.alpha/255.f);
		CGContextSetTextPosition (context, rect.left, rect.bottom);
		CGContextShowText (context, string, strlen (string));
		releaseCGContext (context);
	}

	#else
	CGrafPtr OrigPort;
	GDHandle OrigDevice;
	int width;
	int xPos, yPos;
	int fontHeight;
	int rectHeight;
	int stringLength;

	Rect stringsRect;
	Rect contextsClip;
	Rect compositeClip;
	
	CRect2Rect (rect, stringsRect);
	CRect2Rect (clipRect, contextsClip);
	
	if (SectRect (&stringsRect, &contextsClip, &compositeClip))
	{	
		GetGWorld (&OrigPort, &OrigDevice);
		SetGWorld (getPort (), NULL);
		
		if (opaque)
			TextMode (srcCopy);
		else
			TextMode (srcOr);
		
		RGBColor col;
		CColor2RGBColor (fontColor, col);
		RGBForeColor (&col);

		CColor2RGBColor (fillColor, col);
		RGBBackColor (&col);
		
		rectHeight = rect.height ();
		fontHeight = fontInfoStruct.ascent + fontInfoStruct.descent;
		yPos = rect.bottom - fontInfoStruct.descent;
		if (rectHeight >= fontHeight)
			yPos -= (rectHeight - fontHeight) / 2;
			
		stringLength = strlen (string);
		width = TextWidth ((Ptr)string, 0, stringLength);
	
		switch (hAlign)
		{
		case kCenterText:
			xPos = (rect.right + rect.left - width) / 2;
			break;
			
		case kRightText:
			xPos = rect.right - width;
			break;
			
		default: // left adjust
			xPos = rect.left;
		}
		
		RgnHandle saveRgn = NewRgn ();
		GetClip (saveRgn);
		
		ClipRect (&compositeClip);

		#if TARGET_API_MAC_CARBON
		CFStringRef str;

		// Create a unicode string
		str = CFStringCreateWithCString(NULL, string, kCFStringEncodingMacRoman);
	
		// Initialize proper text box options
		TXNTextBoxOptionsData myOptions;
		myOptions.optionTags = kTXNSetJustificationMask;
		myOptions.justification = kTXNFlushLeft;

		// Determine the vertical alignment of the text box.
		// It is centered vertically.
		// Somehow, the yPos calculation above doesn't work here
		// or I am too stupid to understand it. Therefore I calculate
		// the text position in the surrounding control rect myself.
		long myHeight = (rect.height () - fontHeight) / 2;
		if (myHeight>0)
		{
			stringsRect.top += myHeight;
			stringsRect.bottom += myHeight;
		}
		stringsRect.left = xPos;
		stringsRect.right = xPos + width;//rect.width ();
	
		// Draw the unicode string
		TXNDrawCFStringTextBox (str, &stringsRect, NULL, &myOptions);

		// Release the unicode string
		CFRelease (str);
		#else
		MoveTo (xPos, yPos);
		DrawText ((Ptr)string, 0, stringLength);
		#endif
		
		SetClip (saveRgn);
		DisposeRgn (saveRgn);
		TextMode (srcOr);
		SetGWorld (OrigPort, OrigDevice);
	}
        #endif
        
#elif MOTIF
	int width;
	int fontHeight = pFontInfoStruct->ascent + pFontInfoStruct->descent;
	int xPos;
	int yPos;
	int rectHeight = rect.height ();

	if (rectHeight >= fontHeight)
		yPos = rect.bottom - (rectHeight - fontHeight) / 2;
	else 
		yPos = rect.bottom;
	yPos -=	pFontInfoStruct->descent;

	switch (hAlign)
	{
	case kCenterText:
		width = XTextWidth (pFontInfoStruct, string, strlen (string));
		xPos = (rect.right + rect.left - width) / 2;
		break;
		
	case kRightText:
		width = XTextWidth (pFontInfoStruct, string, strlen (string));
		xPos = rect.right - width;
		break;
		
	default: // left adjust
		xPos = rect.left + 1;
	}
	
	if (opaque)
		XDrawImageString (XDRAWPARAM, xPos, yPos, string, strlen (string));
	else
		XDrawString (XDRAWPARAM, xPos, yPos, string, strlen (string));

#elif BEOS
	BRect r (rect.left, rect.top, rect.right - 1, rect.bottom - 1);
	BRegion LocalRegion (r);
	pView->ConstrainClippingRegion (&LocalRegion);
	pView->SetFontSize (fontSize);
	float width = -1;
	if (opaque)
	{
		width = ceil (pView->StringWidth (string));
		CRect cr (rect.left, rect.top, rect.left + width, rect.bottom);
		fillRect (cr);
	}
	rgb_color c = { fontColor.red, fontColor.green, fontColor.blue, 255 };
	pView->SetHighColor (c);
	if (drawMode == kXorMode)
		pView->SetDrawingMode (B_OP_INVERT);
	else
		pView->SetDrawingMode (B_OP_OVER);
	BPoint		p;
	font_height	height;
	pView->GetFontHeight (&height);
	p.y = r.bottom - (rect.height () - height.ascent) / 2;
	if (hAlign == kCenterText || hAlign == kRightText)
	{
		if (width < 0)
			width = ceil (pView->StringWidth (string));
		if (hAlign == kCenterText)
			p.x = rect.left + (rect.right - rect.left - width) / 2;
		else
			p.x = rect.right - width - 1;
	}
	else
		p.x = rect.left + 1;
	pView->DrawString (string, p);
	pView->ConstrainClippingRegion (NULL);
#endif
}

//-----------------------------------------------------------------------------
long CDrawContext::getMouseButtons ()
{
	long buttons = 0;
	
#if WINDOWS
	if (GetAsyncKeyState (VK_LBUTTON) < 0)
		buttons |= (bSwapped_mouse_buttons ? kRButton : kLButton);
	if (GetAsyncKeyState (VK_MBUTTON) < 0)
		buttons |= kMButton;
	if (GetAsyncKeyState (VK_RBUTTON) < 0)
		buttons |= (bSwapped_mouse_buttons ? kLButton : kRButton);
	
	if (GetAsyncKeyState (VK_SHIFT)   < 0)
		buttons |= kShift;
	if (GetAsyncKeyState (VK_CONTROL) < 0)
		buttons |= kControl;
	if (GetAsyncKeyState (VK_MENU)    < 0)
		buttons |= kAlt;

#elif MAC
	#if MACX // this works for MacOSX 10.2 and later
	UInt32 state = GetCurrentButtonState ();
	if (state & kEventMouseButtonPrimary)
		buttons |= kLButton;
	if (state & kEventMouseButtonSecondary)
		buttons |= kRButton;
	if (state & 4)//kEventMouseButtonTertiary) this define is false...Apple ?
		buttons |= kMButton;

	state = GetCurrentKeyModifiers ();
	if (state & cmdKey)
		buttons |= kControl;
	if (state & shiftKey)
		buttons |= kShift;
	if (state & optionKey)
		buttons |= kAlt;
	if (state & controlKey)
		buttons |= kApple;
	// for the one buttons
	if (buttons & kApple && buttons & kLButton)
	{
		buttons &= ~(kApple | kLButton);
		buttons |= kRButton;
	}
	#else
	if (Button ())
		buttons |= kLButton;
	
	KeyMap	Keys;
	unsigned char *BytePtr = (unsigned char*)Keys;
	GetKeys (Keys);
	
	if (BytePtr[7] & 1)		// Shift   		0x38 == 56 = (7 * 8) + 0
		buttons |= kShift;
	if (BytePtr[7] & 8)		// Control (extra Mac) 0x3B == 59 = (7 * 8) + 3
		buttons |= kApple;			
	if (BytePtr[7] & 4)		// Alt   		0x3A == 58 = (7 * 8) + 2
		buttons |= kAlt;			
	if (BytePtr[6] & 128)	// Apple => ctrl (PC)  0x37 == 55 = (6 * 8) + 7
		buttons |= kControl;
	#endif

#elif MOTIF
	Window root, child;
	long rootX, rootY, childX, childY;
	unsigned int mask;
	int result = XQueryPointer (XWINPARAM, &root, &child, &rootX, &rootY,
								&childX, &childY, &mask);
	if (mask & Button1Mask)
		buttons |= kLButton;
	if (mask & Button2Mask)
		buttons |= kMButton;
	if (mask & Button3Mask)
		buttons |= kRButton;

	if (mask & ShiftMask)
		buttons |= kShift;
	if (mask & ControlMask)
		buttons |= kControl;
	if (mask & Mod1Mask)
		buttons |= kAlt;

#elif BEOS
	BPoint	where;
	uint32	b;
	pView->GetMouse (&where, &b);
	if (b & B_PRIMARY_MOUSE_BUTTON)
		buttons |= kLButton;
	if (b & B_SECONDARY_MOUSE_BUTTON)
		buttons |= kRButton;
	if (b & B_TERTIARY_MOUSE_BUTTON)
		buttons |= kMButton;
	int32 m = modifiers ();
	if (m & B_SHIFT_KEY)
		buttons |= kShift;
	if (m & B_COMMAND_KEY)
		buttons |= kControl;
	if (m & B_OPTION_KEY)
		buttons |= kApple;
	if (m & B_CONTROL_KEY)
		buttons |= kAlt;
#endif
	
	return buttons;
}

//-----------------------------------------------------------------------------
void CDrawContext::getMouseLocation (CPoint &point)
{
#if WINDOWS
	POINT where;
	GetCursorPos (&where);
	point (where.x, where.y);

#elif MACX
	#if 0 // QUARTZ // does not work sic!
	Point where;
	UInt32 mod;
	MouseTrackingResult result;
	if (TrackMouseLocationWithOptions ((CGrafPtr)-1, 0, kEventDurationNoWait, &where, &mod, &result) == noErr)
	{
		QDGlobalToLocalPoint (getPort (), &where);
		point (where.h, where.v);
	}
	#else
	Point where;
	CGrafPtr savedPort;
	Boolean portChanged = QDSwapPort (getPort (), &savedPort);
	GetMouse (&where);
	if (portChanged)
		QDSwapPort (savedPort, NULL);
	point (where.h, where.v);
	#endif
	#if QUARTZ
	point.offset (pFrame->hiScrollOffset.x,pFrame->hiScrollOffset.y);
	#endif
#elif MAC
	Point where;
	GetMouse (&where);
	point (where.h, where.v);
	
#elif MOTIF
	Window root, child;
	int rootX, rootY, childX, childY;
	unsigned int mask;
	int result = XQueryPointer (XWINPARAM, &root, &child, &rootX, &rootY, 
								&childX, &childY, &mask);
	point (childX, childY);

#elif BEOS
	BPoint	where;
	uint32	b;
	pView->GetMouse (&where, &b);
	point (where.x, where.y);
#endif

	point.offset (-offsetScreen.h, -offsetScreen.v);
}

//-----------------------------------------------------------------------------
bool CDrawContext::waitDoubleClick ()
{
	bool doubleClick = false;

#if WINDOWS
	CPoint mouseLoc;
	getMouseLocation (mouseLoc);
	CRect observe (mouseLoc.h - 2, mouseLoc.v - 2, mouseLoc.h + 2, mouseLoc.v + 2);

	DWORD currentTime = GetTickCount ();
	DWORD clickTime = GetMessageTime () + (DWORD)GetDoubleClickTime ();

	MSG message;
	while (currentTime < clickTime)
	{
		getMouseLocation (mouseLoc);
		if (!observe.pointInside (mouseLoc))
			break;

		if (PeekMessage (&message, 0, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_REMOVE | PM_NOYIELD)) 
		{
			doubleClick = true;
			break;
		}
		
		currentTime = GetTickCount ();
	}

#elif MAC
	#if MACX
	#if QUARTZ
	EventTimeout timeout = GetDblTime () * kEventDurationSecond / 60;
	const EventTypeSpec eventTypes[] = { { kEventClassMouse, kEventMouseDown }, { kEventClassMouse, kEventMouseDragged } };
	EventRef event;
	if (ReceiveNextEvent (GetEventTypeCount (eventTypes), eventTypes, timeout, true, &event) == noErr)
	{
		if (GetEventKind (event) == kEventMouseDown)
		{
			doubleClick = true;
		}
		ReleaseEvent (event);
	}
	
	#else
	unsigned long clickTime, doubletime;
	EventRecord downEvent;

	doubletime = GetDblTime ();
	clickTime = TickCount () + doubletime;
	while (TickCount () < clickTime)
	{
		if (GetNextEvent (mDownMask, &downEvent))
		{
			doubleClick = true;
			break;
		}
	}
	#endif // !QUARTZ

	#else
	long clickTime, doubleTime;
	EventRecord downEvent;

	#define MOUSE_IS_DOWN   ((* (char*)0x172) >= 0)

	doubleTime = GetDblTime () / 2;
	clickTime  = TickCount () + doubleTime;
	
	while (TickCount () < clickTime)
		if (!MOUSE_IS_DOWN) break;        /* look for mouse up! */
	
	if (GetNextEvent (mUpMask, &downEvent))
	{
		clickTime += doubleTime;
		while (TickCount () < clickTime)
			if (MOUSE_IS_DOWN) break; /* look for mouse down! */
		if (GetNextEvent (mDownMask, &downEvent))
			doubleClick = true;
	}
	#endif
#elif MOTIF	
	long currentTime = _getTicks ();
	long clickTime = currentTime + XtGetMultiClickTime (pDisplay);
	
	XEvent e;
	while (currentTime < clickTime)
	{
		if (XCheckTypedEvent (pDisplay, ButtonPress, &e))
		{
			doubleClick = true;
			break;
		}
	
		currentTime = _getTicks ();
	}

#elif BEOS
	const bigtime_t snoozeTime = 5000;
	bigtime_t	latest = system_time ();
	bigtime_t	doubleclicktime;
	get_click_speed (&doubleclicktime);
	latest += doubleclicktime;
	BPoint	location;
	uint32	buttons;
	pView->GetMouse (&location, &buttons);
	while (buttons)	// user should release the mouse button
	{
		if (system_time () > latest)
			return false;

		snooze (snoozeTime);
		pView->GetMouse (&location, &buttons);
	}
	
	while (!buttons)
	{
		if (system_time () > latest)
			return false;

		snooze (snoozeTime);
		pView->GetMouse (&location, &buttons);
	}
	
	doubleClick = true;

#endif

	return doubleClick;
}

//-----------------------------------------------------------------------------
bool CDrawContext::waitDrag ()
{
	#if MACX && QUARTZ
	bool dragged = false;
	if (GetCurrentEventButtonState () & kEventMouseButtonPrimary)
	{
		const EventTypeSpec eventTypes[] = { { kEventClassMouse, kEventMouseUp }, { kEventClassMouse, kEventMouseDown }, { kEventClassMouse, kEventMouseDragged } };
		EventRef event;
		if (ReceiveNextEvent (GetEventTypeCount (eventTypes), eventTypes, kEventDurationForever, true, &event) == noErr)
		{
			if (GetEventKind (event) == kEventMouseDragged)
			{
				dragged = true;
			}
			ReleaseEvent (event);
		}
	}
	return dragged;

	#else
	if (!pFrame)
		return false;
	
	CPoint mouseLoc;
	getMouseLocation (mouseLoc);
	CRect observe (mouseLoc.h - 2, mouseLoc.v - 2, mouseLoc.h + 2, mouseLoc.v + 2);
	
	long currentTime = pFrame->getTicks ();
	bool wasOutside = false;

	while (((getMouseButtons () & ~(kMButton|kRButton)) & kLButton) != 0)
	{
		pFrame->doIdleStuff ();
		if (!wasOutside)
		{
			getMouseLocation (mouseLoc);
			if (!observe.pointInside (mouseLoc))
			{
				if (kDragDelay <= 0)
					return true;
				wasOutside = true;
			}
		}

		if (wasOutside && (pFrame->getTicks () - currentTime > kDragDelay))
			return true;
	}
	return false;
	#endif
}

//-----------------------------------------------------------------------------
void CDrawContext::forget ()
{
	#if QUARTZ
	synchronizeCGContext ();
	#endif
	CReferenceCounter::forget ();
}

//-----------------------------------------------------------------------------
#if MOTIF
//-----------------------------------------------------------------------------
long CDrawContext::getIndexColor (CColor color)
{
	// 24bit visual ?
	if (pFrame->getDepth () == 24) 
		return (unsigned int)color.blue << 16 | (unsigned int)color.green << 8 | (unsigned int)color.red;

	// 8bit stuff
	return getIndexColor8Bit (color, pDisplay, pFrame->getColormap ());
}

//-----------------------------------------------------------------------------
Colormap CDrawContext::getColormap ()
{
	if (pFrame)
		return pFrame->getColormap ();
	else
		return NULL;
}

//-----------------------------------------------------------------------------
Visual* CDrawContext::getVisual ()
{
	if (pFrame)
		return pFrame->getVisual ();
	else
		return NULL;
}

//-----------------------------------------------------------------------------
unsigned int CDrawContext::getDepth ()
{
	if (pFrame)
		return pFrame->getDepth ();
	else
		return NULL;
}

//-----------------------------------------------------------------------------
#elif BEOS
//-----------------------------------------------------------------------------
void CDrawContext::lineFromTo (CPoint& cstart, CPoint& cend)
{
	BPoint start (cstart.h, cstart.v);
	BPoint end (cend.h, cend.v);
	if (start.x == end.x)
	{
		if (start.y < end.y)
			end.y--;
		else if (end.y < start.y)
			start.y--;
	}
	else if (start.y == end.y)
	{
		if (start.x < end.x)
			end.x--;
		else if (end.x < start.x)
			start.x--;
	}
	else
	{
		if (start.x > end.x)
		{
			BPoint t = end;
			end = start;
			start = t;
		}
		end.x--;
		if (end.y > start.y)
			end.y--;
		else
			end.y++;
	}
	
	pView->MovePenTo (start);
	if (lineStyle == kLineSolid)
		pView->StrokeLine (end);
	else
	{
		pattern stripes = { {0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3} };
		pView->StrokeLine (end, stripes);
	}
}

//-----------------------------------------------------------------------------
#elif MAC
#if QUARTZ
//-----------------------------------------------------------------------------
CGContextRef CDrawContext::beginCGContext (bool swapYAxis)
{
	if (gCGContext)
	{
		CGContextSaveGState (gCGContext);
		CGContextScaleCTM (gCGContext, 1, -1);
		QuartzSetupClip (gCGContext, clipRect);
		if (!swapYAxis)
			CGContextScaleCTM (gCGContext, 1, -1);
		return gCGContext;
	}
	return 0;
}

//-----------------------------------------------------------------------------
void CDrawContext::releaseCGContext (CGContextRef context)
{
	if (context)
	{
		CGContextRestoreGState (context);
		needToSynchronizeCGContext = true;
	}
}

//-----------------------------------------------------------------------------
void CDrawContext::synchronizeCGContext ()
{
	if (needToSynchronizeCGContext && gCGContext)
	{
		CGContextSynchronize (gCGContext);
		needToSynchronizeCGContext = false;
	}
}

//-----------------------------------------------------------------------------
CGImageRef CDrawContext::getCGImage () const
{
	return 0;
}

//-----------------------------------------------------------------------------
void QuartzSetupClip (CGContextRef context, const CRect clipRect)
{
	CGRect cgClipRect = CGRectMake (clipRect.left, clipRect.top, clipRect.width (), clipRect.height ());
	CGContextClipToRect (context, cgClipRect);
}

//-----------------------------------------------------------------------------
void QuartzSetLineDash (CGContextRef context, CLineStyle style, CCoord lineWidth)
{
	if (style == kLineOnOffDash)
	{
		float offset = 0;
		float dotf[2] = { lineWidth, lineWidth };
		CGContextSetLineDash (context, offset, dotf, 2);
	}
}
#endif

//-----------------------------------------------------------------------------
BitMapPtr CDrawContext::getBitmap ()
{
	#if QUARTZ
	return (BitMapPtr)GetPortBitMapForCopyBits (GetWindowPort ((WindowRef)pWindow));
	#else
	PixMapHandle pixMap = GetPortPixMap (GetWindowPort ((WindowRef)pWindow));
	if (pixMap)
	{
		LockPixels (pixMap);
		return (BitMapPtr)*pixMap;
	}
	#endif
	return 0;
}

//-----------------------------------------------------------------------------
void CDrawContext::releaseBitmap ()
{
	#if !QUARTZ
	PixMapHandle pixMap = GetPortPixMap (GetWindowPort ((WindowRef)pWindow));
	UnlockPixels (pixMap);
	#endif
}

//-----------------------------------------------------------------------------
CGrafPtr CDrawContext::getPort ()
{
	#if QUARTZ
	if (pWindow)
		return (CGrafPtr)GetWindowPort ((WindowRef)pWindow);
	return 0;
	#else
	if (!bInitialized)
	{
		CGrafPtr OrigPort;
		GDHandle OrigDevice;
		GetGWorld (&OrigPort, &OrigDevice);
		SetGWorld ((CGrafPtr)GetWindowPort ((WindowRef)pWindow), NULL);
	
		TextMode (srcOr);
		PenMode (patCopy);
		StuffHex (&fillPattern, "\pFFFFFFFFFFFFFFFF");
	
		SetGWorld (OrigPort, OrigDevice);
		
		bInitialized = true;
	}
	return (CGrafPtr)GetWindowPort ((WindowRef)pWindow);
	#endif
}

#endif


//-----------------------------------------------------------------------------
// COffscreenContext Implementation
//-----------------------------------------------------------------------------
COffscreenContext::COffscreenContext (CDrawContext *pContext, CBitmap *pBitmapBg, bool drawInBitmap)
: CDrawContext (pContext->pFrame, NULL, NULL)
, pBitmap (0)
, pBitmapBg (pBitmapBg)
, height (20)
, width (20)
{
	if (pBitmapBg)
	{
		height = pBitmapBg->getHeight ();
		width  = pBitmapBg->getWidth ();
		
		clipRect (0, 0, width, height);
	}

	#if DEBUG
	gNbCOffscreenContext++;
	gBitmapAllocation += (long)height * (long)width;
	#endif
		
	bDestroyPixmap = false;
	
#if WINDOWS
	if (pOldBrush)
		SelectObject ((HDC)getSystemContext (), pOldBrush);
	if (pOldPen)
		SelectObject ((HDC)getSystemContext (), pOldPen);
	if (pOldFont)
		SelectObject ((HDC)getSystemContext (), pOldFont);
	pOldBrush = pOldPen = pOldFont = 0;

	pSystemContext = CreateCompatibleDC ((HDC)pContext->getSystemContext ());
	
	if (drawInBitmap)
		pWindow = pBitmapBg->getHandle ();
	else // create bitmap if no bitmap handle exists
	{
		bDestroyPixmap = true;
		pWindow = CreateCompatibleBitmap ((HDC)pContext->getSystemContext (), width, height);
	}
	oldBitmap = SelectObject ((HDC)pSystemContext, pWindow);

#elif MAC
	#if QUARTZ
	offscreenBitmap = 0;
	if (drawInBitmap)
	{
		if (pBitmapBg->getHandle ())
		{
			PixMapHandle pixMap = GetGWorldPixMap ((GWorldPtr)pBitmapBg->getHandle ());
			LockPixels (pixMap);
			size_t pixDepth = GetPixDepth (pixMap) / 4;
			size_t rowBytes = GetPixRowBytes (pixMap);
			gCGContext = CGBitmapContextCreate (GetPixBaseAddr (pixMap), (size_t)width, (size_t)height, pixDepth, rowBytes, GetGenericRGBColorSpace (), kCGImageAlphaPremultipliedFirst);
			if (gCGContext)
			{
				CGContextTranslateCTM (gCGContext, 0, (float)height);
				CGContextSetFillColorSpace (gCGContext, GetGenericRGBColorSpace ());
				CGContextSetStrokeColorSpace (gCGContext, GetGenericRGBColorSpace ());
				CGAffineTransform cgCTM = CGAffineTransformMake (1.0, 0.0, 0.0, -1.0, 0.0, 0.0);
				CGContextSetTextMatrix (gCGContext, cgCTM);
				CGContextSaveGState (gCGContext);
			}
		}
	}
	else
	{ // todo !!!
	}
	
	#else
	
	if (drawInBitmap)
		pWindow = pBitmapBg->getHandle ();
	else
	{
		Rect	GWRect;
		GWRect.top  = 0;
		GWRect.left = 0;
		GWRect.right  = width;
		GWRect.bottom = height;
		NewGWorld ((GWorldPtr*)&pWindow, 0, &GWRect, NULL, NULL, 0);
		bDestroyPixmap = true;
	}

	StuffHex (&fillPattern, "\pFFFFFFFFFFFFFFFF");
	#endif
        
#elif MOTIF
 	// if no bitmap handle => create one
	if (!pWindow)
	{
		Drawable dWindow = pContext->pFrame->getWindow ();
		pWindow = (void*)XCreatePixmap (pDisplay, dWindow, width, height, pFrame->getDepth ());
		bDestroyPixmap = true;
	}

	// set the current font
	if (pSystemContext)
		setFont (kNormalFont);

#elif BEOS
	bDestroyPixmap = true;
	offscreenBitmap = new BBitmap (BRect (0, 0, width - 1, height - 1), B_RGB16, true, false);
	pView = new BView (BRect (0, 0, width - 1, height - 1), NULL, 0, 0);
	offscreenBitmap->Lock ();
	offscreenBitmap->AddChild (pView);

#endif

	if (!drawInBitmap)
	{
		// draw bitmap to Offscreen
		CRect r (0, 0, width, height);
		if (pBitmapBg)
			pBitmapBg->draw (this, r);
		else
		{
			setFillColor (kBlackCColor);
			fillRect (r);
		}
	}
}

//-----------------------------------------------------------------------------
COffscreenContext::COffscreenContext (CFrame *pFrame, long width, long height, const CColor backgroundColor)
: CDrawContext (pFrame, NULL, NULL)
, pBitmap (0)
, pBitmapBg (0)
, height (height)
, width (width)
, backgroundColor (backgroundColor)
{
	clipRect (0, 0, width, height);

	#if DEBUG
	gNbCOffscreenContext++;
	gBitmapAllocation += height * width;
	#endif

	bDestroyPixmap = true;

#if WINDOWS
	void *SystemWindow = pFrame->getSystemWindow ();
	void *SystemContext = GetDC ((HWND)SystemWindow);
	
	pSystemContext = CreateCompatibleDC ((HDC)SystemContext);
	#if DEBUG
	gNbDC++;
	#endif
	pWindow = CreateCompatibleBitmap ((HDC)SystemContext, width, height);

	oldBitmap = SelectObject ((HDC)pSystemContext, pWindow);
	ReleaseDC ((HWND)SystemWindow, (HDC)SystemContext);

	CRect r (0, 0, width, height);
	setFillColor (backgroundColor);
	setFrameColor (backgroundColor);
	fillRect (r);
	drawRect (r);

#elif MAC
	#if QUARTZ
	CGContextRef    context = NULL; 
	int             bitmapByteCount; 
	int             bitmapBytesPerRow; 

	// each pixel is represented by four bytes 
	// (8 bits each of alpha, R, G, B) 
	bitmapBytesPerRow   = width * 4; 
	bitmapByteCount     = bitmapBytesPerRow * height; 

	// create the bitmap 
	offscreenBitmap = malloc (bitmapByteCount);
	if (offscreenBitmap != NULL)
	{
		memset (offscreenBitmap, 0, bitmapByteCount);
		// create the context 
		context = CGBitmapContextCreate (offscreenBitmap,
		width, 
		height, 
		8,              // bits per component 
		bitmapBytesPerRow, 
		GetGenericRGBColorSpace (), 
		kCGImageAlphaPremultipliedFirst);

		if (context == NULL)
		{
			// the context couldn't be created for some reason, 
			// and we have no use for the bitmap without the context 
			free (offscreenBitmap);
			offscreenBitmap = 0;
		}
		else
		{
			CGContextTranslateCTM (context, 0, (float)height);
			CGContextSetFillColorSpace (context, GetGenericRGBColorSpace ());
			CGContextSetStrokeColorSpace (context, GetGenericRGBColorSpace ()); 
			CGAffineTransform cgCTM = CGAffineTransformMake (1.0, 0.0, 0.0, -1.0, 0.0, 0.0);
			CGContextSetTextMatrix (context, cgCTM);
			CGContextSaveGState (context);
			CGRect r = CGRectMake (0, 0, width, height);
			CGContextClearRect (context, r);
		}
	}
	gCGContext = context;

	CRect r (0, 0, width, height);
	setFillColor (backgroundColor);
	setFrameColor (backgroundColor);
	fillRect (r);
	drawRect (r);


	#else
	QDErr	err;
	Rect	GWRect;
	
	GWRect.top = GWRect.left = 0;
	GWRect.right = width;
	GWRect.bottom = height;
	err = NewGWorld ((GWorldPtr*) &pWindow, 0, &GWRect, NULL, NULL, 0);
	if (err)
		pWindow = NULL;

	StuffHex (&fillPattern, "\pFFFFFFFFFFFFFFFF");

	CRect r (0, 0, width, height);
	setFillColor (backgroundColor);
	setFrameColor (backgroundColor);
	fillRect (r);
	drawRect (r);
	#endif
        
#elif MOTIF
	Drawable dWindow = pFrame->getWindow ();

	pWindow = (void*)XCreatePixmap (pDisplay, dWindow, width, height, pFrame->getDepth ());

	// clear the pixmap
	XGCValues values;
	values.foreground = getIndexColor (backgroundColor);
	GC gc = XCreateGC (pDisplay, (Drawable)pWindow, GCForeground, &values); 
	XFillRectangle (pDisplay, (Drawable)pWindow, gc, 0, 0, width, height);
	XFreeGC (pDisplay, gc);
	
	// set the current font
	if (pSystemContext)
		setFont (kNormalFont);

#elif BEOS
	BRect frame (0, 0, width - 1, height - 1);
	offscreenBitmap = new BBitmap (frame, B_RGB16, true, false);
	pView = new BView (BRect (0, 0, width - 1, height - 1), NULL, 0, 0);
	offscreenBitmap->Lock ();
	offscreenBitmap->AddChild (pView);
	if (backgroundColor.red != 255 || backgroundColor.green != 255 || backgroundColor.blue != 255)
	{
		rgb_color c = { backgroundColor.red, backgroundColor.green, backgroundColor.blue, 255 };
		pView->SetHighColor (c);
		pView->FillRect (frame);
	}
#endif
}

//-----------------------------------------------------------------------------
COffscreenContext::~COffscreenContext ()
{
	#if DEBUG
	gNbCOffscreenContext--;
	gBitmapAllocation -= (long)height * (long)width;
	#endif

	if (pBitmap)
		pBitmap->forget ();

#if WINDOWS
	if (pSystemContext)
	{
		DeleteDC ((HDC)pSystemContext);
		pSystemContext = 0;
		#if DEBUG
		gNbDC--;
		#endif
	}
	if (bDestroyPixmap && pWindow)
		DeleteObject (pWindow);

#elif MAC
	#if QUARTZ
	if (gCGContext)
	{
		CGContextRestoreGState (gCGContext);
		CGContextRelease (gCGContext);
	}
	gCGContext = 0;
	if (offscreenBitmap)
		free (offscreenBitmap);
	else if (pBitmapBg && pBitmapBg->getHandle ())
	{
		PixMapHandle pixMap = GetGWorldPixMap ((GWorldPtr)pBitmapBg->getHandle ());
		UnlockPixels (pixMap);
	}
	#else
	if (bDestroyPixmap && pWindow)
		DisposeGWorld ((GWorldPtr)pWindow);
	#endif
        
#elif MOTIF
	if (bDestroyPixmap && pWindow)
		XFreePixmap (pDisplay, (Pixmap)pWindow);

#elif BEOS
	delete offscreenBitmap;
	pView = 0;	// deleted because attached to the offscreen
#endif
}

//-----------------------------------------------------------------------------
void COffscreenContext::copyTo (CDrawContext* pContext, CRect& srcRect, CPoint destOffset)
{
#if WINDOWS
	BitBlt ((HDC)pSystemContext,
			destOffset.h,
			destOffset.v,
			srcRect.width (),
			srcRect.height (),
			(HDC)pContext->getSystemContext (),
			srcRect.left + pContext->offset.h,
			srcRect.top + pContext->offset.v,
			SRCCOPY);
			
#elif MAC
	#if QUARTZ
	if (!pBitmapBg)
		return;
	#else
	if (!pWindow)
		return;
	#endif
	
	Rect source, dest;
	RGBColor savedForeColor, savedBackColor;
	
	source.left   = (short)(srcRect.left + pContext->offset.h + pContext->offsetScreen.h);
	source.top    = (short)(srcRect.top + pContext->offset.v + pContext->offsetScreen.v);
	source.right  = (short)(source.left + srcRect.right - srcRect.left);
	source.bottom = (short)(source.top + srcRect.bottom - srcRect.top);
	
	dest.left   = (short)destOffset.h;
	dest.top    = (short)destOffset.v;
	dest.right  = (short)(dest.left + srcRect.right - srcRect.left);
	dest.bottom = (short)(dest.top + srcRect.bottom - srcRect.top);

	GetForeColor (&savedForeColor);
	GetBackColor (&savedBackColor);
	::BackColor (whiteColor);
	::ForeColor (blackColor);

	CopyBits (pContext->getBitmap (), getBitmap (), &source, &dest, srcCopy, 0L);
	releaseBitmap ();
	pContext->releaseBitmap ();

	RGBForeColor (&savedForeColor);
	RGBBackColor (&savedBackColor);
#endif
}

//-----------------------------------------------------------------------------
void COffscreenContext::copyFrom (CDrawContext *pContext, CRect destRect, CPoint srcOffset)
{
#if WINDOWS
	BitBlt ((HDC)pContext->getSystemContext (),  // hdcDest
					destRect.left + pContext->offset.h, // xDest
					destRect.top + pContext->offset.v,  // yDest
					destRect.right - destRect.left,     // xWidth,
					destRect.bottom - destRect.top,     // yHeight
          
					(HDC)pSystemContext,                // hdcSrc
					srcOffset.h,                        // xSrc
					srcOffset.v,                        // ySrc
					SRCCOPY);                           // dwROP

#elif MAC
	#if QUARTZ
	if (!gCGContext)
		return;
	CGContextRef context = pContext->beginCGContext ();
	if (context)
	{
		size_t pixRowBytes = CGBitmapContextGetBytesPerRow (gCGContext);
		short pixDepth = CGBitmapContextGetBitsPerPixel (gCGContext);
		size_t size = pixRowBytes * CGBitmapContextGetHeight (gCGContext);

		CGImageRef image = 0;
		CGDataProviderRef provider = CGDataProviderCreateWithData (NULL, CGBitmapContextGetData (gCGContext), size, NULL);
		CGImageAlphaInfo alphaInfo = CGBitmapContextGetAlphaInfo (gCGContext);
		image = CGImageCreate (CGBitmapContextGetWidth (gCGContext), CGBitmapContextGetHeight (gCGContext), 8 , pixDepth, pixRowBytes, GetGenericRGBColorSpace (), alphaInfo, provider, NULL, 0, kCGRenderingIntentDefault);
		if (image)
		{
			CGRect dest;
			dest.origin.x = destRect.left - srcOffset.h + pContext->offset.h;
			dest.origin.y = (destRect.top + pContext->offset.v) * -1 - (getHeight () - srcOffset.v);
			dest.size.width = getWidth ();
			dest.size.height = getHeight ();
			
			CGRect clipRect;
			clipRect.origin.x = destRect.left + pContext->offset.h;
		    clipRect.origin.y = (destRect.top + pContext->offset.v) * -1  - destRect.height ();
		    clipRect.size.width = destRect.width (); 
		    clipRect.size.height = destRect.height ();
			
			CGContextClipToRect (context, clipRect);

			CGContextDrawImage (context, dest, image);
			
			CGImageRelease (image);
		}
		CGDataProviderRelease (provider);
		
		pContext->releaseCGContext (context);
	}
	#else
	if (!pWindow)
		return;

	Rect source, dest;
	RGBColor savedForeColor, savedBackColor;
	
	source.left   = srcOffset.h;
	source.top    = srcOffset.v;
	source.right  = source.left + destRect.right - destRect.left;
	source.bottom = source.top + destRect.bottom - destRect.top;
	
	dest.top    = destRect.top + pContext->offset.v;
	dest.left   = destRect.left + pContext->offset.h;
	dest.bottom = destRect.bottom + pContext->offset.v;
	dest.right  = destRect.right + pContext->offset.h;

	GetForeColor (&savedForeColor);
	GetBackColor (&savedBackColor);
	::BackColor (whiteColor);
	::ForeColor (blackColor);

	CopyBits (getBitmap (), pContext->getBitmap (), &source, &dest, srcCopy, 0L);
	#if MACX
	QDAddRectToDirtyRegion (pContext->getPort (), &dest);
	#endif
	releaseBitmap ();
	pContext->releaseBitmap ();

	RGBForeColor (&savedForeColor);
	RGBBackColor (&savedBackColor);
	#endif

#elif MOTIF
	XCopyArea (pDisplay, (Drawable)pWindow, (Drawable)pContext->getWindow (),
						 (GC)pSystemContext, srcOffset.h, srcOffset.v,
						 destRect.width (), destRect.height (),
						 destRect.left, destRect.top);

#elif BEOS
	pContext->pView->SetDrawingMode (B_OP_COPY);
	BRect destination (destRect.left, destRect.top, destRect.right - 1, destRect.bottom - 1);
	BRect source = destination;
	source.OffsetTo (srcOffset.h, srcOffset.v);
	pView->Sync ();
	pContext->pView->DrawBitmap (offscreenBitmap, source, destination);
#endif
}

//-----------------------------------------------------------------------------
#if MAC
#if QUARTZ
//-----------------------------------------------------------------------------
CGImageRef COffscreenContext::getCGImage () const
{
	#ifdef MAC_OS_X_VERSION_10_4
	if (CGBitmapContextCreateImage && gCGContext)
	{
		return CGBitmapContextCreateImage (gCGContext);
	}
	#endif
	return 0;
}

#endif

//-----------------------------------------------------------------------------
BitMapPtr COffscreenContext::getBitmap ()
{
	#if QUARTZ
	return pBitmapBg ? (BitMapPtr)GetPortBitMapForCopyBits ((GWorldPtr)pBitmapBg->getHandle ()) : 0;
	#else
	PixMapHandle pixMap = GetGWorldPixMap ((GWorldPtr)pWindow);
	if (pixMap)
	{
		LockPixels (pixMap);
		return (BitMapPtr)*pixMap;
	}
	return 0;
	#endif
}

//-----------------------------------------------------------------------------
void COffscreenContext::releaseBitmap ()
{
	#if QUARTZ
	#else
	PixMapHandle pixMap = GetGWorldPixMap ((GWorldPtr)pWindow);
	UnlockPixels (pixMap);
	#endif
}

#if !QUARTZ
//-----------------------------------------------------------------------------
CGrafPtr COffscreenContext::getPort ()
{
	if (!bInitialized)
		bInitialized = true;

	return (CGrafPtr)pWindow;
}
#endif // QUARTZ
#endif // MAC

//-----------------------------------------------------------------------------
class CAttributeListEntry
{
public:
	CAttributeListEntry (long size, CViewAttributeID id)
	: nextEntry (0)
	, pointer (0)
	, sizeOfPointer (size)
	, id (id)
	{
		pointer = malloc (size);
	}

	~CAttributeListEntry ()
	{
		if (pointer)
			free (pointer);
	}

	const CViewAttributeID getID () const { return id; }
	const long getSize () const { return sizeOfPointer; }
	void* getPointer () const { return pointer; }
	CAttributeListEntry* getNext () const { return nextEntry; }
	
	void setNext (CAttributeListEntry* entry) { nextEntry = entry; }

protected:
	CAttributeListEntry () : nextEntry (0), pointer (0), sizeOfPointer (0), id (0) {}

	CAttributeListEntry* nextEntry;
	void* pointer;
	long sizeOfPointer;
	CViewAttributeID id;
};

//-----------------------------------------------------------------------------
char* kMsgCheckIfViewContainer	= "kMsgCheckIfViewContainer";

//-----------------------------------------------------------------------------
// CView
//-----------------------------------------------------------------------------
/*! @class CView
base class of all view objects
*/
//-----------------------------------------------------------------------------
CView::CView (const CRect& size)
: size (size)
, mouseableArea (size)
, pParentFrame (0)
, pParentView (0)
, bDirty (false)
, bMouseEnabled (true)
, bTransparencyEnabled (false)
, bWantsFocus (false)
, pBackground (0)
, pAttributeList (0)
{
	#if DEBUG
	gNbCView++;
	#endif
}

//-----------------------------------------------------------------------------
CView::~CView ()
{
	if (pBackground)
		pBackground->forget ();

	if (pAttributeList)
	{
		CAttributeListEntry* entry = pAttributeList;
		while (entry)
		{
			CAttributeListEntry* nextEntry = entry->getNext ();
			delete entry;
			entry = nextEntry;
		}
	}
	#if DEBUG
	gNbCView--;
	#endif
}

//-----------------------------------------------------------------------------
void CView::getMouseLocation (CDrawContext* context, CPoint &point)
{
	if (context)
	{
		if (pParentView && pParentView->notify (this, kMsgCheckIfViewContainer) == kMessageNotified)
		{
			CCoord save[4];
			((CViewContainer*)pParentView)->modifyDrawContext (save, context);
			pParentView->getMouseLocation (context, point);
			((CViewContainer*)pParentView)->restoreDrawContext (context, save);
		}
		else
			context->getMouseLocation (point);
	}
}

#if ENABLE_DEPRECATED_METHODS
//-----------------------------------------------------------------------------
void CView::getFrameTopLeftPos (CPoint& topLeft) const
{
	topLeft.h += size.left;
	topLeft.v += size.top;
	if (pParentView && pParentView->notify (0, kMsgCheckIfViewContainer) == kMessageNotified)
		pParentView->getFrameTopLeftPos (topLeft);
}
#endif

//-----------------------------------------------------------------------------
CPoint& CView::frameToLocal (CPoint& point) const
{
	if (pParentView && pParentView->isTypeOf ("CViewContainer"))
		return pParentView->frameToLocal (point);
	return point;
}

//-----------------------------------------------------------------------------
CPoint& CView::localToFrame (CPoint& point) const
{
	if (pParentView && pParentView->isTypeOf ("CViewContainer"))
		return pParentView->localToFrame (point);
	return point;
}

//-----------------------------------------------------------------------------
void CView::redraw ()
{
	if (pParentFrame)
		pParentFrame->draw (this);
}

//-----------------------------------------------------------------------------
void CView::redrawRect (CDrawContext* context, const CRect& rect)
{
	// we always pass it on to the parent view as it knows what else must be drawn (needed for nested view containers)
	if (pParentView)
		pParentView->redrawRect (context, rect);
	else if (pParentFrame)
		pParentFrame->drawRect (context, rect);
}

//-----------------------------------------------------------------------------
void CView::draw (CDrawContext *pContext)
{
	if (pBackground)
	{
		if (bTransparencyEnabled)
			pBackground->drawTransparent (pContext, size);
		else
			pBackground->draw (pContext, size);
	}
	setDirty (false);
}

//-----------------------------------------------------------------------------
void CView::mouse (CDrawContext *pContext, CPoint &where, long buttons)
{}

//-----------------------------------------------------------------------------
bool CView::onWheel (CDrawContext *pContext, const CPoint &where, float distance)
{
	return false;
}

//------------------------------------------------------------------------
bool CView::onWheel (CDrawContext *pContext, const CPoint &where, const CMouseWheelAxis axis, float distance)
{
	return onWheel (pContext, where, distance);
}

//------------------------------------------------------------------------
void CView::update (CDrawContext *pContext)
{
	if (isDirty ())
	{
		#if NEW_UPDATE_MECHANISM
		if (pContext)
			redrawRect (pContext, size);
		else
			redraw ();
		#else
		#if USE_ALPHA_BLEND
		if (pContext)
		{
			if (bTransparencyEnabled)
				getFrame ()->drawRect (pContext, size);
			else
				draw (pContext);
		}
		#else
		if (pContext)
			draw (pContext);
		#endif
		else
			redraw ();
		#endif // !NEW_UPDATE_MECHANISM
		setDirty (false);
	}
}

//------------------------------------------------------------------------------
long CView::onKeyDown (VstKeyCode& keyCode)
{
	return -1;
}

//------------------------------------------------------------------------------
long CView::onKeyUp (VstKeyCode& keyCode)
{
	return -1;
}

//------------------------------------------------------------------------------
long CView::notify (CView* sender, const char* message)
{
	return kMessageUnknown;
}

//------------------------------------------------------------------------------
void CView::looseFocus (CDrawContext *pContext)
{}

//------------------------------------------------------------------------------
void CView::takeFocus (CDrawContext *pContext)
{}

//------------------------------------------------------------------------------
void CView::setViewSize (CRect &rect)
{
	size = rect;
	setDirty ();
}

//-----------------------------------------------------------------------------
void *CView::getEditor () const
{ 
	return pParentFrame ? pParentFrame->getEditor () : 0; 
}

//-----------------------------------------------------------------------------
void CView::setBackground (CBitmap *background)
{
	if (pBackground)
		pBackground->forget ();
	pBackground = background;
	if (pBackground)
		pBackground->remember ();
	setDirty (true);
}

//-----------------------------------------------------------------------------
const CViewAttributeID kCViewAttributeReferencePointer = 'cvrp';

//-----------------------------------------------------------------------------
/**
 * @param id the ID of the Attribute
 * @param outSize on return the size of the attribute
 */
bool CView::getAttributeSize (const CViewAttributeID id, long& outSize) const
{
	if (pAttributeList)
	{
		CAttributeListEntry* entry = pAttributeList;
		while (entry)
		{
			if (entry->getID () == id)
				break;
			entry = entry->getNext ();
		}
		if (entry)
		{
			outSize = entry->getSize ();
			return true;
		}
	}
	return false;
}

//-----------------------------------------------------------------------------
/**
 * @param id the ID of the Attribute
 * @param inSize the size of the outData pointer
 * @param outData a pointer where to copy the attribute data
 * @param outSize the size in bytes which was copied into outData
 */
bool CView::getAttribute (const CViewAttributeID id, const long inSize, void* outData, long& outSize) const
{
	if (pAttributeList)
	{
		CAttributeListEntry* entry = pAttributeList;
		while (entry)
		{
			if (entry->getID () == id)
				break;
			entry = entry->getNext ();
		}
		if (entry && inSize >= entry->getSize ())
		{
			outSize = entry->getSize ();
			memcpy (outData, entry->getPointer (), outSize);
			return true;
		}
	}
	return false;
}

//-----------------------------------------------------------------------------
/**
 * copies data into the attribute. If it does not exist, creates a new attribute.
 * @param id the ID of the Attribute
 * @param inSize the size of the outData pointer
 * @param inData a pointer to the data
 */
bool CView::setAttribute (const CViewAttributeID id, const long inSize, void* inData)
{
	CAttributeListEntry* lastEntry = 0;
	if (pAttributeList)
	{
		CAttributeListEntry* entry = pAttributeList;
		while (entry)
		{
			if (entry->getID () == id)
				break;
			if (entry->getNext () == 0)
				lastEntry = entry;
			entry = entry->getNext ();
		}
		if (entry)
		{
			if (entry->getSize () >= inSize)
			{
				memcpy (entry->getPointer (), inData, inSize);
				return true;
			}
			else
				return false;
		}
	}
	
	// create a new attribute
	CAttributeListEntry* newEntry = new CAttributeListEntry (inSize, id);
	memcpy (newEntry->getPointer (), inData, inSize);
	if (lastEntry)
		lastEntry->setNext (newEntry);
	else if (!pAttributeList)
		pAttributeList = newEntry;
	else
	{
		delete newEntry;
		return false;
	}
	return true;
}

#if DEBUG
//-----------------------------------------------------------------------------
void CView::dumpInfo ()
{
	CRect viewRect = getViewSize (viewRect);
	DebugPrint ("left:%4d, top:%4d, width:%4d, height:%4d ", viewRect.left, viewRect.top, viewRect.getWidth (), viewRect.getHeight ());
	if (getMouseEnabled ())
		DebugPrint ("(Mouse Enabled) ");
	if (getTransparency ())
		DebugPrint ("(Transparent) ");
	CRect mouseRect = getMouseableArea (mouseRect);
	if (mouseRect != viewRect)
		DebugPrint (" (Mouseable Area: left:%4d, top:%4d, width:%4d, height:%4d ", mouseRect.left, mouseRect.top, mouseRect.getWidth (), mouseRect.getHeight ());
}
#endif

#define FOREACHSUBVIEW for (CCView *pSv = pFirstView; pSv; pSv = pSv->pNext) {CView *pV = pSv->pView;
#define FOREACHSUBVIEW_REVERSE(reverse) for (CCView *pSv = reverse ? pLastView : pFirstView; pSv; pSv = reverse ? pSv->pPrevious : pSv->pNext) {CView *pV = pSv->pView;
#define ENDFOR }

//-----------------------------------------------------------------------------
// CFrame Implementation
//-----------------------------------------------------------------------------
/*! @class CFrame
It creates a platform dependend view object. 
On classic Mac OS it just draws into the provided window.
On Mac OS X it is a ControlRef. 
On Windows it's a WS_CHILD Window.
*/
CFrame::CFrame (const CRect &inSize, void *inSystemWindow, void *inEditor)
: CViewContainer (inSize, 0, 0)
, pEditor (inEditor)
, pSystemWindow (inSystemWindow)
, pModalView (0)
, pFocusView (0)
, bFirstDraw (true)
, bDropActive (false)
, bUpdatesDisabled (false)
, pFrameContext (0)
, bAddedWindow (false)
, pVstWindow (0)
, defaultCursor (0)
{
	setOpenFlag (true);
	
	pParentFrame = this;

#if WINDOWS
	pHwnd = 0;
	dropTarget = 0;
	backBuffer = 0;
	OleInitialize (0);

	#if DYNAMICALPHABLEND
	pfnAlphaBlend = 0;
	pfnTransparentBlt = 0;

	hInstMsimg32dll = LoadLibrary ("msimg32.dll");
	if (hInstMsimg32dll)
	{
		pfnAlphaBlend = (PFNALPHABLEND)GetProcAddress (hInstMsimg32dll, "AlphaBlend");

		// get OS version
		memset (&gSystemVersion, 0, sizeof (gSystemVersion));
		gSystemVersion.dwOSVersionInfoSize = sizeof (gSystemVersion);

		if (GetVersionEx ((OSVERSIONINFO *)&gSystemVersion))
		{
			// Is this win NT or better?
			if (gSystemVersion.dwPlatformId >= VER_PLATFORM_WIN32_NT)
			{
				// Yes, then TransparentBlt doesn't have the memory-leak and can be safely used
				pfnTransparentBlt = (PFNTRANSPARENTBLT)GetProcAddress (hInstMsimg32dll, "TransparentBlt");
			}
		}
	}
	#endif	// DYNAMICALPHABLEND
    
#elif MOTIF
	gc = 0;
	depth    = 0;
	pDisplay = 0;
	pVisual  = 0;
	window   = 0;

#elif BEOS
	pPlugView = NULL;
#endif

	initFrame (pSystemWindow);

#if WINDOWS
	#if USE_GLOBAL_CONTEXT
	pFrameContext = new CDrawContext (this, 0, getSystemWindow ());
	#endif

#elif MAC
	Gestalt (gestaltSystemVersion, &pSystemVersion);
	#if QUARTZ
	pFrameContext = 0;
	#else
	pFrameContext = new CDrawContext (this, getSystemWindow (), getSystemWindow ());
	pFrameContext->offset.h = size.left;
	pFrameContext->offset.v = size.top;
	#endif
	
#elif MOTIF
	pFrameContext = new CDrawContext (this, gc, (void*)window);
#endif
}

//-----------------------------------------------------------------------------
CFrame::CFrame (const CRect& inSize, const char* inTitle, void* inEditor, const long inStyle)
: CViewContainer (inSize, 0, 0)
, pEditor (inEditor)
, pSystemWindow (0)
, pModalView (0)
, pFocusView (0)
, bFirstDraw (true)
, bDropActive (false)
, bUpdatesDisabled (false)
, pFrameContext (0)
, pVstWindow (0) 
, defaultCursor (0)
{
	bAddedWindow  = true;
	setOpenFlag (false);
	pParentFrame = this;

#if WINDOWS
	pHwnd = 0;
	dropTarget = 0;
	backBuffer = 0;
	OleInitialize (0);

	#if DYNAMICALPHABLEND
	pfnAlphaBlend = 0;
	pfnTransparentBlt = 0;

	hInstMsimg32dll = LoadLibrary ("msimg32.dll");
	if (hInstMsimg32dll)
	{
		pfnAlphaBlend = (PFNALPHABLEND)GetProcAddress (hInstMsimg32dll, "AlphaBlend");

		// get OS version
		OSVERSIONINFOEX	osvi;

		memset (&osvi, 0, sizeof (osvi));
		osvi.dwOSVersionInfoSize = sizeof (osvi);

		if (GetVersionEx ((OSVERSIONINFO *)&osvi))
		{
			// Is this win NT or better?
			if (osvi.dwPlatformId >= VER_PLATFORM_WIN32_NT)
			{
				// Yes, then TransparentBlt doesn't have the memory-leak and can be safely used
				pfnTransparentBlt = (PFNTRANSPARENTBLT)GetProcAddress (hInstMsimg32dll, "TransparentBlt");
			}
		}
	}
	#endif
    
#elif MOTIF
	gc = 0;
	depth    = 0;
	pDisplay = 0;
	pVisual  = 0;
	window   = 0;

#elif BEOS
	pPlugView = NULL;

#endif

	#if USE_VST_WINDOW
	pVstWindow = (VstWindow*)malloc (sizeof (VstWindow));
	strcpy (((VstWindow*)pVstWindow)->title, inTitle);
	((VstWindow*)pVstWindow)->xPos   = (short)size.left;
	((VstWindow*)pVstWindow)->yPos   = (short)size.top;
	((VstWindow*)pVstWindow)->width  = (short)size.width ();
	((VstWindow*)pVstWindow)->height = (short)size.height ();
	((VstWindow*)pVstWindow)->style  = inStyle;
	((VstWindow*)pVstWindow)->parent     = 0;
	((VstWindow*)pVstWindow)->userHandle = 0;
	((VstWindow*)pVstWindow)->winHandle  = 0;
	#endif
}

//-----------------------------------------------------------------------------
CFrame::~CFrame ()
{
	if (pModalView)
		removeView (pModalView, false);

	setCursor (kCursorDefault);

	setDropActive (false);

	if (pFrameContext)
		pFrameContext->forget ();

#if WINDOWS
	OleUninitialize ();

	if (backBuffer)
		backBuffer->forget ();

	#if DYNAMICALPHABLEND
	if (hInstMsimg32dll)
		FreeLibrary (hInstMsimg32dll);
	#endif
		
	if (pHwnd)
	{
		SetWindowLongPtr ((HWND)pHwnd, GWLP_USERDATA, (long)NULL);
		DestroyWindow ((HWND)pHwnd);

		ExitWindowClass ();
	}

#elif MOTIF
 #if TEST_REGION
	XDestroyRegion (region);
 #endif

	// remove callbacks to avoid undesirable update
	if (pSystemWindow)
	{
		XtRemoveCallback ((Widget)pSystemWindow, XmNexposeCallback,  _drawingAreaCallback, this);
		XtRemoveCallback ((Widget)pSystemWindow, XmNinputCallback,   _drawingAreaCallback, this);
		XtRemoveCallback ((Widget)pSystemWindow, XmNdestroyCallback, _destroyCallback, this);
		
		freeGc ();
	}
#endif
	
	if (bAddedWindow)
		close ();
	if (pVstWindow)
		free (pVstWindow);

#if BEOS
	CBitmap::closeResource ();	// must be done only once at the end of the story.
#endif

#if MAC && QUARTZ
	if (controlRef)
		DisposeControl (controlRef);
	if (controlSpec.u.classRef)
	{
		OSStatus status = UnregisterToolboxObjectClass ((ToolboxObjectClassRef)controlSpec.u.classRef);
		if (status != noErr)
			fprintf (stderr, "UnregisterToolboxObjectClass failed : %d\n", (int)status);
	}
#endif
}

//-----------------------------------------------------------------------------
bool CFrame::open (CPoint *point)
{
#if PLUGGUI
	return false;
#else
	if (!bAddedWindow)
		return false;
	if (getOpenFlag ())
	{
#if WINDOWS
		BringWindowToTop (GetParent (GetParent ((HWND)getSystemWindow ())));

#elif MOTIF
		Widget widget = (Widget)getSystemWindow ();
		while (widget && !XtIsTopLevelShell (widget))
			widget = XtParent (widget);
		if (widget)
			XRaiseWindow (getDisplay (), XtWindow (widget));

#elif BEOS
		pPlugView->Window ()->Activate (true);
#endif
		return false;
	}

#if USE_VST_WINDOW
	if (pVstWindow)
	{
		if (point)
		{
			((VstWindow*)pVstWindow)->xPos = (short)point->h;
			((VstWindow*)pVstWindow)->yPos = (short)point->v;
		}
		AudioEffectX *pAudioEffectX = (AudioEffectX*)(((AEffGUIEditor*)pEditor)->getEffect ());
		pSystemWindow = pAudioEffectX->openWindow ((VstWindow*)pVstWindow);
	}
#endif

	if (pSystemWindow)
	{
		if (initFrame (pSystemWindow))
			setOpenFlag (true);
	}

	return getOpenFlag ();
#endif
}

//-----------------------------------------------------------------------------
bool CFrame::close ()
{
#if PLUGGUI
	return false;
#else
	if (!bAddedWindow || !getOpenFlag () || !pSystemWindow)
		return false;

#if USE_VST_WINDOW
	AudioEffectX *pAudioEffectX = (AudioEffectX*)(((AEffGUIEditor*)pEditor)->getEffect ());
	pAudioEffectX->closeWindow ((VstWindow*)pVstWindow);
#endif

	pSystemWindow = 0;

	return true;
#endif
}

//-----------------------------------------------------------------------------
bool CFrame::initFrame (void *systemWin)
{
	if (!systemWin)
		return false;
	
#if WINDOWS

	InitWindowClass ();
	pHwnd = CreateWindowEx (0, gClassName, "Window",
			 WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 
			 0, 0, size.width (), size.height (), 
			 (HWND)pSystemWindow, NULL, GetInstance (), NULL);

	SetWindowLongPtr ((HWND)pHwnd, GWLP_USERDATA, (LONG_PTR)this);

#elif MAC

	#if QUARTZ
	dragEventHandler = 0;
	if (!registerWithToolbox ())
		return false;

	hasFocus = false;
	Rect r = {(short)size.top, (short)size.left, (short)size.bottom, (short)size.right};
	OSStatus status = CreateCustomControl (NULL, &r, &controlSpec, NULL, &controlRef);
	if (status != noErr)
	{
		fprintf (stderr, "Could not create Control : %d\n", (int)status);
		return false;
	}
	EventTypeSpec keyWorkaroundEvents[] = {
		{ kEventClassTextInput, kEventTextInputUnicodeForKeyEvent }
	};
	InstallWindowEventHandler ((WindowRef)systemWin, carbonEventHandler, GetEventTypeCount (keyWorkaroundEvents), keyWorkaroundEvents, this, NULL);
	
	SetControlDragTrackingEnabled (controlRef, true);
	SetAutomaticControlDragTrackingEnabledForWindow ((WindowRef)systemWin, true);
	#if !AU // for AudioUnits define AU and embed the controlRef at your AUCarbonViewBase
	WindowAttributes attributes;
	GetWindowAttributes ((WindowRef)systemWin, &attributes);
	if (attributes & kWindowCompositingAttribute) 
	{
		HIViewRef contentView;
		HIViewRef rootView = HIViewGetRoot ((WindowRef)systemWin);
		if (HIViewFindByID (rootView, kHIViewWindowContentID, &contentView) != noErr)
			contentView = rootView;
		HIViewAddSubview (contentView, controlRef);
	}
	else
	{
		ControlRef rootControl;
		GetRootControl ((WindowRef)systemWin, &rootControl);
		if (rootControl == NULL)
			CreateRootControl ((WindowRef)systemWin, &rootControl);
		EmbedControl(controlRef, rootControl);	
	}
	#endif
	size.offset (-size.left, -size.top);
	mouseableArea.offset (-size.left, -size.top);
	#endif
	
#elif MOTIF
	// attach the callbacks
	XtAddCallback ((Widget)systemWin, XmNexposeCallback, _drawingAreaCallback, this);
	XtAddCallback ((Widget)systemWin, XmNinputCallback,  _drawingAreaCallback, this);
	XtAddCallback ((Widget)systemWin, XmNdestroyCallback, _destroyCallback, this);
	XtAddEventHandler ((Widget)systemWin, LeaveWindowMask, true, _eventHandler, this);

	// init a default gc
	window  = XtWindow ((Widget)systemWin);
	pDisplay = XtDisplay ((Widget)systemWin);
	XGCValues values;
	values.foreground = 1;
	gc = XCreateGC (pDisplay, (Drawable)window, GCForeground, &values); 
	
#if TEST_REGION
	region = XCreateRegion ();
#endif

	// get the std colormap
	XWindowAttributes attr;
	XGetWindowAttributes (pDisplay, window, &attr);
	colormap = attr.colormap;
	pVisual  = attr.visual;
	depth    = attr.depth;

	// init and load the fonts
	if (!gFontInit)
	{
		for (long i = 0; i < kNumStandardFonts; i++) 
		{
			gFontStructs[i] = XLoadQueryFont (pDisplay, gFontTable[i].string);
			assert (gFontStructs[i] != 0);
		}
		gFontInit = true;
	}

#elif BEOS
	BView* parentView = (BView*) pSystemWindow;
	BRect frame = parentView->Frame ();
	frame.OffsetTo (B_ORIGIN);
	pPlugView = new PlugView (frame, this);
	parentView->AddChild (pPlugView);
#endif

	setDropActive (true);

	return true;
}

//-----------------------------------------------------------------------------
bool CFrame::setDropActive (bool val)
{	
	if (!bDropActive && !val)
		return true;

#if WINDOWS
	if (!pHwnd)
		return false;
	if (dropTarget)
	{
		RevokeDragDrop ((HWND)pHwnd);
		dropTarget = 0;
	}
	if (val)
	{
		dropTarget = createDropTarget (this);
		RegisterDragDrop ((HWND)pHwnd, (IDropTarget*)dropTarget);
	}

#elif MAC
#if MAC_OLD_DRAG
	if (val)
		install_drop (this);
	else
		remove_drop (this);
#endif
#endif

	bDropActive = val;
	return true;
}

#if MOTIF
//-----------------------------------------------------------------------------
void CFrame::freeGc ()
{
	if (gc)
		XFreeGC (pDisplay, gc);
	gc = 0;
}
#endif

//-----------------------------------------------------------------------------
CDrawContext* CFrame::createDrawContext ()
{
	if (pFrameContext)
	{
		pFrameContext->remember ();
		return pFrameContext;
	}

	CDrawContext* pContext = 0;
	#if WINDOWS || MAC
	pContext = new CDrawContext (this, NULL, getSystemWindow ());

	#elif MOTIF
	pContext = new CDrawContext (this, gc, (void*)window);

	#elif BEOS
	pContext = new CDrawContext (this, pPlugView, 0);
	#endif
	
	return pContext;
}

//-----------------------------------------------------------------------------
void CFrame::draw (CDrawContext *pContext)
{
	if (bFirstDraw)
		bFirstDraw = false;
	
	if (!pContext)
		pContext = pFrameContext;

	// draw the background and the children
	CViewContainer::draw (pContext);
}

//-----------------------------------------------------------------------------
void CFrame::drawRect (CDrawContext *pContext, const CRect& updateRect)
{
	if (bFirstDraw)
		bFirstDraw = false;

	bool localContext = false;	
	if (!pContext)
	{
		localContext = true;
		pContext = createDrawContext ();
	}

	#if USE_CLIPPING_DRAWRECT
	CRect oldClip;
	pContext->getClipRect (oldClip);
	CRect newClip (updateRect);
	newClip.bound (oldClip);
	pContext->setClipRect (newClip);
	#endif
	
	// draw the background and the children
	if (updateRect.getWidth () > 0 && updateRect.getHeight () > 0)
		CViewContainer::drawRect (pContext, updateRect);

	#if USE_CLIPPING_DRAWRECT
	pContext->setClipRect (oldClip);
	#endif

	if (localContext)
		pContext->forget ();
}

//-----------------------------------------------------------------------------
void CFrame::draw (CView *pView)
{
	CView *pViewToDraw = 0;

		// Search it in the view list
	if (pView && isChild(pView))
		pViewToDraw = pView;

	CDrawContext *pContext = createDrawContext ();
	if (pContext)
	{
		if (pViewToDraw)
			pViewToDraw->draw (pContext);
		else
			draw (pContext);

		pContext->forget ();
	}
}

//-----------------------------------------------------------------------------
void CFrame::mouse (CDrawContext *pContext, CPoint &where, long buttons)
{
	if (!pContext)
		pContext = pFrameContext;
	
	if (pFocusView)
		setFocusView (NULL);

	if (buttons == -1 && pContext)
		buttons = pContext->getMouseButtons ();

	if (pModalView)
	{
		if (pModalView->hitTest (where, buttons))
			pModalView->mouse (pContext, where, buttons);
	}
	else 
	{
		CViewContainer::mouse (pContext, where, buttons);
	}
}

//-----------------------------------------------------------------------------
long CFrame::onKeyDown (VstKeyCode& keyCode)
{
	long result = -1;

	if (pFocusView)
		result = pFocusView->onKeyDown (keyCode);

	if (result == -1 && pModalView)
		result = pModalView->onKeyDown (keyCode);

	if (result == -1 && keyCode.virt == VKEY_TAB)
		result = advanceNextFocusView (pFocusView, (keyCode.modifier & MODIFIER_SHIFT) ? true : false) ? 1 : -1;

	return result;
}

//-----------------------------------------------------------------------------
long CFrame::onKeyUp (VstKeyCode& keyCode)
{
	long result = -1;

	if (pFocusView)
		result = pFocusView->onKeyUp (keyCode);

	if (result == -1 && pModalView)
		result = pModalView->onKeyUp (keyCode);

	return result;
}

//------------------------------------------------------------------------
bool CFrame::onWheel (CDrawContext *pContext, const CPoint &where, const CMouseWheelAxis axis, float distance)
{
	bool result = false;

	CView *view = pModalView ? pModalView : getViewAt (where);
	if (view)
	{
		bool localContext = false;
		if (!pContext)
		{
			localContext = true;
			pContext = createDrawContext ();
		}

		result = view->onWheel (pContext, where, axis, distance);

		if (localContext)
			pContext->forget ();
	
	#if BEOS
		pPlugView->UnlockLooper ();
	#endif
	}
	return result;
}

//-----------------------------------------------------------------------------
bool CFrame::onWheel (CDrawContext *pContext, const CPoint &where, float distance)
{
	return onWheel (pContext, where, kMouseWheelAxisY, distance);
}
		
//-----------------------------------------------------------------------------
void CFrame::update (CDrawContext *pContext)
{
	if (!getOpenFlag () || updatesDisabled ())
		return;

	#if WINDOWS && USE_ALPHA_BLEND
	CDrawContext* oldFrameContext = pFrameContext;
	CDrawContext* dc = pFrameContext = getBackBuffer ();
	#else
	CDrawContext* dc = pContext;
	#endif

	if (bDirty)
	{
		draw (dc);
		setDirty (false);
	}
	else
	{
		#if USE_CLIPPING_DRAWRECT
		CRect oldClipRect;
		dc->getClipRect (oldClipRect);
		#endif
		#if NEW_UPDATE_MECHANISM
		if (pModalView && pModalView->isDirty ())
			pModalView->update (dc);
		#endif
		FOREACHSUBVIEW
			#if USE_CLIPPING_DRAWRECT
			CRect viewSize (pV->size);
			viewSize.bound (oldClipRect);
			dc->setClipRect (viewSize);
			#endif
			pV->update (dc);
		ENDFOR
		#if USE_CLIPPING_DRAWRECT
		dc->setClipRect (oldClipRect);
		#endif
	}

	#if MACX && !QUARTZ
	if (QDIsPortBufferDirty (GetWindowPort ((WindowRef)pSystemWindow)))
	{
		QDFlushPortBuffer (GetWindowPort ((WindowRef)pSystemWindow), NULL);
	}
	#endif
	#if WINDOWS && USE_ALPHA_BLEND
	backBuffer->copyFrom (pContext, size);
	pFrameContext = oldFrameContext;
	#endif
}

//-----------------------------------------------------------------------------
void CFrame::idle ()
{
	if (!getOpenFlag ())
		return;

	#if MAC
	// if the window is collapsed, we don't need to draw anything
	if (pSystemWindow && IsWindowCollapsed ((WindowRef)pSystemWindow))
		return;
	#endif
	
	// don't do an idle before a draw
	if (bFirstDraw)
		return;

	if (!isDirty ())
		return;

	#if BEOS
	if (pPlugView->LockLooperWithTimeout (0) != B_OK)
		return;
	#endif

	CDrawContext *pContext = createDrawContext ();
	
	update (pContext);

	pContext->forget ();

	#if BEOS
	pPlugView->UnlockLooper ();
	#endif
}

//-----------------------------------------------------------------------------
void CFrame::doIdleStuff ()
{
#if PLUGGUI
	if (pEditor)
		((PluginGUIEditor*)pEditor)->doIdleStuff ();
#else
	if (pEditor)
		((AEffGUIEditor*)pEditor)->doIdleStuff ();
#endif
#if (MAC && QUARTZ)
	if (pFrameContext)
		pFrameContext->synchronizeCGContext ();
#endif
}

//-----------------------------------------------------------------------------
unsigned long CFrame::getTicks () const
{
#if PLUGGUI
	if (pEditor)
		return ((PluginGUIEditor*)pEditor)->getTicks ();
#else
	if (pEditor)
		return ((AEffGUIEditor*)pEditor)->getTicks ();
#endif
	return 0;
}

//-----------------------------------------------------------------------------
long CFrame::getKnobMode () const
{
#if PLUGGUI
	return PluginGUIEditor::getKnobMode ();
#else
	return AEffGUIEditor::getKnobMode ();
#endif
}

//-----------------------------------------------------------------------------
#if WINDOWS
COffscreenContext* CFrame::getBackBuffer ()
{
	#if WINDOWS && USE_ALPHA_BLEND
	if (!backBuffer)
		backBuffer = new COffscreenContext (this, size.width (), size.height ());
	#endif

	return backBuffer;
}

HWND CFrame::getOuterWindow () const
{
	int diffWidth, diffHeight;
	RECT  rctTempWnd, rctPluginWnd;
	HWND  hTempWnd = (HWND)pHwnd;
	GetWindowRect (hTempWnd, &rctPluginWnd);
    
	while (hTempWnd != NULL)
	{
		// Looking for caption bar
		if (GetWindowLong (hTempWnd, GWL_STYLE) & WS_CAPTION)
			return hTempWnd;

		// Looking for last parent
		if (!GetParent (hTempWnd))
			return hTempWnd;
    
		// get difference between plugin-window and current parent
		GetWindowRect (GetParent (hTempWnd), &rctTempWnd);
	    
		diffWidth  = (rctTempWnd.right - rctTempWnd.left) - (rctPluginWnd.right - rctPluginWnd.left);
		diffHeight = (rctTempWnd.bottom - rctTempWnd.top) - (rctPluginWnd.bottom - rctPluginWnd.top);
		
		// Looking for size mismatch
		if ((abs (diffWidth) > 60) || (abs (diffHeight) > 60)) // parent belongs to host
			return (hTempWnd);

		if (diffWidth < 0)
			diffWidth = 0;
        if (diffHeight < 0)
			diffHeight = 0; 
		
		// get the next parent window
		hTempWnd = GetParent (hTempWnd);
	}

	return NULL;
}
#endif

//-----------------------------------------------------------------------------
bool CFrame::setPosition (CCoord x, CCoord y)
{
	if (!getOpenFlag ())
		return false;
#if MAC
	#if QUARTZ
	if (controlRef)
	{
		HIRect r;
		if (HIViewGetFrame (controlRef, &r) != noErr)
			return false;
		if (HIViewMoveBy (controlRef, x - r.origin.x, y - r.origin.y) != noErr)
			return false;
		return true;
	}
	#else
	return false;
	#endif
#elif WINDOWS
	// not implemented yet

#else
	// not implemented yet

#endif
	return false;
}

//-----------------------------------------------------------------------------
bool CFrame::getPosition (CCoord &x, CCoord &y) const
{
	if (!getOpenFlag ())
		return false;
	
	// get the position of the Window including this frame in the main pWindow
#if WINDOWS
	HWND wnd = (HWND)getOuterWindow ();
	HWND wndParent = GetParent (wnd);

	RECT  rctTempWnd;
	GetWindowRect (wnd, &rctTempWnd);

	POINT point;
	point.x = rctTempWnd.left;
	point.y = rctTempWnd.top;

	MapWindowPoints (HWND_DESKTOP, wndParent, &point, 1);
	
	x = point.x;
	y = point.y;

#elif MAC
	Rect bounds;
	GetWindowBounds ((WindowRef)pSystemWindow, kWindowContentRgn, &bounds);
	
	x   = bounds.left;
	y   = bounds.top;

	#if QUARTZ
	WindowAttributes attr;
	GetWindowAttributes ((WindowRef)pSystemWindow, &attr);
	if (attr & kWindowCompositingAttribute)
	{
/*		HIPoint hip = { 0.f, 0.f };
		HIViewRef contentView;
		HIViewFindByID (HIViewGetRoot ((WindowRef)pSystemWindow), kHIViewWindowContentID, &contentView);
		if (HIViewGetSuperview ((HIViewRef)controlRef) != contentView)
			HIViewConvertPoint (&hip, controlRef, contentView);
		x += hip.x;
		y += hip.y;*/
	}
	else
	{
		HIRect hirect;
		HIViewGetFrame ((HIViewRef)controlRef, &hirect);
		x += (CCoord)hirect.origin.x;
		y += (CCoord)hirect.origin.y;
	}
	x -= hiScrollOffset.x;
	y -= hiScrollOffset.y;
	#endif

#elif MOTIF
	Position xWin, yWin;

	// get the topLevelShell of the pSystemWindow
	Widget parent = (Widget)getSystemWindow ();
	Widget parentOld = parent;
	while (parent != 0 && !XtIsTopLevelShell (parent))
	{
		parentOld = parent;
		parent = XtParent (parent);
	}

	if (parent == 0)
		parent = parentOld;

	if (parent)
	{
		XtVaGetValues (parent, XtNx, &xWin, XtNy, &yWin, NULL);
		x = xWin - 8;
		y = yWin - 30;
	}

#elif BEOS
	BRect frame = pPlugView->Window ()->Frame ();
	x = (long) frame.left;
	y = (long) frame.top;
#endif
	return true;
}

//-----------------------------------------------------------------------------
void CFrame::setViewSize (CRect& inRect)
{
	setSize (inRect.width (), inRect.height ());
}

//-----------------------------------------------------------------------------
bool CFrame::setSize (CCoord width, CCoord height)
{
	if (!getOpenFlag ())
		return false;
	
	if ((width == size.width ()) && (height == size.height ()))
	 return false;

#if WINDOWS
	if (backBuffer)
		backBuffer->forget ();
	backBuffer = 0;
#endif
#if !PLUGGUI
	if (pEditor)
	{
		AudioEffectX* effect = (AudioEffectX*)((AEffGUIEditor*)pEditor)->getEffect ();
		if (effect && effect->canHostDo ("sizeWindow"))
		{
			if (effect->sizeWindow ((long)width, (long)height))
			{
				size.right = size.left + width;
				size.bottom = size.top + height;

				#if WINDOWS
				SetWindowPos ((HWND)pHwnd, HWND_TOP, 0, 0, width, height, SWP_NOMOVE);
				
				#elif (MAC && QUARTZ)
				Rect bounds;
				CRect2Rect (size, bounds);
				SetControlBounds (controlRef, &bounds);
				#endif
				
				return true;
			}
		}
	}
#endif

	// keep old values
	CCoord oldWidth  = size.width ();
	CCoord oldHeight = size.height ();

	// set the new size
	size.right  = size.left + width;
	size.bottom = size.top  + height;

#if WINDOWS
	RECT  rctTempWnd, rctParentWnd;
	HWND  hTempWnd;
	long   iFrame = (2 * GetSystemMetrics (SM_CYFIXEDFRAME));
	
	long diffWidth  = 0;
	long diffHeight = 0;
	
	hTempWnd = (HWND)pHwnd;
	
	while ((diffWidth != iFrame) && (hTempWnd != NULL)) // look for FrameWindow
	{
		HWND hTempParentWnd = GetParent (hTempWnd);
		char buffer[1024];
		GetClassName (hTempParentWnd, buffer, 1024);
		if (!hTempParentWnd || !strcmp (buffer, "MDIClient"))
			break;
		GetWindowRect (hTempWnd, &rctTempWnd);
		GetWindowRect (hTempParentWnd, &rctParentWnd);
		
		SetWindowPos (hTempWnd, HWND_TOP, 0, 0, width + diffWidth, height + diffHeight, SWP_NOMOVE);
		
		diffWidth  += (rctParentWnd.right - rctParentWnd.left) - (rctTempWnd.right - rctTempWnd.left);
		diffHeight += (rctParentWnd.bottom - rctParentWnd.top) - (rctTempWnd.bottom - rctTempWnd.top);
		
		if ((diffWidth > 80) || (diffHeight > 80)) // parent belongs to host
			return true;

		if (diffWidth < 0)
			diffWidth = 0;
        if (diffHeight < 0)
			diffHeight = 0;
		
		hTempWnd = hTempParentWnd;
	}
	
	if (hTempWnd)
		SetWindowPos (hTempWnd, HWND_TOP, 0, 0, width + diffWidth, height + diffHeight, SWP_NOMOVE);

#elif MAC
	#if QUARTZ
	if (getSystemWindow ())
	{
		WindowAttributes windowAttributes;
		GetWindowAttributes ((WindowRef)getSystemWindow (), &windowAttributes);
		if (!(windowAttributes & kWindowCompositingAttribute))
		{
			Rect bounds;
			GetPortBounds (GetWindowPort ((WindowRef)getSystemWindow ()), &bounds);
			SizeWindow ((WindowRef)getSystemWindow (), (short)((bounds.right - bounds.left) - oldWidth + width),
									(short)((bounds.bottom - bounds.top) - oldHeight + height), true);
		}
	}
	if (controlRef)
	{
		HIRect frameRect;
		HIViewGetFrame (controlRef, &frameRect);
		frameRect.size.width = width;
		frameRect.size.height = height;
		HIViewSetFrame (controlRef, &frameRect);
	}

	#else
	if (getSystemWindow ())
	{
		Rect bounds;
		GetPortBounds (GetWindowPort ((WindowRef)getSystemWindow ()), &bounds);
		SizeWindow ((WindowRef)getSystemWindow (), (bounds.right - bounds.left) - oldWidth + width,
								(bounds.bottom - bounds.top) - oldHeight + height, true);
		#if MACX && !QUARTZ
		SetPort (GetWindowPort ((WindowRef)getSystemWindow ()));
		#endif
		#if QUARTZ
		CRect2Rect (size, bounds);
		SetControlBounds (controlRef, &bounds);
		#endif
	}
	#endif
	
#elif MOTIF
	Dimension heightWin, widthWin;

	// get the topLevelShell of the pSystemWindow
	Widget parent = (Widget)getSystemWindow ();
	Widget parentOld = parent;
	while (parent != 0 && !XtIsTopLevelShell (parent))
	{
		parentOld = parent;
		parent = XtParent (parent);
	}

	if (parent == 0)
		parent = parentOld;
	if (parent)
	{
		XtVaGetValues (parent, XtNwidth, &widthWin, XtNheight, &heightWin, NULL);	
		long diffWidth  = widthWin - oldWidth;
		long diffHeight = heightWin - oldHeight;
		XtVaSetValues (parent, XmNwidth, width + diffWidth, 
									 XmNheight, height + diffHeight, NULL);
	}

#elif BEOS
	BView* parent = pPlugView->Parent ();
	parent->SetResizingMode (B_FOLLOW_ALL_SIDES);
	BRect frame = pPlugView->Frame ();
	pPlugView->Window ()->ResizeBy (width - frame.Width () - 1, height - frame.Height () - 1);
	parent->SetResizingMode (B_FOLLOW_NONE);
#endif

	CRect myViewSize (0, 0, size.width (), size.height ());
	CViewContainer::setViewSize (myViewSize);

	return true;
}

//-----------------------------------------------------------------------------
bool CFrame::getSize (CRect *pRect) const
{
	if (!getOpenFlag ())
		return false;

#if WINDOWS
	// return the size relative to the client rect of this window
	// get the main window
	HWND wnd = GetParent ((HWND)getSystemWindow ());
	HWND wndParent = GetParent (wnd);
	HWND wndParentParent = GetParent (wndParent);

	RECT  rctTempWnd;
	GetWindowRect (wnd, &rctTempWnd);
	
	POINT point;
	point.x = rctTempWnd.left;
	point.y = rctTempWnd.top;

	MapWindowPoints (HWND_DESKTOP, wndParentParent, &point, 1);
	
	pRect->left   = point.x;
	pRect->top    = point.y;
	pRect->right  = pRect->left + rctTempWnd.right - rctTempWnd.left;
	pRect->bottom = pRect->top  + rctTempWnd.bottom - rctTempWnd.top;

#elif MAC
	#if QUARTZ
	HIRect hiRect;
	if (HIViewGetFrame (controlRef, &hiRect) == noErr)
	{
		pRect->left = (CCoord)hiRect.origin.x;
		pRect->top = (CCoord)hiRect.origin.y;
		pRect->setWidth ((CCoord)hiRect.size.width);
		pRect->setHeight ((CCoord)hiRect.size.height);
		return true;
	}
	#endif

	Rect bounds;
	GetPortBounds (GetWindowPort ((WindowRef)getSystemWindow ()), &bounds);

	pRect->left   = bounds.left;
	pRect->top    = bounds.top;
	pRect->right  = bounds.right;
	pRect->bottom = bounds.bottom;
	
#elif MOTIF
	Dimension height, width;
	XtVaGetValues ((Widget)getSystemWindow (),
								 XtNwidth, &width, XtNheight, &height, NULL);

	Position x, y;
	Position xTotal = 0, yTotal = 0;
	Widget parent = (Widget)getSystemWindow ();
	while (parent != 0 && !XtIsTopLevelShell (parent) && !XmIsDialogShell (parent))
	{
		XtVaGetValues (parent, XtNx, &x, XtNy, &y, NULL);	
		xTotal += x;
		yTotal += y;
		parent = XtParent (parent);
	}

	pRect->left   = xTotal;
	pRect->top    = yTotal;
	pRect->right  = width + pRect->left;
	pRect->bottom = height + pRect->top;

#elif BEOS
	BRect v = pPlugView->Frame ();
	(*pRect) (v.left, v.top, v.right + 1, v.bottom + 1);
#endif
	return true;
}

//-----------------------------------------------------------------------------
bool CFrame::getSize (CRect& outSize) const
{
	return getSize (&outSize);
}

//-----------------------------------------------------------------------------
long CFrame::setModalView (CView *pView)
{
	// There's already a modal view so we get out
	if (pView && pModalView)
			return 0;

	if (pModalView)
		removeView (pModalView, false);
	
	pModalView = pView;
	if (pModalView)
		addView (pModalView);

	return 1;
}

//-----------------------------------------------------------------------------
void CFrame::beginEdit (long index)
{
#if PLUGGUI
	#if AU
	if (pEditor)
		((PluginGUIEditor*)pEditor)->beginEdit (index);
	#endif
#else
	if (pEditor)
		((AEffGUIEditor*)pEditor)->beginEdit (index);
#endif
}

//-----------------------------------------------------------------------------
void CFrame::endEdit (long index)
{
#if PLUGGUI
	#if AU
	if (pEditor)
		((PluginGUIEditor*)pEditor)->endEdit (index);
	#endif
#else
	if (pEditor)
		((AEffGUIEditor*)pEditor)->endEdit (index);
#endif
}

//-----------------------------------------------------------------------------
CView *CFrame::getCurrentView () const
{
	if (pModalView)
		return pModalView;
	
	return CViewContainer::getCurrentView ();
}

//-----------------------------------------------------------------------------
bool CFrame::getCurrentLocation (CPoint &where)
{
#if WINDOWS
	HWND hwnd = (HWND)this->getSystemWindow ();
	POINT _where;
	GetCursorPos (&_where);
	where (_where.x, _where.y);
	if (hwnd)
	{
		RECT rctTempWnd;
		GetWindowRect (hwnd, &rctTempWnd);
		where.offset (-rctTempWnd.left, -rctTempWnd.top);
	}
	return true;
#endif

	// create a local context
	CDrawContext *pContext = createDrawContext ();
	if (pContext)
	{
	// get the current position
		pContext->getMouseLocation (where);
		pContext->forget ();
	}
	return true;
}

#if MACX
#define kThemeResizeUpDownCursor	21
#define kThemeNotAllowedCursor		18
#endif

//-----------------------------------------------------------------------------
void CFrame::setCursor (CCursorType type)
{
	#if WINDOWS
	if (!defaultCursor)
		defaultCursor = GetCursor ();
	switch (type)
	{
		case kCursorWait:
			SetCursor (LoadCursor (0, IDC_WAIT));
			break;
		case kCursorHSize:
			SetCursor (LoadCursor (0, IDC_SIZEWE));
			break;
		case kCursorVSize:
			SetCursor (LoadCursor (0, IDC_SIZENS));
			break;
		case kCursorNESWSize:
			SetCursor (LoadCursor (0, IDC_SIZENESW));
			break;
		case kCursorNWSESize:
			SetCursor (LoadCursor (0, IDC_SIZENWSE));
			break;
		case kCursorSizeAll:
			SetCursor (LoadCursor (0, IDC_SIZEALL));
			break;
		case kCursorNotAllowed:
			SetCursor (LoadCursor (0, IDC_NO));
			break;
		case kCursorHand:
			SetCursor (LoadCursor (0, IDC_HAND));
			break;
		default:
			SetCursor ((HCURSOR)defaultCursor);
			break;
	}
	#elif MAC
	#if MACX
	switch (type)
	{
		case kCursorWait:
			SetThemeCursor (kThemeWatchCursor);
			break;
		case kCursorHSize:
			SetThemeCursor (pSystemVersion < 0x1030 ? kThemeCrossCursor : kThemeResizeLeftRightCursor);
			break;
		case kCursorVSize:
			SetThemeCursor (pSystemVersion < 0x1030 ? kThemeCrossCursor : kThemeResizeUpDownCursor);
			break;
		case kCursorNESWSize:
			SetThemeCursor (kThemeCrossCursor);
			break;
		case kCursorNWSESize:
			SetThemeCursor (kThemeCrossCursor);
			break;
		case kCursorSizeAll:
			SetThemeCursor (kThemeCrossCursor);
			break;
		case kCursorCopy:
			SetThemeCursor (kThemeCopyArrowCursor);
			break;
		case kCursorNotAllowed:
			SetThemeCursor (pSystemVersion < 0x1020 ? kThemeArrowCursor : kThemeNotAllowedCursor);
			break;
		case kCursorHand:
			SetThemeCursor (kThemeOpenHandCursor);
			break;
		default:
			SetThemeCursor (kThemeArrowCursor);
			break;
	}
	#else
	//if (!defaultCursor)
	//	defaultCursor = GetCursor (0);
	switch (type)
	{
		case kCursorWait:
			SetCursor (*GetCursor (watchCursor));
			break;
		case kCursorHSize:
			SetCursor (*GetCursor (crossCursor));
			break;
		case kCursorVSize:
			SetCursor (*GetCursor (crossCursor));
			break;
		case kCursorNESWSize:
			SetCursor (*GetCursor (crossCursor));
			break;
		case kCursorNWSESize:
			SetCursor (*GetCursor (crossCursor));
			break;
		case kCursorSizeAll:
			SetCursor (*GetCursor (plusCursor));
			break;
		default:
			InitCursor ();
			break;
	}
	#endif
	#endif
}

//-----------------------------------------------------------------------------
void CFrame::setFocusView (CView *pView)
{
	CView *pOldFocusView = pFocusView;
	pFocusView = pView;
	if (pFocusView && pFocusView->wantsFocus ())
		pFocusView->setDirty ();

	if (pOldFocusView)
	{
		pOldFocusView->looseFocus ();
		if (pOldFocusView->wantsFocus ())
			pOldFocusView->setDirty ();
	}
}

//-----------------------------------------------------------------------------
bool CFrame::advanceNextFocusView (CView* oldFocus, bool reverse)
{
	if (pModalView)
		return false; // currently not supported, but should be done sometime
	if (oldFocus == 0)
	{
		if (pFocusView == 0)
			return CViewContainer::advanceNextFocusView (0, reverse);
		oldFocus = pFocusView;
	}
	if (isChild (oldFocus))
	{
		if (CViewContainer::advanceNextFocusView (oldFocus, reverse))
			return true;
		else
		{
			setFocusView (NULL);
			return false;
		}
	}
	CView* parentView = oldFocus->getParentView ();
	if (parentView && parentView->isTypeOf ("CViewContainer"))
	{
		CView* tempOldFocus = oldFocus;
		CViewContainer* vc = (CViewContainer*)parentView;
		while (vc)
		{
			if (vc->advanceNextFocusView (tempOldFocus, reverse))
				return true;
			else
			{
				tempOldFocus = vc;
				if (vc->getParentView () && vc->getParentView ()->isTypeOf ("CViewContainer"))
					vc = (CViewContainer*)vc->getParentView ();
				else
					vc = 0;
			}
		}
	}
	return CViewContainer::advanceNextFocusView (oldFocus, reverse);
}

//-----------------------------------------------------------------------------
void CFrame::invalidate (const CRect &rect)
{
	CRect rectView;
	FOREACHSUBVIEW
	if (pV)
	{
		pV->getViewSize (rectView);
		if (rect.rectOverlap (rectView))
			pV->setDirty (true);
	}
	ENDFOR
}

#if DEBUG
//-----------------------------------------------------------------------------
void CFrame::dumpHierarchy ()
{
	dumpInfo ();
	DebugPrint ("\n");
	CViewContainer::dumpHierarchy ();
}
#endif

//-----------------------------------------------------------------------------
// CCView Implementation
//-----------------------------------------------------------------------------
CCView::CCView (CView *pView)
 :  pView (pView), pNext (0), pPrevious (0)
{
	if (pView)
		pView->remember ();
}

//-----------------------------------------------------------------------------
CCView::~CCView ()
{ 
	if (pView)
		pView->forget (); 
}

//-----------------------------------------------------------------------------
// CViewContainer Implementation
//-----------------------------------------------------------------------------
/**
 * CViewContainer constructor.
 * @param rect the size of the container
 * @param pParent the parent CFrame
 * @param pBackground the background bitmap, can be NULL
 */
CViewContainer::CViewContainer (const CRect &rect, CFrame *pParent, CBitmap *pBackground)
: CView (rect), pFirstView (0), pLastView (0), 
 mode (kNormalUpdate), pOffscreenContext (0), bDrawInOffscreen (true), currentDragView (0)
{
	#if MACX || USE_ALPHA_BLEND
	bDrawInOffscreen = false;
	#endif
	backgroundOffset (0, 0);
	this->pParentFrame = pParent;
	setBackground (pBackground);
	backgroundColor = kBlackCColor;	
	#if NEW_UPDATE_MECHANISM
	mode = kOnlyDirtyUpdate;
	#endif
}

//-----------------------------------------------------------------------------
CViewContainer::~CViewContainer ()
{
	// remove all views
	removeAll (true);

	#if !BEOS
	 if (pOffscreenContext)
		pOffscreenContext->forget ();
	pOffscreenContext = 0;
	#endif
}

//-----------------------------------------------------------------------------
/**
 * @param rect the new size of the container
 */
void CViewContainer::setViewSize (CRect &rect)
{
	CView::setViewSize (rect);

	#if !BEOS
	if (pOffscreenContext && bDrawInOffscreen)
	{
		pOffscreenContext->forget ();
		pOffscreenContext = new COffscreenContext (pParentFrame, (long)size.width (), (long)size.height (), kBlackCColor);
	}
	#endif
}

//-----------------------------------------------------------------------------
/**
 * @param color the new background color of the container
 */
void CViewContainer::setBackgroundColor (CColor color)
{
	backgroundColor = color;
	setDirty (true);
}

//------------------------------------------------------------------------------
long CViewContainer::notify (CView* sender, const char* message)
{
	if (message == kMsgCheckIfViewContainer)
		return kMessageNotified;
	return kMessageUnknown;
}

//-----------------------------------------------------------------------------
/**
 * @param pView the view object to add to this container
 */
void CViewContainer::addView (CView *pView)
{
	if (!pView)
		return;

	CCView *pSv = new CCView (pView);
	
	pView->pParentFrame = pParentFrame;
	pView->pParentView = this;

	CCView *pV = pFirstView;
	if (!pV)
	{
		pLastView = pFirstView = pSv;
	}
	else
	{
		while (pV->pNext)
			pV = pV->pNext;
		pV->pNext = pSv;
		pSv->pPrevious = pV;
		pLastView = pSv;
	}
	pView->attached (this);
	pView->setDirty ();
}

//-----------------------------------------------------------------------------
/**
 * @param pView the view object to add to this container
 * @param mouseableArea the view area in where the view will get mouse events
 * @param mouseEnabled bool to set if view will get mouse events
 */
void CViewContainer::addView (CView *pView, CRect &mouseableArea, bool mouseEnabled)
{
	if (!pView)
		return;

	pView->setMouseEnabled (mouseEnabled);
	pView->setMouseableArea (mouseableArea);

	addView (pView);
}

//-----------------------------------------------------------------------------
/**
 * @param withForget bool to indicate if the view's reference counter should be decreased after removed from the container
 */
void CViewContainer::removeAll (const bool &withForget)
{
	CCView *pV = pFirstView;
	while (pV)
	{
		CCView *pNext = pV->pNext;
		if (pV->pView)
		{
			pV->pView->removed (this);
			if (withForget)
				pV->pView->forget ();
		}

		delete pV;

		pV = pNext;
	}
	pFirstView = 0;
	pLastView = 0;
}

//-----------------------------------------------------------------------------
/**
 * @param pView the view which should be removed from the container
 * @param withForget bool to indicate if the view's reference counter should be decreased after removed from the container
 */
void CViewContainer::removeView (CView *pView, const bool &withForget)
{
	if (pParentFrame && pParentFrame->getFocusView () == pView)
		pParentFrame->setFocusView (0);
	CCView *pV = pFirstView;
	while (pV)
	{
		if (pView == pV->pView)
		{
			CCView *pNext = pV->pNext;
			CCView *pPrevious = pV->pPrevious;
			if (pV->pView)
			{
				pV->pView->removed (this);
				if (withForget)
					pV->pView->forget ();
			}
			delete pV;
			if (pPrevious)
			{
				pPrevious->pNext = pNext;
				if (pNext)
					pNext->pPrevious = pPrevious;
				else
					pLastView = pPrevious;
			}
			else
			{
				pFirstView = pNext;
				if (pNext)
					pNext->pPrevious = 0;
				else
					pLastView = 0;	
			}
			break;
		}
		else
			pV = pV->pNext;
	}
}

//-----------------------------------------------------------------------------
/**
 * @param pView the view which should be checked if it is a child of this container
 */
bool CViewContainer::isChild (CView *pView) const
{
	bool found = false;

	CCView *pV = pFirstView;
	while (pV)
	{
		if (pView == pV->pView)
		{
			found = true;
			break;
		}
		pV = pV->pNext;
	}
	return found;
}

//-----------------------------------------------------------------------------
long CViewContainer::getNbViews () const
{
	long nb = 0;
	CCView *pV = pFirstView;
	while (pV)
	{
		pV = pV->pNext;
		nb++;
	}
	return nb;
}

//-----------------------------------------------------------------------------
/**
 * @param index the index of the view to return
 */
CView *CViewContainer::getView (long index) const
{
	long nb = 0;
	CCView *pV = pFirstView;
	while (pV)
	{
		if (nb == index)
			return pV->pView;
		pV = pV->pNext;
		nb++;
	}
	return 0;
}

//-----------------------------------------------------------------------------
/**
 * @param pContext the context which to use to draw this container and its subviews
 */
void CViewContainer::draw (CDrawContext *pContext)
{
	CDrawContext *pC;
	CCoord save[4];

	#if BEOS
	// create offscreen
	if (pBackground)
		pC = new COffscreenContext (pContext, pBackground);
	else
		pC = new COffscreenContext (pParentFrame, size.width (), size.height (), backgroundColor);
	
	#else
	if (!pOffscreenContext && bDrawInOffscreen)
		pOffscreenContext = new COffscreenContext (pParentFrame, (long)size.width (), (long)size.height (), kBlackCColor);
	#if USE_ALPHA_BLEND
	if (pOffscreenContext && bTransparencyEnabled)
		pOffscreenContext->copyTo (pContext, size);
	#endif

	if (bDrawInOffscreen)
		pC = pOffscreenContext;
	else
	{
		pC = pContext;
		modifyDrawContext (save, pContext);
	}

	CRect r (0, 0, size.width (), size.height ());

 	#if USE_CLIPPING_DRAWRECT
	CRect oldClip;
	pContext->getClipRect (oldClip);
	CRect oldClip2 (oldClip);
	if (bDrawInOffscreen && getFrame () != this)
		oldClip.offset (-oldClip.left, -oldClip.top);
		
	CRect newClip (r);
	newClip.bound (oldClip);
	pC->setClipRect (newClip);
	#endif

	// draw the background
	if (pBackground)
	{
		if (bTransparencyEnabled)
			pBackground->drawTransparent (pC, r, backgroundOffset);
		else
			pBackground->draw (pC, r, backgroundOffset);
	}
	else if (!bTransparencyEnabled)
	{
		pC->setFillColor (backgroundColor);
		pC->fillRect (r);
	}
	#endif
	
	// draw each view
	FOREACHSUBVIEW
		#if USE_CLIPPING_DRAWRECT
		CRect vSize (pV->size);
		vSize.bound (oldClip);
		pC->setClipRect (vSize);
		#endif
		pV->draw (pC);
	ENDFOR

	#if USE_CLIPPING_DRAWRECT
	pC->setClipRect (oldClip2);
	#endif
	
	// transfert offscreen
	if (bDrawInOffscreen)
		((COffscreenContext*)pC)->copyFrom (pContext, size);
	else
		restoreDrawContext (pContext, save);

	#if BEOS
	delete pC;
	#endif

	setDirty (false);
}

//-----------------------------------------------------------------------------
/**
 * @param pContext the context which to use to draw the background
 * @param _updateRect the area which to draw
 */
void CViewContainer::drawBackgroundRect (CDrawContext *pContext, CRect& _updateRect)
{
	if (pBackground)
	{
		CRect oldClip;
		pContext->getClipRect (oldClip);
		CRect newClip (_updateRect);
		newClip.bound (oldClip);
		pContext->setClipRect (newClip);
		CRect tr (0, 0, pBackground->getWidth (), pBackground->getHeight ());
		if (bTransparencyEnabled)
			pBackground->drawTransparent (pContext, tr, backgroundOffset);
		else
			pBackground->draw (pContext, tr, backgroundOffset);
		pContext->setClipRect (oldClip);
	}
	else if (!bTransparencyEnabled)
	{
		pContext->setFillColor (backgroundColor);
		pContext->fillRect (_updateRect);
	}
}

//-----------------------------------------------------------------------------
/**
 * @param pContext the context which to use to draw
 * @param _updateRect the area which to draw
 */
void CViewContainer::drawRect (CDrawContext *pContext, const CRect& _updateRect)
{
	CDrawContext *pC;
	CCoord save[4];

	#if BEOS
	// create offscreen
	if (pBackground)
		pC = new COffscreenContext (pContext, pBackground);
	else
		pC = new COffscreenContext (pParentFrame, size.width (), size.height (), backgroundColor);
	
	#else
	if (!pOffscreenContext && bDrawInOffscreen)
		pOffscreenContext = new COffscreenContext (pParentFrame, (long)size.width (), (long)size.height (), kBlackCColor);
	#if USE_ALPHA_BLEND
	if (pOffscreenContext && bTransparencyEnabled)
		pOffscreenContext->copyTo (pContext, size);
	#endif

	if (bDrawInOffscreen)
		pC = pOffscreenContext;
	else
	{
		pC = pContext;
		modifyDrawContext (save, pContext);
	}

	CRect updateRect (_updateRect);
	updateRect.bound (size);

	CRect clientRect (updateRect);
	clientRect.offset (-size.left, -size.top);

	#if USE_CLIPPING_DRAWRECT
	CRect oldClip;
	pContext->getClipRect (oldClip);
	CRect oldClip2 (oldClip);
	if (bDrawInOffscreen && getFrame () != this)
		oldClip.offset (-oldClip.left, -oldClip.top);
	
	CRect newClip (clientRect);
	newClip.bound (oldClip);
	pC->setClipRect (newClip);
	#endif
	
	// draw the background
	drawBackgroundRect (pC, clientRect);
	#endif
	
	// draw each view
	FOREACHSUBVIEW
		if (pV->checkUpdate (clientRect))
		{
			#if USE_CLIPPING_DRAWRECT
			CRect viewSize (pV->size);
			viewSize.bound (newClip);
			if (viewSize.getWidth () == 0 || viewSize.getHeight () == 0)
				continue;
			pC->setClipRect (viewSize);
			#endif

			bool wasDirty = pV->isDirty ();
			pV->drawRect (pC, clientRect);
			
			#if DEBUG_FOCUS_DRAWING
			if (getFrame ()->getFocusView() == pV && pV->wantsFocus ())
			{
				pC->setDrawMode (kCopyMode);
				pC->setFrameColor (kRedCColor);
				pC->drawRect (pV->size);
			}
			#endif
			if (wasDirty && pV->size != viewSize && !isTypeOf ("CScrollContainer"))
			{
				pV->setDirty (true);
			}
		}
	ENDFOR

	#if USE_CLIPPING_DRAWRECT
	pC->setClipRect (oldClip2);
	#endif

	// transfer offscreen
	if (bDrawInOffscreen)
		((COffscreenContext*)pC)->copyFrom (pContext, updateRect, CPoint (clientRect.left, clientRect.top));
	else
		restoreDrawContext (pContext, save);

	#if BEOS
	delete pC;
	#endif

#if EVENT_DRAW_FIX
	if (bDirty && newClip == size)
#endif
		setDirty (false);
}

//-----------------------------------------------------------------------------
/**
 * @param context the context which to use to redraw this container
 * @param rect the area which to redraw
 */
void CViewContainer::redrawRect (CDrawContext* context, const CRect& rect)
{
	CRect _rect (rect);
	_rect.offset (size.left, size.top);
	if (bTransparencyEnabled)
	{
		// as this is transparent, we call the parentview to redraw this area.
		if (pParentView)
			pParentView->redrawRect (context, _rect);
		else if (pParentFrame)
			pParentFrame->drawRect (context, _rect);
	}
	else
	{
		CCoord save[4];
		if (pParentView)
		{
			CPoint off;
			pParentView->localToFrame (off);
			// store
			save[0] = context->offsetScreen.h;
			save[1] = context->offsetScreen.v;
			save[2] = context->offset.h;
			save[3] = context->offset.v;

			context->offsetScreen.h += off.x;
			context->offsetScreen.v += off.y;
			context->offset.h += off.x;
			context->offset.v += off.y;
		}

		drawRect (context, _rect);

		if (pParentView)
		{
			// restore
			context->offsetScreen.h = save[0];
			context->offsetScreen.v = save[1];
			context->offset.h = save[2];
			context->offset.v = save[3];
		}
	}
}

//-----------------------------------------------------------------------------
bool CViewContainer::hitTestSubViews (const CPoint& where, const long buttons)
{
	CPoint where2 (where);
	where2.offset (-size.left, -size.top);

	CCView *pSv = pLastView;
	while (pSv)
	{
		CView *pV = pSv->pView;
		if (pV && pV->getMouseEnabled () && pV->hitTest (where2, buttons))
			return true;
		pSv = pSv->pPrevious;
	}
	return false;
}

//-----------------------------------------------------------------------------
bool CViewContainer::hitTest (const CPoint& where, const long buttons)
{
	//return hitTestSubViews (where); would change default behavior
	return CView::hitTest (where, buttons);
}

//-----------------------------------------------------------------------------
void CViewContainer::mouse (CDrawContext *pContext, CPoint &where, long buttons)
{
	// convert to relativ pos
	CPoint where2 (where);
	where2.offset (-size.left, -size.top);

	if (buttons == -1 && pContext)
		buttons = pContext->getMouseButtons ();

	CCView *pSv = pLastView;
	while (pSv)
	{
		CView *pV = pSv->pView;
		if (pV && pV->getMouseEnabled () && pV->hitTest (where2, buttons))
		{
			pV->mouse (pContext, where2, buttons);
			break;
		}
		pSv = pSv->pPrevious;
	}
}

//-----------------------------------------------------------------------------
long CViewContainer::onKeyDown (VstKeyCode& keyCode)
{
	long result = -1;

	CCView* pSv = pLastView;
	while (pSv)
	{
		long result = pSv->pView->onKeyDown (keyCode);
		if (result != -1)
			break;

		pSv = pSv->pPrevious;
	}

	return result;
}

//-----------------------------------------------------------------------------
long CViewContainer::onKeyUp (VstKeyCode& keyCode)
{
	long result = -1;

	CCView* pSv = pLastView;
	while (pSv)
	{
		long result = pSv->pView->onKeyUp (keyCode);
		if (result != -1)
			break;

		pSv = pSv->pPrevious;
	}

	return result;
}

//-----------------------------------------------------------------------------
bool CViewContainer::onWheel (CDrawContext *pContext, const CPoint &where, const CMouseWheelAxis axis, float distance)
{
	bool result = false;
	CView *view = getViewAt (where);
	if (view)
	{
		// convert to relativ pos
		CPoint where2 (where);
		where2.offset (-size.left, -size.top);

		CCoord save[4];
		modifyDrawContext (save, pContext);
	
		result = view->onWheel (pContext, where2, axis, distance);

		restoreDrawContext (pContext, save);
	}
	return result;
}

//-----------------------------------------------------------------------------
bool CViewContainer::onWheel (CDrawContext *pContext, const CPoint &where, float distance)
{
	return onWheel (pContext, where, kMouseWheelAxisY, distance);
}

//-----------------------------------------------------------------------------
bool CViewContainer::onDrop (CDrawContext* context, CDragContainer* drag, const CPoint& where)
{
	if (!pParentFrame)
		return false;

	bool result = false;

	CCoord save[4];
	modifyDrawContext (save, context);

	// convert to relativ pos
	CPoint where2 (where);
	where2.offset (-size.left, -size.top);

	CView* view = getViewAt (where);
	if (view != currentDragView)
	{
		if (currentDragView)
			currentDragView->onDragLeave (context, drag, where2);
		currentDragView = view;
	}
	if (currentDragView)
	{
		result = currentDragView->onDrop (context, drag, where2);
		currentDragView->onDragLeave (context, drag, where2);
	}
	currentDragView = 0;
	
	restoreDrawContext (context, save);

	return result;
}

//-----------------------------------------------------------------------------
void CViewContainer::onDragEnter (CDrawContext* context, CDragContainer* drag, const CPoint& where)
{
	if (!pParentFrame)
		return;
	
	CCoord save[4];
	modifyDrawContext (save, context);

	// convert to relativ pos
	CPoint where2 (where);
	where2.offset (-size.left, -size.top);

	if (currentDragView)
		currentDragView->onDragLeave (context, drag, where2);
	CView* view = getViewAt (where);
	currentDragView = view;
	if (view)
		view->onDragEnter (context, drag, where2);
	
	restoreDrawContext (context, save);
}

//-----------------------------------------------------------------------------
void CViewContainer::onDragLeave (CDrawContext* context, CDragContainer* drag, const CPoint& where)
{
	if (!pParentFrame)
		return;
	
	CCoord save[4];
	modifyDrawContext (save, context);

	// convert to relativ pos
	CPoint where2 (where);
	where2.offset (-size.left, -size.top);

	if (currentDragView)
		currentDragView->onDragLeave (context, drag, where2);
	currentDragView = 0;

	restoreDrawContext (context, save);
}

//-----------------------------------------------------------------------------
void CViewContainer::onDragMove (CDrawContext* context, CDragContainer* drag, const CPoint& where)
{
	if (!pParentFrame)
		return;
	
	CCoord save[4];
	modifyDrawContext (save, context);

	// convert to relativ pos
	CPoint where2 (where);
	where2.offset (-size.left, -size.top);

	CView* view = getViewAt (where);
	if (view != currentDragView)
	{
		if (currentDragView)
			currentDragView->onDragLeave (context, drag, where2);
		if (view)
			view->onDragEnter (context, drag, where2);
		currentDragView = view;
	}
	else if (currentDragView)
		currentDragView->onDragMove (context, drag, where2);
	
	restoreDrawContext (context, save);
}

//-----------------------------------------------------------------------------
void CViewContainer::update (CDrawContext *pContext)
{
	switch (mode)
	{
		//---Normal : redraw all...
		case kNormalUpdate:
			if (isDirty ())
			{
				#if NEW_UPDATE_MECHANISM
				CRect ur (0, 0, size.width (), size.height ());
				redrawRect (pContext, ur);
				#else
				#if USE_ALPHA_BLEND
				if (bTransparencyEnabled)
				{
					CRect updateRect (size);
					CPoint offset (0,0);
					localToFrame (offset);
					updateRect.offset (offset.x, offset.y);
					getFrame ()->drawRect (pContext, updateRect);
				}
				else
				#endif
				draw (pContext);
				#endif // !NEW_UPDATE_MECHANISM
				setDirty (false);
			}
		break;
	
		//---Redraw only dirty controls-----
		case kOnlyDirtyUpdate:
		{
			#if NEW_UPDATE_MECHANISM
			if (bDirty)
			{
				CRect ur (0, 0, size.width (), size.height ());
				redrawRect (pContext, ur);
			}
			else
			{
				CRect updateRect (size);
				updateRect.offset (-size.left, -size.top);
				FOREACHSUBVIEW
					if (pV->isDirty () && pV->checkUpdate (updateRect))
					{
						if (pV->notify (this, kMsgCheckIfViewContainer))
							pV->update (pContext);
						else
						{
							CRect drawSize (pV->size);
							drawSize.bound (updateRect);
							pV->redrawRect (pContext, drawSize);
						}
					}
				ENDFOR
			}
			#else
			#if USE_ALPHA_BLEND
			if (bTransparencyEnabled)
			{
				if (bDirty)
				{
					CRect updateRect (size);
					CPoint offset (0,0);
					localToFrame (offset);
					updateRect.offset (offset.x, offset.y);
					getFrame ()->drawRect (pContext, updateRect);
				}
				else
				{
					CRect updateRect (size);
					updateRect.offset (-size.left, -size.top);
					FOREACHSUBVIEW
						if (pV->isDirty () && pV->checkUpdate (updateRect))
						{
							if (pV->notify (this, kMsgCheckIfViewContainer))
							{
								pV->update (pContext);
							}
							else
							{
								CPoint offset;
								CRect viewSize (pV->size);
								pV->localToFrame (offset);
								viewSize.offset (offset.x, offset.y);
								getFrame ()->drawRect (pContext, viewSize);
							}
						}
					ENDFOR
				}
				setDirty (false);
				return;
			}
			#endif
			if (bDirty)
				draw (pContext);
			else if (bDrawInOffscreen && pOffscreenContext) 
			{
				bool doCopy = false;
				if (isDirty ())
					doCopy = true;

				FOREACHSUBVIEW
					pV->update (pOffscreenContext);
				ENDFOR

				// transfert offscreen
				if (doCopy)
					pOffscreenContext->copyFrom (pContext, size);
			}
			else
			{
				long save[4];
				modifyDrawContext (save, pContext);

				FOREACHSUBVIEW
					if (pV->isDirty ())
					{
						long oldMode = 0;
						CViewContainer* child = 0;
						if (pV->notify (this, kMsgCheckIfViewContainer))
						{
							child = (CViewContainer*)pV;
							oldMode = child->getMode ();
							child->setMode (kNormalUpdate);
						}
						CRect viewSize (pV->size);
						drawBackgroundRect (pContext, viewSize);
						pV->update (pContext);
						if (child)
							child->setMode (oldMode);
					}
				ENDFOR

				restoreDrawContext (pContext, save);
			}
			#endif // !NEW_UPDATE_MECHANISM
			setDirty (false);
		break;
		}
	}
}

//-----------------------------------------------------------------------------
void CViewContainer::looseFocus (CDrawContext *pContext)
{
	FOREACHSUBVIEW
		pV->looseFocus (pContext);
	ENDFOR
}

//-----------------------------------------------------------------------------
void CViewContainer::takeFocus (CDrawContext *pContext)
{
	FOREACHSUBVIEW
		pV->takeFocus (pContext);
	ENDFOR
}

//-----------------------------------------------------------------------------
bool CViewContainer::advanceNextFocusView (CView* oldFocus, bool reverse)
{
	bool foundOld = false;
	FOREACHSUBVIEW_REVERSE(reverse)
		if (oldFocus && !foundOld)
		{
			if (oldFocus == pV)
			{
				foundOld = true;
				continue;
			}
		}
		else
		{
			if (pV->wantsFocus ())
			{
				getFrame ()->setFocusView (pV);
				return true;
			}
			else if (pV->isTypeOf ("CViewContainer"))
			{
				if (((CViewContainer*)pV)->advanceNextFocusView (0, reverse))
					return true;
			}
		}
	ENDFOR
	return false;
}

//-----------------------------------------------------------------------------
bool CViewContainer::isDirty () const
{
	if (bDirty)
		return true;
		
	CRect viewSize (size);
	viewSize.offset (-size.left, -size.top);

	FOREACHSUBVIEW
		if (pV->isDirty ())
		{
			CRect r (pV->size);
			r.bound (viewSize);
			if (r.getWidth () > 0 && r.getHeight () > 0)
				return true;
		}
	ENDFOR
	return false;
}

//-----------------------------------------------------------------------------
CView *CViewContainer::getCurrentView () const
{
	if (!pParentFrame)
		return 0;

	// get the current position
	CPoint where;
	pParentFrame->getCurrentLocation (where);

	frameToLocal (where);
	
	CCView *pSv = pLastView;
	while (pSv)
	{
		CView *pV = pSv->pView;
		if (pV && where.isInside (pV->mouseableArea))
			return pV;
		pSv = pSv->pPrevious;
	}

	return 0;
}

//-----------------------------------------------------------------------------
CView *CViewContainer::getViewAt (const CPoint& p, bool deep) const
{
	if (!pParentFrame)
		return 0;

	CPoint where (p);

	// convert to relativ pos
	where.offset (-size.left, -size.top);

	CCView *pSv = pLastView;
	while (pSv)
	{
		CView *pV = pSv->pView;
		if (pV && where.isInside (pV->mouseableArea))
		{
			if (deep)
			{
				if (pV->isTypeOf ("CViewContainer"))
					return ((CViewContainer*)pV)->getViewAt (where, deep);
			}
			return pV;
		}
		pSv = pSv->pPrevious;
	}

	return 0;
}

//-----------------------------------------------------------------------------
CPoint& CViewContainer::frameToLocal (CPoint& point) const
{
	point.offset (-size.left, -size.top);
	if (pParentView && pParentView->isTypeOf ("CViewContainer"))
		return pParentView->frameToLocal (point);
	return point;
}

//-----------------------------------------------------------------------------
CPoint& CViewContainer::localToFrame (CPoint& point) const
{
	point.offset (size.left, size.top);
	if (pParentView && pParentView->isTypeOf ("CViewContainer"))
		return pParentView->localToFrame (point);
	return point;
}

//-----------------------------------------------------------------------------
bool CViewContainer::removed (CView* parent)
{
	#if !BEOS
	 if (pOffscreenContext)
		pOffscreenContext->forget ();
	pOffscreenContext = 0;
	#endif

	return true;
}

//-----------------------------------------------------------------------------
bool CViewContainer::attached (CView* view)
{
	#if !BEOS
	// create offscreen bitmap
	if (!pOffscreenContext && bDrawInOffscreen)
		pOffscreenContext = new COffscreenContext (pParentFrame, (long)size.width (), (long)size.height (), kBlackCColor);
	#endif

	return true;
}

//-----------------------------------------------------------------------------
void CViewContainer::useOffscreen (bool b)
{
	bDrawInOffscreen = b;
	
	#if !BEOS
	if (!bDrawInOffscreen && pOffscreenContext)
	{
		pOffscreenContext->forget ();
		pOffscreenContext = 0;
	}
	#endif
}

//-----------------------------------------------------------------------------
void CViewContainer::modifyDrawContext (CCoord save[4], CDrawContext* pContext)
{
	// store
	save[0] = pContext->offsetScreen.h;
	save[1] = pContext->offsetScreen.v;
	save[2] = pContext->offset.h;
	save[3] = pContext->offset.v;

	pContext->offsetScreen.h += size.left;
	pContext->offsetScreen.v += size.top;
	pContext->offset.h += size.left;
	pContext->offset.v += size.top;
}

//-----------------------------------------------------------------------------
void CViewContainer::restoreDrawContext (CDrawContext* pContext, CCoord save[4])
{
	// restore
	pContext->offsetScreen.h = save[0];
	pContext->offsetScreen.v = save[1];
	pContext->offset.h = save[2];
	pContext->offset.v = save[3];
}

#if DEBUG
static long _debugDumpLevel = 0;
//-----------------------------------------------------------------------------
void CViewContainer::dumpInfo ()
{
	static const char* modeString[] = { "Normal Update Mode", "Only Dirty Update Mode"};
	DebugPrint ("CViewContainer: Mode: %s, Offscreen:%s ", modeString[mode], bDrawInOffscreen ? "Yes" : "No");
	CView::dumpInfo ();
}

//-----------------------------------------------------------------------------
void CViewContainer::dumpHierarchy ()
{
	_debugDumpLevel++;
	FOREACHSUBVIEW
		for (long i = 0; i < _debugDumpLevel; i++)
			DebugPrint ("\t");
		pV->dumpInfo ();
		DebugPrint ("\n");
		if (pV->isTypeOf ("CViewContainer"))
			((CViewContainer*)pV)->dumpHierarchy ();
	ENDFOR
	_debugDumpLevel--;
}

#endif

#if WINDOWS && USE_LIBPNG
class PNGResourceStream
{
public:
		PNGResourceStream ()
		: streamPos (0)
		, resData (0)
		, resSize (0)
		{
		}

		~PNGResourceStream ()
		{
		}

		bool open (long resourceID)
		{
			HRSRC rsrc = FindResource (GetInstance (), MAKEINTRESOURCE (resourceID), "PNG");
			if (rsrc)
			{
				resSize = SizeofResource (GetInstance (), rsrc);
				HGLOBAL resDataLoad = LoadResource (GetInstance (), rsrc);
				if (resDataLoad)
				{
					resData = LockResource (resDataLoad);
					return true;
				}
			}
			return false;
		}

		void read (unsigned char* ptr, size_t size)
		{
			if (streamPos + size <= resSize)
			{
				memcpy (ptr, ((unsigned char*)resData+streamPos), size);
				streamPos += (unsigned long)size;
			}
		}

		static void readCallback (png_struct* pngPtr, unsigned char* ptr, size_t size)
		{
			void* obj = png_get_io_ptr (pngPtr);
			if (obj)
				((PNGResourceStream*)obj)->read (ptr, size);
		}
protected:
	HGLOBAL resData;
	unsigned long streamPos;
	unsigned long resSize;
};
#endif

//-----------------------------------------------------------------------------
// CBitmap Implementation
//-----------------------------------------------------------------------------
/*! @class CBitmap
@section cbitmap_alphablend Alpha Blend and Transparency
With Version 3.0 of VSTGUI it is possible to use alpha blended bitmaps. This comes free on Mac OS X and with Windows you need to include libpng.
Per default PNG images will be rendered alpha blended. If you want to use a transparency color with PNG Bitmaps, you need to call setNoAlpha(true) on the bitmap and set the transparency color.
@section cbitmap_macos Classic Apple Mac OS
The Bitmaps are PICTs and stored inside the resource fork.
@section cbitmap_macosx Apple Mac OS X
The Bitmaps can be of type PNG, JPEG, PICT, BMP and are stored in the Resources folder of the plugin bundle.
They must be named bmp00100.png (or bmp00100.jpg, etc). The number is the resource id.
@section cbitmap_windows Microsoft Windows
The Bitmaps are .bmp files and must be included in the plug (usually using a .rc file).
It's also possible to use png as of version 3.0 if you define the macro USE_LIBPNG and include the libpng and zlib libraries/sources to your project.
*/
CBitmap::CBitmap (long resourceID)
	: resourceID (resourceID), width (0), height (0), noAlpha (true)
{
	#if DEBUG
	gNbCBitmap++;
	#endif

#if WINDOWS || MAC
	pMask = 0;
	pHandle = 0;
	#if QUARTZ
	cgImage = 0;
	#endif

	loadFromResource (resourceID);

#elif MOTIF
	bool found = false;
	long  i = 0;
	long  ncolors, cpp;

	pHandle = 0;
	pMask  = 0;

	// find the good pixmap resource
	while (xpmResources[i].id != 0)
	{
		if (xpmResources[i].id == resourceID) 
		{
			if (xpmResources[i].xpm != NULL) 
			{
				found = true;
				ppDataXpm = xpmResources[i].xpm;
				
				xpmGetValues (ppDataXpm, &width, &height, &ncolors, &cpp);
				break;
			}
		}
		i++;
	}

	if (!found)
		ppDataXpm = 0;

#elif BEOS
	bbitmap = 0;
	transparencySet = false;
	if (resourceFile == 0)
	{
		// this is a hack to find the plug-in on the disk to access resources.
		const char* locate_me = "";
		int32	cookie = 0;
		image_info	iinfo;
		uint32	here = uint32 (locate_me);
		while (get_next_image_info (0, &cookie, &iinfo) == B_OK)
		{
			uint32	begin = uint32 (iinfo.text);
			if (begin <= here && here <= begin + iinfo.text_size)
				break;
		}
		BFile resource (iinfo.name, B_READ_ONLY);
		resourceFile = new BResources (&resource);
		resourceFile->PreloadResourceType ();
	}
	size_t	outSize;
	const char* res = (const char*) resourceFile->LoadResource ('RAWT', resourceID, &outSize);
	if (res)
	{
		BMemoryIO	memoryIO (res, outSize);
		bbitmap = BTranslationUtils::GetBitmap (&memoryIO);
		if (bbitmap)
		{
			BRect rect = bbitmap->Bounds ();
			width = (long) rect.Width () + 1;
			height = (long) rect.Height () + 1;
		}
	}
	if (!bbitmap)
		fprintf (stderr, "********* Resource %d could NOT be loaded!\n", (int)resourceID);
#endif

	setTransparentColor (kTransparentCColor);
	
	#if DEBUG
	gBitmapAllocation += (long)height * (long)width;
	#endif
}

//-----------------------------------------------------------------------------
CBitmap::CBitmap (CFrame &frame, CCoord width, CCoord height)
	: width (width), height (height), noAlpha (true)
{
	#if DEBUG
	gNbCBitmap++;
	#endif

#if WINDOWS
	HDC hScreen = GetDC (0);
	pHandle = CreateCompatibleBitmap (hScreen, width, height);
	ReleaseDC (0, hScreen);	
	pMask = 0;

#elif MAC
	pHandle = 0;
	pMask = 0;
	
	Rect r;
	r.left = r.top = 0;
	r.right = (short)width;
	r.bottom = (short)height;

    #if QUARTZ
	NewGWorld ((GWorldPtr*)&pHandle, 32, &r, 0, 0, 0);
	cgImage = 0;
    #else
	NewGWorld ((GWorldPtr*)&pHandle, 0, &r, 0, 0, 0);

	#endif

#elif MOTIF
	pXdisplay = frame.getDisplay ();
	Drawable pWindow = frame.getWindow ();

	pMask = 0;
	pHandle = (void*)XCreatePixmap (pXdisplay, (Drawable)pWindow, width, height, frame.getDepth ());

#elif BEOS
	bbitmap = 0;
	transparencySet = false;
#endif
	
	setTransparentColor (kTransparentCColor);
}

//-----------------------------------------------------------------------------
CBitmap::CBitmap ()
: resourceID (0)
, width (0)
, height (0)
, noAlpha (true)
{
	#if WINDOWS
	pHandle = 0;
	pMask = 0;
	
	#elif MAC
	pHandle = 0;
	pMask = 0;
	#if QUARTZ
	cgImage = 0;
	#endif
	
	#elif MOTIF
	pMask = 0;
	pHandle = 0;
	
	#elif BEOS
	bbitmap = 0;

	#endif
}

//-----------------------------------------------------------------------------
CBitmap::~CBitmap ()
{
	dispose ();
}

//-----------------------------------------------------------------------------
void CBitmap::dispose ()
{
	#if DEBUG
	gNbCBitmap--;
	gBitmapAllocation -= (long)height * (long)width;
	#endif

	#if WINDOWS
	if (pHandle)
		DeleteObject (pHandle);
	if (pMask)
		DeleteObject (pMask);

	pHandle = 0;
	pMask = 0;
	noAlpha = false;
		
	#elif MAC
	#if QUARTZ
	if (cgImage)
		CGImageRelease ((CGImageRef)cgImage);
	cgImage = 0;
	#endif
	if (pHandle)
		DisposeGWorld ((GWorldPtr)pHandle);
	if (pMask)
		DisposeGWorld ((GWorldPtr)pMask);

	pHandle = 0;
	pMask = 0;
	
	#elif MOTIF
	if (pHandle)
		XFreePixmap (pXdisplay, (Pixmap)pHandle);
	if (pMask) 
		XFreePixmap (pXdisplay, (Pixmap)pMask);

	pHandle = 0;
	pMask = 0;
	
	#elif BEOS
	if (bbitmap)
		delete bbitmap;
	
	bbitmap = 0;

	#endif

	width = 0;
	height = 0;

}

//-----------------------------------------------------------------------------
void *CBitmap::getHandle () const
 {
	#if WINDOWS||MOTIF
	return pHandle; 

	#elif MAC
	return pHandle;

	#elif BEOS
	return bbitmap;
	#endif
}

//-----------------------------------------------------------------------------
bool CBitmap::loadFromResource (long resourceID)
{
	bool result = false;

	dispose ();
	
	//---------------------------------------------------------------------------------------------
	#if WINDOWS
	//---------------------------------------------------------------------------------------------
	#if USE_LIBPNG
	PNGResourceStream resStream;
	if (resStream.open (resourceID))
	{
		// setup libpng
		png_structp png_ptr;
		png_infop info_ptr;
		png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
		if (png_ptr)
		{
			info_ptr = png_create_info_struct (png_ptr);
			if (info_ptr)
			{
				if (setjmp (png_jmpbuf (png_ptr)) == 0)
				{
					int bit_depth, color_type;
					png_set_read_fn (png_ptr, (void *)&resStream, PNGResourceStream::readCallback);
					png_read_info (png_ptr, info_ptr);
					png_get_IHDR (png_ptr, info_ptr, (png_uint_32*)&width, (png_uint_32*)&height, &bit_depth, &color_type, 0, 0, 0);
					long bytesPerRow = width * (32 / 8);
					while (bytesPerRow & 0x03)
						bytesPerRow++;
					// create BITMAP
					BITMAPINFO* bmInfo = new BITMAPINFO;
					BITMAPINFOHEADER* header = (BITMAPINFOHEADER*)bmInfo;
					memset (header, 0, sizeof(BITMAPINFOHEADER));
					header->biSize = sizeof(BITMAPINFOHEADER);
					header->biWidth = width;
					header->biHeight = height;
					header->biPlanes = 1;
					header->biBitCount = 32;
					header->biCompression = BI_RGB;
					header->biClrUsed = 0;
					void* bits;
					HDC dstDC = 0; //CreateCompatibleDC (0);
					pHandle = CreateDIBSection (dstDC, bmInfo, DIB_RGB_COLORS, &bits, NULL, 0);
					delete bmInfo;
					if (pHandle)
					{
						if (color_type == PNG_COLOR_TYPE_PALETTE)
							png_set_palette_to_rgb (png_ptr);
						if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
							png_set_gray_to_rgb (png_ptr);
						if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
							png_set_gray_1_2_4_to_8 (png_ptr);
						if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
							png_set_tRNS_to_alpha (png_ptr);
						else
							png_set_filler (png_ptr, 0xFF, PNG_FILLER_AFTER);
						if (bit_depth == 16)
						{
							png_set_swap (png_ptr);
							png_set_strip_16 (png_ptr);
						}
						if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA)
							png_set_bgr (png_ptr);
						png_read_update_info (png_ptr, info_ptr);

						unsigned char** rows = new unsigned char*[1];
						rows[0] = (unsigned char*)bits + (height-1) * bytesPerRow;
						for (long i = 0; i < height; i++)
						{
							png_read_rows (png_ptr, rows, NULL, 1);
							rows[0] -= bytesPerRow;
						}
						delete [] rows;
						png_read_end (png_ptr, 0);
						// premultiply alpha
						unsigned long* pixelPtr = (unsigned long*)bits;
						for (int y = 0; y <height; y++)
						{
							for (int x = 0; x < width; x++)
							{
								unsigned char* pixel = (unsigned char*)pixelPtr;
								if (pixel[3] != 0)
								{
									pixel[0] = ((pixel[0] * pixel[3]) >> 8);
									pixel[1] = ((pixel[1] * pixel[3]) >> 8);
									pixel[2] = ((pixel[2] * pixel[3]) >> 8);
								}
								else
									*pixelPtr = 0UL;
								pixelPtr++;
							}
						}
						if (dstDC)
							DeleteDC (dstDC);
#if 0
						HDC srcDC = CreateCompatibleDC (0);
						SelectObject (srcDC, pHandle);

						HDC dstDC = CreateCompatibleDC (0);
						this->pHandle = CreateCompatibleBitmap (dstDC, width, height);
						SelectObject (dstDC, this->pHandle);

						BLENDFUNCTION blendFunction;
						blendFunction.BlendOp = AC_SRC_OVER;
						blendFunction.BlendFlags = 0;
						blendFunction.SourceConstantAlpha = 255;
						#if USE_ALPHA_BLEND
						if (noAlpha)
							blendFunction.AlphaFormat = 0;//AC_SRC_NO_ALPHA;
						else
							blendFunction.AlphaFormat = AC_SRC_ALPHA;
						#else
						blendFunction.AlphaFormat = 0;//AC_SRC_NO_ALPHA;
						#endif
						#if DYNAMICALPHABLEND
						(*pfnAlphaBlend) (dstDC, 
									0, 0,
									width, height, 
									srcDC,
									0, 0,
									width, height,
									blendFunction);
						#else
						#endif

						DeleteDC (srcDC);
						DeleteDC (dstDC);
						DeleteObject (pHandle);
#endif
					}
				}
			}
			png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
		}
		noAlpha = false;
		return true;
	}
	#endif
	pHandle = LoadBitmap (GetInstance (), MAKEINTRESOURCE (resourceID));
	BITMAP bm;
	if (pHandle && GetObject (pHandle, sizeof (bm), &bm))
	{
		width  = bm.bmWidth; 
		height = bm.bmHeight;
		noAlpha = true;
		return true;
	}
	
	//---------------------------------------------------------------------------------------------
	#elif MAC
	//---------------------------------------------------------------------------------------------
	pHandle = 0;
	pMask = 0;
	#if QUARTZ
	cgImage = 0;
	#endif
	#if MACX
	if (gBundleRef)
	{
		// find the bitmap in our Bundle. It must be in the form of bmp00123.png, where the resource id would be 123.
		char filename [PATH_MAX];
		sprintf (filename, "bmp%05d", (int)resourceID);
		CFStringRef cfStr = CFStringCreateWithCString (NULL, filename, kCFStringEncodingASCII);
		if (cfStr)
		{
			CFURLRef url = NULL;
			int i = 0;
			while (url == NULL)
			{
				static CFStringRef resTypes [] = { CFSTR("png"), CFSTR("bmp"), CFSTR("jpg"), CFSTR("pict"), NULL };
				url = CFBundleCopyResourceURL ((CFBundleRef)gBundleRef, cfStr, resTypes[i], NULL);
				if (resTypes[++i] == NULL)
					break;
			}
			CFRelease (cfStr);
			if (url)
			{
				result = loadFromPath (url);
				CFRelease (url);
			}
			else
			{
				#if DEVELOPMENT
				fprintf (stderr, "Bitmap Nr.:%d not found.\n", resourceID);
				#endif
			}
		}
	}
	#endif
	
	if (!result && pHandle == 0)
	{
		Handle picHandle = GetResource ('PICT', resourceID);
		if (picHandle)
		{
			HLock (picHandle);
			
			PictInfo info;
			GetPictInfo ((PicHandle)picHandle, &info, recordComments, 0, systemMethod, 0);
			width  = info.sourceRect.right;
			height = info.sourceRect.bottom;
			
			OSErr err = NewGWorld ((GWorldPtr*)&pHandle, 32, &info.sourceRect, 0, 0, 0);
			if (!err)
			{
				GWorldPtr oldPort;
				GDHandle oldDevice;
				GetGWorld (&oldPort, &oldDevice);
				SetGWorld ((GWorldPtr)pHandle, 0);
				
				DrawPicture ((PicHandle)picHandle, &info.sourceRect);
				
				SetGWorld (oldPort, oldDevice);
				result = true;
			}

			HUnlock (picHandle);
			ReleaseResource (picHandle);
		}
	}

	#else
	// other platforms go here
	#endif
	return result;
}

//-----------------------------------------------------------------------------
bool CBitmap::loadFromPath (const void* platformPath)
{
	bool result = false;

	dispose ();

	#if QUARTZ
	CFURLRef url = (CFURLRef)platformPath;

	FSRef fsRef;
	if (CFURLGetFSRef (url, &fsRef))
	{
		FSSpec fsSpec;
		FSCatalogInfoBitmap infoBitmap = kFSCatInfoNone;
		if (FSGetCatalogInfo (&fsRef, infoBitmap, NULL, NULL, &fsSpec, NULL) == noErr)
		{
			ComponentInstance* gi = 0;
			CFStringRef ext = CFURLCopyPathExtension (url);
			if (ext == 0)
				return false;
			if (CFStringCompare (ext, CFSTR("bmp"), 0) == kCFCompareEqualTo)
				gi = &bmpGI;
			else if (CFStringCompare (ext, CFSTR("png"), 0) == kCFCompareEqualTo)
			{
				gi = &pngGI;
				noAlpha = false;
			}
			else if (CFStringCompare (ext, CFSTR("jpg"), 0) == kCFCompareEqualTo)
				gi = &jpgGI;
			else if (CFStringCompare (ext, CFSTR("pict"), 0) == kCFCompareEqualTo)
				gi = &pictGI;
			CFRelease (ext);

			if (*gi == 0)
				GetGraphicsImporterForFile (&fsSpec, gi);
			else
				if (GraphicsImportSetDataFile (*gi, &fsSpec) != noErr)
					return false;
			if (*gi)
			{
				#ifdef MAC_OS_X_VERSION_10_3
				if (!noAlpha && GraphicsImportCreateCGImage)
				{
					if (GraphicsImportCreateCGImage (*gi, (CGImageRef*)&cgImage, 0) == noErr)
					{
						width = CGImageGetWidth ((CGImageRef)cgImage);
						height = CGImageGetHeight ((CGImageRef)cgImage);
						result = true;
					}
				}
				else
				#endif
				{
					Rect r;
					GraphicsImportGetSourceRect (*gi, &r);
					OSErr err = NewGWorld ((GWorldPtr*)&pHandle, 32, &r, 0, 0, 0);
					if (!err)
					{
						width = r.right;
						height = r.bottom;
						GraphicsImportSetGWorld (*gi, (GWorldPtr)pHandle, 0);
						GraphicsImportDraw (*gi);
						result = true;
					}
				}
			}
		}
	}
	#elif WINDOWS
	// todo
	
	#endif
	
	return result;
}

//-----------------------------------------------------------------------------
bool CBitmap::isLoaded () const
{
	#if MOTIF
	if (ppDataXpm)
		return true;
	
	#elif QUARTZ
	if (cgImage || getHandle ())
		return true;
	#else
	if (getHandle ())
		return true;
	#endif

	return false;
}

#if QUARTZ
class CDataProvider 
{
public:
	CDataProvider (CBitmap* bitmap) : bmp (bitmap) 
	{ 
		pos = 0; 
		PixMapHandle pixMap = GetGWorldPixMap ((GWorldPtr)bmp->getHandle ());
		ptr = (unsigned char*)GetPixBaseAddr (pixMap);
		color = bmp->getTransparentColor ();
	}

	static size_t getBytes (void *info, void *buffer, size_t count)
	{	// this could be optimized ;-)
		CDataProvider* p = (CDataProvider*)info;
		unsigned char* dst = (unsigned char*)buffer;
		unsigned char* src = p->ptr + p->pos;
		for (unsigned long i = 0; i < count / 4; i++)
		{
			if (src[1] == p->color.red && src[2] == p->color.green && src[3] == p->color.blue)
			{
				*dst++ = 0;
				src++;
			}
			else
				*dst++ = *src++;
			*dst++ = *src++;
			*dst++ = *src++;
			*dst++ = *src++;
		}
		p->pos += count;
		return count;
	}

	static void skipBytes (void *info, size_t count)
	{
		CDataProvider* p = (CDataProvider*)info;
		p->pos += count;
	}

	static void rewind (void *info)
	{
		CDataProvider* p = (CDataProvider*)info;
		p->pos = 0;
	}

	static void releaseProvider (void *info)
	{
		CDataProvider* p = (CDataProvider*)info;
		delete p;
	}

	unsigned long pos;
	CBitmap* bmp;
	unsigned char* ptr;
	CColor color;
};

//-----------------------------------------------------------------------------
CGImageRef CBitmap::createCGImage (bool transparent)
{
	if (cgImage)
	{
		CGImageRetain ((CGImageRef)cgImage);
		return (CGImageRef)cgImage;
	}
	if (!pHandle)
		return NULL;

	PixMapHandle pixMap = GetGWorldPixMap ((GWorldPtr)pHandle);
	
	Rect bounds;
	GetPixBounds (pixMap, &bounds);

	size_t pixRowBytes = GetPixRowBytes (pixMap);
	short pixDepth = GetPixDepth (pixMap);
	size_t size = pixRowBytes * (bounds.bottom - bounds.top);

	CGImageRef image = 0;
	CGDataProviderRef provider = 0;
	static CGDataProviderCallbacks callbacks = { CDataProvider::getBytes, CDataProvider::skipBytes, CDataProvider::rewind, CDataProvider::releaseProvider };
	if (transparent)
		provider = CGDataProviderCreate (new CDataProvider (this), &callbacks);
	else
		provider = CGDataProviderCreateWithData (NULL, GetPixBaseAddr (pixMap), size, NULL);
	CGImageAlphaInfo alphaInfo = kCGImageAlphaFirst;
	if (GetPixDepth (pixMap) != 32)
		alphaInfo = kCGImageAlphaNone;
	image = CGImageCreate (bounds.right - bounds.left, bounds.bottom - bounds.top, 8 , pixDepth, pixRowBytes, GetGenericRGBColorSpace (), alphaInfo, provider, NULL, false, kCGRenderingIntentDefault);
	CGDataProviderRelease (provider);

	cgImage = image;
	CGImageRetain (image);
	return image;
}
#endif

//-----------------------------------------------------------------------------
void CBitmap::draw (CDrawContext *pContext, CRect &rect, const CPoint &offset)
{
#if WINDOWS
	#if USE_ALPHA_BLEND
	if (!noAlpha)
	{
		drawAlphaBlend (pContext, rect, offset, 255);
		return;
	}
	#endif	

	if (pHandle)
	{
		HGDIOBJ hOldObj;
		HDC hdcMemory = CreateCompatibleDC ((HDC)pContext->pSystemContext);
		hOldObj = SelectObject (hdcMemory, pHandle);
		BitBlt ((HDC)pContext->pSystemContext, 
						rect.left + pContext->offset.h, rect.top + pContext->offset.v, rect.width (), rect.height (), 
						(HDC)hdcMemory, offset.h, offset.v, SRCCOPY);
		SelectObject (hdcMemory, hOldObj);
		DeleteDC (hdcMemory);
	}

#elif MAC

	#if QUARTZ
	drawAlphaBlend (pContext, rect, offset, 255);

	#else
	Rect source, dest;
	dest.top    = rect.top  + pContext->offset.v;
	dest.left   = rect.left + pContext->offset.h;
	dest.bottom = dest.top  + rect.height ();
	dest.right  = dest.left + rect.width ();
		
	source.top    = offset.v;
	source.left   = offset.h;
	source.bottom = source.top  + rect.height ();
	source.right  = source.left + rect.width ();

	pContext->getPort ();
	BitMapPtr bitmapPtr = pContext->getBitmap ();
	
	if (pHandle && bitmapPtr)
	{
		PixMapHandle pmHandle = GetGWorldPixMap ((GWorldPtr)pHandle);
		if (pmHandle && LockPixels (pmHandle))
		{
			RGBColor oldForeColor, oldBackColor;
			GetForeColor (&oldForeColor);
			GetBackColor (&oldBackColor);
			::BackColor (whiteColor);
			::ForeColor (blackColor);
			
			CopyBits ((BitMapPtr)*pmHandle, bitmapPtr, &source, &dest, srcCopy, 0L);
			#if MACX
			QDAddRectToDirtyRegion (pContext->getPort (), &dest);
			#endif
			
			RGBForeColor (&oldForeColor);
			RGBBackColor (&oldBackColor);
			
			UnlockPixels (pmHandle);
		}
	}
	
	pContext->releaseBitmap ();
	#endif

#elif MOTIF
	if (!pHandle)
	{
		// the first time try to decode the pixmap
		pHandle = createPixmapFromXpm (pContext);
		if (!pHandle)
			return;
		
		// keep a trace of the display for deletion
		pXdisplay = pContext->pDisplay;
	}
	
#if DEVELOPMENT
	if (!(offset.h >= 0 && offset.v >= 0 &&
				rect.width () <= (getWidth () - offset.h) &&
				rect.height () <= (getHeight () - offset.v)))
	{
		fprintf (stderr, "%s(%d) -> Assert failed: try to display outside from the bitmap\n", __FILE__, __LINE__);
		return;
	}
#endif

	XCopyArea (pContext->pDisplay, (Drawable)pHandle, 
						 (Drawable)pContext->pWindow, 
						 (GC)pContext->pSystemContext, offset.h, offset.v,
						 rect.width (), rect.height (), rect.left, rect.top);

#elif BEOS
	BRect	brect (rect.left, rect.top, rect.right - 1, rect.bottom - 1);
	BRect	drect = brect;
	brect.OffsetTo (offset.h, offset.v);
	drect.OffsetBy (pContext->offset.h, pContext->offset.v);
	pContext->pView->SetDrawingMode (B_OP_COPY);
	pContext->pView->DrawBitmap (bbitmap, brect, drect);
#endif
}

//-----------------------------------------------------------------------------
void CBitmap::drawTransparent (CDrawContext *pContext, CRect &rect, const CPoint &offset)
{
#if WINDOWS
	#if USE_ALPHA_BLEND
	if (!noAlpha)
	{
		drawAlphaBlend (pContext, rect, offset, 255);
		return;
	}
	#endif	

	BITMAP bm;
	HDC hdcBitmap;
	POINT ptSize;

	hdcBitmap = CreateCompatibleDC ((HDC)pContext->pSystemContext);
	SelectObject (hdcBitmap, pHandle);	 // Select the bitmap

	GetObject (pHandle, sizeof (BITMAP), (LPSTR)&bm);
	ptSize.x = bm.bmWidth;            // Get width of bitmap
	ptSize.y = bm.bmHeight;           // Get height of bitmap
	DPtoLP (hdcBitmap, &ptSize, 1);   // Convert from device to logical points

	DrawTransparent (pContext, rect, offset, hdcBitmap, ptSize, (HBITMAP)pMask, RGB(transparentCColor.red, transparentCColor.green, transparentCColor.blue));

	DeleteDC (hdcBitmap);

#elif MAC

	#if QUARTZ
	if (noAlpha)
	{
		CGImageRef image = createCGImage (true);
		if (image)
		{
			drawAlphaBlend (pContext, rect, offset, 255);
			CGImageRelease (image);
		}
	}
	else
		drawAlphaBlend (pContext, rect, offset, 255);

	#else
	Rect source, dest;
	dest.top    = rect.top  + pContext->offset.v;
	dest.left   = rect.left + pContext->offset.h;
	dest.bottom = dest.top  + rect.height ();
	dest.right  = dest.left + rect.width ();
	
	source.top    = offset.v;
	source.left   = offset.h;
	source.bottom = source.top  + rect.height ();
	source.right  = source.left + rect.width ();

	pContext->getPort ();
	BitMapPtr bitmapPtr = pContext->getBitmap ();

	if (pHandle && bitmapPtr)
	{
		PixMapHandle pmHandle = GetGWorldPixMap ((GWorldPtr)pHandle);
		if (pmHandle && LockPixels (pmHandle))
		{
			RGBColor oldForeColor, oldBackColor;
			GetForeColor (&oldForeColor);
			GetBackColor (&oldBackColor);
			
			RGBColor col;
			CColor2RGBColor (transparentCColor, col);
			RGBBackColor (&col);
			::ForeColor (blackColor);
			
			if (pMask)
			{
				PixMapHandle pmHandleMask = GetGWorldPixMap ((GWorldPtr)pMask);
				if (pmHandleMask && LockPixels (pmHandleMask))
				{
					CopyMask ((BitMapPtr)*pmHandle, (BitMapPtr)*pmHandleMask, bitmapPtr, 
								&source, &source, &dest);
										
					UnlockPixels (pmHandleMask);
				}
			}
			else
				CopyBits ((BitMapPtr)*pmHandle, bitmapPtr, &source, &dest, transparent, 0L);
			
			RGBForeColor (&oldForeColor);
			RGBBackColor (&oldBackColor);

			#if MACX
			QDAddRectToDirtyRegion (pContext->getPort (), &dest);
			#endif
			
			UnlockPixels (pmHandle);
		}
	}

	pContext->releaseBitmap ();
	#endif
        
#elif MOTIF
	if (!pHandle) 
	{
		// the first time try to decode the pixmap
		pHandle = createPixmapFromXpm (pContext);
		if (!pHandle)
			return;
		
		// keep a trace of the display for deletion
		pXdisplay = pContext->pDisplay;
	}
	
	if (pMask == 0)
	{
		// get image from the pixmap
		XImage* image = XGetImage (pContext->pDisplay, (Drawable)pHandle, 
                0, 0, width, height, AllPlanes, ZPixmap);
		assert (image);
		
		// create the bitmap mask
		pMask = (void*)XCreatePixmap (pContext->pDisplay, (Drawable)pContext->pWindow, 
                width, height, 1);
		assert (pMask);
		
		// create a associated GC
		XGCValues values;
		values.foreground = 1;
		GC gc = XCreateGC (pContext->pDisplay, (Drawable)pMask, GCForeground, &values); 
		
		// clear the mask
		XFillRectangle (pContext->pDisplay, (Drawable)pMask, gc, 0, 0, width, height);
   
		// get the transparent color index
		int color = pContext->getIndexColor (transparentCColor);
		
		// inverse the color
		values.foreground = 0;
		XChangeGC (pContext->pDisplay, gc, GCForeground, &values);
     
		// compute the mask
		XPoint *points = new XPoint [height * width];
		int x, y, nbPoints = 0;
		switch (image->depth) 
		{
		case 8:
			for (y = 0; y < height; y++) 
			{
				char* src = image->data + (y * image->bytes_per_line);
				
				for (x = 0; x < width; x++) 
				{
					if (src[x] == color) 
					{
						points[nbPoints].x = x;
						points[nbPoints].y = y;
						nbPoints++;
					}
				}
			}
			break;

		case 24: {
			int bytesPerPixel = image->bits_per_pixel >> 3;
			char *lp = image->data;
			for (y = 0; y < height; y++)
			{
				char* cp = lp;
				for (x = 0; x < width; x++)
				{
					if (*(int*)cp == color)
					{
						points[nbPoints].x = x;
						points[nbPoints].y = y;
						nbPoints++;
					}
					cp += bytesPerPixel;
				}
				lp += image->bytes_per_line;
			}
		} break;

		default :
			break;
		}

		XDrawPoints (pContext->pDisplay, (Drawable)pMask, gc,
								 points, nbPoints, CoordModeOrigin);
     
		// free 
		XFreeGC (pContext->pDisplay, gc);
		delete []points;

		// delete 
		XDestroyImage (image);
	}
	
	// set the new clipmask
	XGCValues value;
	value.clip_mask = (Pixmap)pMask;
	value.clip_x_origin = rect.left - offset.h;
	value.clip_y_origin = rect.top - offset.v;
	XChangeGC (pContext->pDisplay, (GC)pContext->pSystemContext,
						 GCClipMask|GCClipXOrigin|GCClipYOrigin, &value);

	XCopyArea (pContext->pDisplay, (Drawable)pHandle, (Drawable)pContext->pWindow, 
						 (GC)pContext->pSystemContext, offset.h, offset.v,
						 rect.width (), rect.height (), rect.left, rect.top);
	
	// unset the clipmask
	XSetClipMask (pContext->pDisplay, (GC)pContext->pSystemContext, None);
	

#elif BEOS
	if (!transparencySet)
	{
		uint32 c32 = transparentCColor.red | (transparentCColor.green  << 8) | (transparentCColor.blue << 16);
		uint32 *pix = (uint32*) bbitmap->Bits ();
		uint32 ctr = B_TRANSPARENT_32_BIT.red | (B_TRANSPARENT_32_BIT.green << 8) | (B_TRANSPARENT_32_BIT.blue << 16) | (B_TRANSPARENT_32_BIT.alpha << 24);
		
		for (int32 z = 0, count = bbitmap->BitsLength () / 4; z < count; z++)
		{
			if ((pix[z] & 0xffffff) == c32) 
				pix[z] = ctr;
		}
		transparencySet = true;
	}
	BRect	brect (rect.left, rect.top, rect.right - 1, rect.bottom - 1);
	BRect	drect = brect;
	brect.OffsetTo (offset.h, offset.v);
	drect.OffsetBy (pContext->offset.h, pContext->offset.v);
	pContext->pView->SetDrawingMode (B_OP_OVER);
	pContext->pView->DrawBitmap (bbitmap, brect, drect);

#endif
}

//-----------------------------------------------------------------------------
void CBitmap::drawAlphaBlend (CDrawContext *pContext, CRect &rect, const CPoint &offset, unsigned char alpha)
{
#if WINDOWS
	if (pHandle)
	{
		HGDIOBJ hOldObj;
		HDC hdcMemory = CreateCompatibleDC ((HDC)pContext->pSystemContext);
		hOldObj = SelectObject (hdcMemory, pHandle);

		BLENDFUNCTION blendFunction;
		blendFunction.BlendOp = AC_SRC_OVER;
		blendFunction.BlendFlags = 0;
		blendFunction.SourceConstantAlpha = alpha;
		#if USE_ALPHA_BLEND
		if (noAlpha)
			blendFunction.AlphaFormat = 0;//AC_SRC_NO_ALPHA;
		else
			blendFunction.AlphaFormat = AC_SRC_ALPHA;
		#else
		blendFunction.AlphaFormat = 0;//AC_SRC_NO_ALPHA;
		#endif
		#if DYNAMICALPHABLEND
		// check for Win98 as it has a bug in AlphaBlend
		if (gSystemVersion.dwMajorVersion == 4 && gSystemVersion.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && gSystemVersion.dwMinorVersion == 10)
		{
			HGDIOBJ hOldObj1;
			HDC hdcMemory1 = CreateCompatibleDC ((HDC)pContext->pSystemContext);
			HBITMAP hbmp = CreateCompatibleBitmap(hdcMemory, rect.width(), rect.height());
			//this does NOT work:
			//HBITMAP hbmp = CreateCompatibleBitmap(hdcMemory1, rect.width(), rect.height());
			hOldObj1 = SelectObject (hdcMemory1, hbmp);

			//copy contents of original picture in hdcMemory 
			//from the offset to hdcMemory1 (0,0)
			long res = BitBlt((HDC)hdcMemory1, 
					0, 0, 
					rect.width(), rect.height(), 
					(HDC)hdcMemory, offset.h, offset.v, SRCCOPY);

			//Copy the resulting image with alpha blending:
			(*pfnAlphaBlend) ((HDC)pContext->pSystemContext, 
						rect.left + pContext->offset.h, rect.top + pContext->offset.v,
						rect.width (), rect.height (), 
						hdcMemory1,
						0, 0,//the offset is done in BitBlt
						rect.width (), rect.height (),
						blendFunction);
			SelectObject (hdcMemory1, hOldObj1);
			DeleteDC(hdcMemory1);
			DeleteObject(hbmp);
		}
		else
		{
			(*pfnAlphaBlend) ((HDC)pContext->pSystemContext, 
						rect.left + pContext->offset.h, rect.top + pContext->offset.v,
						rect.width (), rect.height (), 
						(HDC)hdcMemory,
						offset.h, offset.v,
						rect.width (), rect.height (),
						blendFunction);
		}
		#else
		AlphaBlend ((HDC)pContext->pSystemContext, 
					rect.left + pContext->offset.h, rect.top + pContext->offset.v,
					rect.width (), rect.height (), 
					(HDC)hdcMemory,
					offset.h, offset.v,
					rect.width (), rect.height (),
					blendFunction);
		#endif
		SelectObject (hdcMemory, hOldObj);
		DeleteDC (hdcMemory);
	}

#elif MAC

    #if QUARTZ
    if (_CGImageCreateWithImageInRect)	// this is much faster on Mac OS X 10.4 and above
    {
        if (pHandle || cgImage)
        {
            CGContextRef context = pContext->beginCGContext ();
            if (context)
            {
                if (alpha != 255)
                    CGContextSetAlpha (context, (float)alpha / 255.f);
        
                CGImageRef image = createCGImage ();

                if (image)
                {
                    CRect ccr;
                    pContext->getClipRect (ccr);
                     CGRect clipRect = CGRectMake (ccr.left - rect.left + offset.h, ccr.top - rect.top + offset.v, ccr.width (), ccr.height ());
                    CGRect subRect = CGRectMake (offset.h, offset.v, rect.getWidth (), rect.getHeight ());
                    subRect = CGRectIntersection (clipRect, subRect);
                    if (subRect.size.width && subRect.size.height)
                    {
                        CGImageRef subImage = _CGImageCreateWithImageInRect (image, subRect);
                        if (subImage)
                        {
                            CGRect dest;
                            dest.origin.x = subRect.origin.x + pContext->offset.h - offset.h + rect.left;
                            dest.origin.y = subRect.origin.y + pContext->offset.v - offset.v + rect.top;
                            dest.size.width = subRect.size.width;
                            dest.size.height = subRect.size.height;
                            CGContextScaleCTM (context, 1, -1);
                            HIViewDrawCGImage (context, &dest, subImage);
                            CGImageRelease (subImage);
                        }
                    }
                    CGImageRelease (image);
                }
                pContext->releaseCGContext (context);
            }
        }
        return;
    }
	if (pHandle || cgImage)
	{
		CGContextRef context = pContext->beginCGContext ();
		if (context)
		{
			if (alpha != 255)
				CGContextSetAlpha (context, (float)alpha / 255.f);
			
			CGImageRef image = createCGImage ();

			if (image)
			{
				CGRect dest;
				dest.origin.x = rect.left - offset.h + pContext->offset.h;
				dest.origin.y = (rect.top + pContext->offset.v) * -1 - (getHeight () - offset.v);
				dest.size.width = getWidth ();
				dest.size.height = getHeight ();
				
				CRect ccr;
				pContext->getClipRect (ccr);
				CGRect cgClipRect = CGRectMake (ccr.left + pContext->offset.h, (ccr.top + pContext->offset.v) * -1 - ccr.height (), ccr.width (), ccr.height ());
				CGContextClipToRect (context, cgClipRect);

				CGRect clipRect;
				clipRect.origin.x = rect.left + pContext->offset.h;
			    clipRect.origin.y = (rect.top + pContext->offset.v) * -1  - rect.height ();
			    clipRect.size.width = rect.width (); 
			    clipRect.size.height = rect.height ();
				
				CGContextClipToRect (context, clipRect);

				CGContextDrawImage (context, dest, image);
				CGImageRelease (image);
			}
			pContext->releaseCGContext (context);
		}
	}
	
    #else
	Rect source, dest;
	dest.top    = rect.top  + pContext->offset.v;
	dest.left   = rect.left + pContext->offset.h;
	dest.bottom = dest.top  + rect.height ();
	dest.right  = dest.left + rect.width ();
		
	source.top    = offset.v;
	source.left   = offset.h;
	source.bottom = source.top  + rect.height ();
	source.right  = source.left + rect.width ();
		
	pContext->getPort ();
	BitMapPtr bitmapPtr = pContext->getBitmap ();
	if (bitmapPtr)
	{
		RGBColor col;
		CColor color = {alpha, alpha, alpha, 0};
		CColor2RGBColor (color, col);
		OpColor (&col);
		
		if (pHandle)
		{
			PixMapHandle pmHandle = GetGWorldPixMap ((GWorldPtr)pHandle);
			if (pmHandle && LockPixels (pmHandle))
			{
				RGBColor oldForeColor, oldBackColor;
				GetForeColor (&oldForeColor);
				GetBackColor (&oldBackColor);
				::BackColor (whiteColor);
				::ForeColor (blackColor);
			
				CopyBits ((BitMapPtr)*pmHandle, bitmapPtr, &source, &dest, blend, 0L);
				#if MACX
				QDAddRectToDirtyRegion (pContext->getPort (), &dest);
				#endif
			
				RGBForeColor (&oldForeColor);
				RGBBackColor (&oldBackColor);
			
				UnlockPixels (pmHandle);
			}
		}
	}

	pContext->releaseBitmap ();
        #endif
#endif
}
//-----------------------------------------------------------------------------
void CBitmap::setTransparentColor (const CColor color)
{
	transparentCColor = color;
#if QUARTZ
	if (noAlpha)
	{
		if (cgImage)
			CGImageRelease ((CGImageRef)cgImage);
		cgImage = 0;
	}
#endif
}

//-----------------------------------------------------------------------------
void CBitmap::setTransparencyMask (CDrawContext* pContext, const CPoint& offset)
{
#if WINDOWS
	if (pMask)
		DeleteObject (pMask);

	CRect r (0, 0, width, height);
	r.offset (offset.h, offset.v);
	pMask = CreateMaskBitmap (pContext, r, transparentCColor);

#elif MAC
	#if QUARTZ
	#else
	if (pMask)
		DisposeGWorld ((GWorldPtr)pMask);
	pMask = 0;
	
	Rect r;
	r.left = r.top = 0;
	r.right = width;
	r.bottom = height;
	OSErr err = NewGWorld ((GWorldPtr*)&pMask, 1, &r, 0, 0, 0); // create monochrome GWorld
	if (!err)
	{
		GWorldPtr oldPort;
		GDHandle oldDevice;
		GetGWorld (&oldPort, &oldDevice);
		SetGWorld ((GWorldPtr)pMask, 0);

		PixMapHandle pmHandle = GetGWorldPixMap ((GWorldPtr)pMask);
		BitMapPtr sourcePtr = pContext->getBitmap ();
		
		if (sourcePtr && pmHandle && LockPixels (pmHandle))
		{
			RGBColor oldForeColor, oldBackColor;
			GetForeColor (&oldForeColor);
			GetBackColor (&oldBackColor);
			
			RGBColor col;
			CColor2RGBColor (transparentCColor, col);
			RGBBackColor (&col);

			::ForeColor (blackColor);

			Rect src = r;
			src.left   += offset.h;
			src.right  += offset.h;
			src.top    += offset.v;
			src.bottom += offset.v;

			CopyBits (sourcePtr, (BitMapPtr)*pmHandle, &src, &r, srcCopy, 0L);

			RGBForeColor (&oldForeColor);
			RGBBackColor (&oldBackColor);
			
			UnlockPixels (pmHandle);
		}
		
		pContext->releaseBitmap ();
				
		SetGWorld (oldPort, oldDevice);
	}
	#endif
        
#else
	// todo: implement me!
#endif
}

//-----------------------------------------------------------------------------
//----------------------------------------------------------------------------
#if MOTIF
//-----------------------------------------------------------------------------
void* CBitmap::createPixmapFromXpm (CDrawContext *pContext)
{
	if (!ppDataXpm)
		return NULL;
  
	Pixmap pixmap = 0;
	XpmAttributes attributes;
	
	attributes.valuemask = XpmCloseness|XpmColormap|XpmVisual|XpmDepth; 
	attributes.closeness = 100000;
	attributes.visual = pContext->getVisual ();
	attributes.depth  = pContext->getDepth ();

	// use the pContext colormap instead of the DefaultColormapOfScreen
	attributes.colormap = pContext->getColormap ();

	int status;
	if (attributes.depth == 8 || attributes.depth == 24)
	{
#if USE_XPM
		status = XpmCreatePixmapFromData (pContext->pDisplay,
							(Drawable)pContext->pWindow, ppDataXpm, &pixmap, NULL, &attributes);
		if (status != XpmSuccess)
		{
			fprintf (stderr, "createPixmapFromXpm-> XpmError: %s\n", XpmGetErrorString(status));
			return NULL;
		}
#else
		status = createPixmapFromData (pContext->pDisplay,
         (Drawable)pContext->pWindow, ppDataXpm, &pixmap, &attributes);
		if (!status)
		{
			fprintf (stderr, "createPixmapFromXpm-> Error\n");
			return NULL;
		}
#endif
	}
	else
	{
		fprintf (stderr, "createPixmapFromXpm-> Depth %d not supported\n", attributes.depth);
		return NULL;
	}

#if DEVELOPMENT
	fprintf (stderr, "createPixmapFromXpm-> There are %d requested colors\n", attributes.ncolors);
#endif

	return (void*)pixmap;
}
#endif

//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
#if BEOS
//----------------------------------------------------------------------------

BResources* CBitmap::resourceFile = 0;

//----------------------------------------------------------------------------

void CBitmap::closeResource ()
{
	if (resourceFile)
	{
		delete resourceFile;
		resourceFile = 0;
	}
}

//----------------------------------------------------------------------------
#endif


//-----------------------------------------------------------------------------
// CDragContainer Implementation
//-----------------------------------------------------------------------------
CDragContainer::CDragContainer (void* platformDrag)
: platformDrag (platformDrag)
, nbItems (0)
, iterator (0)
, lastItem (0)
{
	#if MAC
	DragRef dragRef = (DragRef)platformDrag;
	UInt16 numItems;
	CountDragItems (dragRef, &numItems);
	nbItems = numItems;
	
	#elif WINDOWS
	
	IDataObject* dataObject = (IDataObject*)platformDrag;
	STGMEDIUM medium;
	FORMATETC formatTEXTDrop = {CF_TEXT,  0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
	FORMATETC formatHDrop    = {CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};

	long type = 0; // 0 = file, 1 = text

	HRESULT hr = dataObject->GetData (&formatTEXTDrop, &medium);
	if (hr != S_OK)
		hr = dataObject->GetData (&formatHDrop, &medium);
	else
		type = 1;
	
	if (type == 0)
		nbItems = (long)DragQueryFile ((HDROP)medium.hGlobal, 0xFFFFFFFFL, 0, 0);
	else
		nbItems = 1;
	
	#else
	#endif
}

//-----------------------------------------------------------------------------
CDragContainer::~CDragContainer ()
{
	if (lastItem)
	{
		free (lastItem);
		lastItem = 0;
	}
}

//-----------------------------------------------------------------------------
long CDragContainer::getType (long idx) const
{
	#if MACX
	DragItemRef itemRef;
	if (GetDragItemReferenceNumber ((DragRef)platformDrag, idx+1, &itemRef) == noErr)
	{
		FlavorType type;
		if (GetFlavorType ((DragRef)platformDrag, itemRef, 1, &type) == noErr)
		{
			if (type == flavorTypeHFS || type == typeFileURL)
				return kFile;
			else if (type == 'TEXT' || type == 'XML ')
				return kText;
		}
	}
	#elif WINDOWS
	IDataObject* dataObject = (IDataObject*)platformDrag;
	STGMEDIUM medium;
	FORMATETC formatTEXTDrop = {CF_TEXT,  0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
	FORMATETC formatHDrop    = {CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};

	long type = 0; // 0 = file, 1 = text

	HRESULT hr = dataObject->GetData (&formatTEXTDrop, &medium);
	if (hr != S_OK)
		hr = dataObject->GetData (&formatHDrop, &medium);
	else
		type = 1;
	if (type == 0)
		return kFile;
	else
		return kText;

	#else
	// not implemented
	#endif
	return kUnknown;
}

//-----------------------------------------------------------------------------
void* CDragContainer::first (long& size, long& type)
{
	iterator = 0;
	return next (size, type);
}

//-----------------------------------------------------------------------------
void* CDragContainer::next (long& size, long& type)
{
	if (lastItem)
	{
		free (lastItem);
		lastItem = 0;
	}
	size = 0;
	type = kUnknown;
	#if MACX
	long flavorSize;
	DragItemRef itemRef;
	if (GetDragItemReferenceNumber ((DragRef)platformDrag, ++iterator, &itemRef) == noErr)
	{
		FlavorType flavorType;
		if (GetFlavorType ((DragRef)platformDrag, itemRef, 1, &flavorType) == noErr)
		{
			if (flavorType == flavorTypeHFS)
			{
				HFSFlavor     hfs;
				if (GetFlavorDataSize ((DragRef)platformDrag, itemRef, flavorTypeHFS, &flavorSize) == noErr)
				{ 
					GetFlavorData ((DragRef)platformDrag, itemRef, flavorTypeHFS, &hfs, &flavorSize, 0L);
					
					FSRef fsRef;
					if (FSpMakeFSRef (&hfs.fileSpec, &fsRef) == noErr)
					{
						lastItem = malloc (PATH_MAX);
						if (FSRefMakePath (&fsRef, (unsigned char*)lastItem, PATH_MAX) == noErr)
						{
							size = strlen ((const char*)lastItem);
							type = kFile;
							return lastItem;
						}
						}
					}
			}
			else if (flavorType == typeFileURL)
			{
				if (GetFlavorDataSize ((DragRef)platformDrag, itemRef, typeFileURL, &flavorSize) == noErr)
				{
					void* bytes = malloc (flavorSize);
					if (GetFlavorData ((DragRef)platformDrag, itemRef, typeFileURL, bytes, &flavorSize, 0L) == noErr)
					{
						CFURLRef url = CFURLCreateWithBytes (NULL, (const unsigned char*)bytes, flavorSize, kCFStringEncodingUTF8, NULL);
						lastItem = malloc (PATH_MAX);
						CFURLGetFileSystemRepresentation (url, false, (unsigned char*)lastItem, PATH_MAX);
						CFRelease (url);
						type = kFile;
					}
					free (bytes);
					return lastItem;
				}
			}
			else
			{
				if (GetFlavorDataSize ((DragRef)platformDrag, itemRef, flavorType, &flavorSize) == noErr)
				{
					lastItem = malloc (flavorSize + 1);
					((char*)lastItem)[0] = 0;
					if (GetFlavorData ((DragRef)platformDrag, itemRef, flavorType, lastItem, &flavorSize, 0) == noErr)
					{
						((char*)lastItem)[flavorSize] = 0;
						size = flavorSize;
						if (flavorType == 'TEXT' || flavorType == 'XML ')
							type = kText;
						return lastItem;
					}
				}
				else
				{
					if (GetFlavorDataSize ((DragRef)platformDrag, itemRef, 'TEXT', &flavorSize) == noErr)
					{
						lastItem = malloc (flavorSize + 1);
						((char*)lastItem)[0] = 0;
						if (GetFlavorData ((DragRef)platformDrag, itemRef, 'TEXT', lastItem, &flavorSize, 0) == noErr)
						{
							((char*)lastItem)[flavorSize] = 0;
							size = flavorSize;
							type = kText;
							return lastItem;
						}
					}
				}
				
			}
		}
	}
	#elif WINDOWS
	IDataObject* dataObject = (IDataObject*)platformDrag;
	void* hDrop = 0;
	STGMEDIUM medium;
	FORMATETC formatTEXTDrop = {CF_TEXT,  0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
	FORMATETC formatHDrop    = {CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};

	long wintype = 0; // 0 = file, 1 = text

	HRESULT hr = dataObject->GetData (&formatTEXTDrop, &medium);
	if (hr != S_OK)
		hr = dataObject->GetData (&formatHDrop, &medium);
	else
		wintype = 1;
	if (hr == S_OK)
		hDrop = medium.hGlobal;

	if (hDrop)
	{
		if (wintype == 0)
		{
			char fileDropped[1024];

			long nbRealItems = 0;
			if (DragQueryFile ((HDROP)hDrop, iterator++, fileDropped, sizeof (fileDropped))) 
			{
				// resolve link
				checkResolveLink (fileDropped, fileDropped);
				lastItem = malloc (strlen (fileDropped)+1);
				strcpy ((char*)lastItem, fileDropped);
				size = (long)strlen ((const char*)lastItem);
				type = kFile;
				return lastItem;
			}
		}
		else if (iterator++ == 0)
		//---TEXT----------------------------
		{
			void* data = GlobalLock (medium.hGlobal);
			long dataSize = (long)GlobalSize (medium.hGlobal);
			if (data && dataSize)
			{
				lastItem = malloc (dataSize+1);
				memcpy (lastItem, data, dataSize);
				size = dataSize;
				type = kText;
			}

			GlobalUnlock (medium.hGlobal);
			if (medium.pUnkForRelease)
				medium.pUnkForRelease->Release ();
			else
				GlobalFree (medium.hGlobal);
			return lastItem;
		}
	}
	#else
	// not implemented
	#endif
	return NULL;
}

END_NAMESPACE_VSTGUI


#if WINDOWS

#if USE_MOUSE_HOOK
HHOOK MouseHook = 0L;

LRESULT CALLBACK MouseProc (int nCode, WPARAM wParam, LPARAM lParam)
{
	if (nCode < 0)
		return CallNextHookEx (MouseHook, nCode, wParam, lParam);

	if (wParam == 522)
	{
		MOUSEHOOKSTRUCT* struct2 = (MOUSEHOOKSTRUCT*) lParam;
		if (struct2->hwnd == ???)
		{
			return -1;
		}
	}
	return CallNextHookEx (MouseHook, nCode, wParam, lParam);
}
#endif

//-----------------------------------------------------------------------------
bool InitWindowClass ()
{
	gUseCount++;
	if (gUseCount == 1)
	{
		sprintf (gClassName, "Plugin%p", GetInstance ());
		
		WNDCLASS windowClass;
		windowClass.style = CS_GLOBALCLASS;//|CS_OWNDC; // add Private-DC constant 

		windowClass.lpfnWndProc = WindowProc; 
		windowClass.cbClsExtra  = 0; 
		windowClass.cbWndExtra  = 0; 
		windowClass.hInstance   = GetInstance (); 
		windowClass.hIcon = 0; 

		windowClass.hCursor = LoadCursor (NULL, IDC_ARROW);
		windowClass.hbrBackground = GetSysColorBrush (COLOR_BTNFACE); 
		windowClass.lpszMenuName  = 0; 
		windowClass.lpszClassName = gClassName; 
		RegisterClass (&windowClass);

		#if USE_MOUSE_HOOK
		MouseHook = SetWindowsHookEx (WH_MOUSE, MouseProc, GetInstance (), 0);
		#endif

		bSwapped_mouse_buttons = GetSystemMetrics (SM_SWAPBUTTON) > 0;
	}
	return true;
}

//-----------------------------------------------------------------------------
void ExitWindowClass ()
{
	gUseCount--;
	if (gUseCount == 0)
	{
		UnregisterClass (gClassName, GetInstance ());

		#if USE_MOUSE_HOOK
		if (MouseHook)
		{
			UnhookWindowsHookEx (MouseHook);
			MouseHook = 0L;
		}
		#endif
	}
}

//-----------------------------------------------------------------------------
LONG_PTR WINAPI WindowProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	USING_NAMESPACE_VSTGUI
	CFrame* pFrame = (CFrame*)GetWindowLongPtr (hwnd, GWLP_USERDATA);

	switch (message)
	{
	case WM_MOUSEWHEEL:
	{
		if (pFrame)
		{
			VSTGUI_CDrawContext context (pFrame, 0, hwnd);
			VSTGUI_CPoint where (LOWORD (lParam), HIWORD (lParam));
			short zDelta = (short) HIWORD(wParam);
			pFrame->onWheel (&context, where, (float)zDelta / WHEEL_DELTA);
		}
		break;
	}
	case WM_CTLCOLOREDIT:
	{
		if (pFrame)
		{
			VSTGUI_CTextEdit *textEdit = (VSTGUI_CTextEdit*)pFrame->getFocusView ();
			if (textEdit)
			{
				VSTGUI_CColor fontColor = textEdit->getFontColor ();
				SetTextColor ((HDC) wParam, RGB (fontColor.red, fontColor.green, fontColor.blue));

				VSTGUI_CColor backColor = textEdit->getBackColor ();
				SetBkColor ((HDC) wParam, RGB (backColor.red, backColor.green, backColor.blue));

				if (textEdit->platformFontColor)
					DeleteObject (textEdit->platformFontColor);
				textEdit->platformFontColor = CreateSolidBrush (RGB (backColor.red, backColor.green, backColor.blue));
				return (LRESULT)(textEdit->platformFontColor);
			}
		}
	}
	break;

	case WM_PAINT:
	{
		RECT r;
		if (pFrame && GetUpdateRect (hwnd, &r, false))
		{
			PAINTSTRUCT ps;
			HDC hdc = BeginPaint (hwnd, &ps);

			VSTGUI_CDrawContext* context = pFrame->getBackBuffer ();
			if (!context)
				context = new VSTGUI_CDrawContext (pFrame, hdc, hwnd);
			
			CRect updateRect (ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom);
			pFrame->drawRect (context, updateRect);

			if (pFrame->getBackBuffer ())
			{
				VSTGUI_CDrawContext localContext (pFrame, hdc, hwnd);
				pFrame->getBackBuffer ()->copyFrom (&localContext, updateRect, CPoint (ps.rcPaint.left, ps.rcPaint.top));
			}
			else
				context->forget ();

			EndPaint (hwnd, &ps);
			return 0;
		}
	}
	break;

	case WM_MEASUREITEM :
	{
		MEASUREITEMSTRUCT* ms = (MEASUREITEMSTRUCT*)lParam;
		if (pFrame && ms && ms->CtlType == ODT_MENU && ms->itemData)
		{
			VSTGUI_COptionMenu* optMenu = (VSTGUI_COptionMenu*)pFrame->getFocusView ();
			if (optMenu && optMenu->getScheme ())
			{
				VSTGUI_CPoint size;

				VSTGUI_CDrawContext context (pFrame, 0, hwnd);
				optMenu->getScheme ()->getItemSize ((const char*)ms->itemData, &context, size);

				ms->itemWidth  = size.h;
				ms->itemHeight = size.v;
				return TRUE;
			}
		}
	}
	break;

	case WM_DRAWITEM :
	{
		DRAWITEMSTRUCT* ds = (DRAWITEMSTRUCT*)lParam;
		if (pFrame && ds && ds->CtlType == ODT_MENU && ds->itemData)
		{
			VSTGUI_COptionMenu* optMenu = (VSTGUI_COptionMenu*)pFrame->getFocusView ();
			if (optMenu && optMenu->getScheme ())
			{
				long state = 0;
				if (ds->itemState & ODS_CHECKED)
					state |= VSTGUI_COptionMenuScheme::kChecked;
				if (ds->itemState & ODS_DISABLED) // ODS_GRAYED?
					state |= VSTGUI_COptionMenuScheme::kDisabled;
				if (ds->itemState & ODS_SELECTED)
					state |= VSTGUI_COptionMenuScheme::kSelected;
					
				CRect r (ds->rcItem.left, ds->rcItem.top, ds->rcItem.right, ds->rcItem.bottom);
				r.bottom++;
				
				VSTGUI_CDrawContext* pContext = new VSTGUI_CDrawContext (pFrame, ds->hDC, 0);
				optMenu->getScheme ()->drawItem ((const char*)ds->itemData, ds->itemID, state, pContext, r);
				delete pContext;
				return TRUE;
			}
		}
	}
	break;
	
	case WM_RBUTTONDOWN:
	case WM_MBUTTONDOWN:
	case WM_LBUTTONDOWN:
		if (pFrame)
		{
		#if 1
			VSTGUI_CDrawContext context (pFrame, 0, hwnd);
			VSTGUI_CPoint where (LOWORD (lParam), HIWORD (lParam));
			pFrame->mouse (&context, where);
		#else
			VSTGUI_CPoint where (LOWORD (lParam), HIWORD (lParam));
			pFrame->mouse ((VSTGUI_CDrawContext*)0, where);
		#endif

			return 0;
		}
		break;
		
	case WM_DESTROY:
		if (pFrame)
		{
			pFrame->setOpenFlag (false);
			pFrame->setParentSystemWindow (0);
		}
		break;
	}
	return DefWindowProc (hwnd, message, wParam, lParam);
}

//-----------------------------------------------------------------------------
HANDLE CreateMaskBitmap (CDrawContext* pContext, CRect& rect, CColor transparentColor)
{
	HBITMAP pMask = CreateBitmap (rect.width (), rect.height (), 1, 1, 0);

	HDC hSrcDC = (HDC)pContext->getSystemContext ();
	HDC hDstDC = CreateCompatibleDC (hSrcDC);
	SelectObject (hDstDC, pMask);

	COLORREF oldBkColor = SetBkColor (hSrcDC, RGB (transparentColor.red, transparentColor.green, transparentColor.blue));
	
	BitBlt (hDstDC, 0, 0, rect.width (), rect.height (), hSrcDC, rect.left, rect.top, SRCCOPY);
	
	SetBkColor (hSrcDC, oldBkColor);
	DeleteDC (hDstDC);
	
	return pMask;
}

//-----------------------------------------------------------------------------
void DrawTransparent (CDrawContext* pContext, CRect& rect, const CPoint& offset,
					  HDC hdcBitmap, POINT ptSize, HBITMAP pMask, COLORREF color)
{
	if (pMask == NULL)
	{
		if (pfnTransparentBlt)
		{
			HDC		hdcSystemContext = (HDC)pContext->getSystemContext ();
			long	x, y;
			long	width  = rect.width ();
			long	height = rect.height ();

			x = rect.x + pContext->offset.x;
			y = rect.y + pContext->offset.y;

			pfnTransparentBlt (hdcSystemContext, x, y, width, height, hdcBitmap, offset.x, offset.y, width, height, color);
		}
		else
		{
			// OPTIMIZATION: we only do four instead of EIGHT blits
			HDC		hdcSystemContext = (HDC)pContext->getSystemContext ();
			HDC		hdcMask = CreateCompatibleDC (hdcSystemContext);

			COLORREF	crOldBack = SetBkColor (hdcSystemContext, 0xFFFFFF);
			COLORREF	crOldText = SetTextColor (hdcSystemContext, 0x000000);
			HBITMAP		bmMaskOld, maskMap;

			long	x, y;
			long	width  = rect.width ();
			long	height = rect.height ();

			x = rect.x + pContext->offset.x;
			y = rect.y + pContext->offset.y;

			// Create mask-bitmap in memory
			maskMap = CreateBitmap (width, height, 1, 1, NULL);
			bmMaskOld = (HBITMAP)SelectObject (hdcMask, maskMap);

			// Copy bitmap into mask-bitmap and converting it into a black'n'white mask
			SetBkColor (hdcBitmap, color);
			BitBlt (hdcMask, 0, 0, width, height, hdcBitmap, offset.x, offset.y, SRCCOPY);

			// Copy image masked to screen
			BitBlt (hdcSystemContext, x, y, width, height, hdcBitmap, offset.x, offset.y, SRCINVERT);
			BitBlt (hdcSystemContext, x, y, width, height, hdcMask, 0, 0, SRCAND);
			BitBlt (hdcSystemContext, x, y, width, height, hdcBitmap, offset.x, offset.y, SRCINVERT);

			DeleteObject (SelectObject (hdcMask, bmMaskOld));
			DeleteDC (hdcMask);

			SetBkColor (hdcSystemContext, crOldBack);
			SetTextColor (hdcSystemContext, crOldText);
		}
	}
	else
	{
		// OPTIMIZATION: we only do five instead of EIGHT blits
		HDC		hdcSystemContext = (HDC)pContext->getSystemContext ();
		HDC		hdcMask = CreateCompatibleDC (hdcSystemContext);
		HDC		hdcMem = CreateCompatibleDC (hdcSystemContext);
		HBITMAP	bmAndMem;
		HBITMAP	bmMemOld, bmMaskOld;

		long	x, y;
		long	width = rect.width ();
		long	height = rect.height ();

		x = rect.x + pContext->offset.x;
		y = rect.y + pContext->offset.y;

		bmAndMem = CreateCompatibleBitmap(hdcSystemContext, width, height);

		bmMaskOld   = (HBITMAP)SelectObject (hdcMask, pMask);
		bmMemOld    = (HBITMAP)SelectObject (hdcMem, bmAndMem);

		BitBlt (hdcMem, 0, 0, width, height, hdcSystemContext, x, y, SRCCOPY);
		BitBlt (hdcMem, 0, 0, width, height, hdcBitmap, offset.x, offset.y, SRCINVERT);
		BitBlt (hdcMem, 0, 0, width, height, hdcMask, offset.x, offset.y, SRCAND);
		BitBlt (hdcMem, 0, 0, width, height, hdcBitmap, offset.x, offset.y, SRCINVERT);
		BitBlt (hdcSystemContext, x, y, width, height, hdcMem, 0, 0, SRCCOPY);

		DeleteObject (SelectObject (hdcMem, bmMemOld));
		SelectObject (hdcMask, bmMaskOld);

		DeleteDC (hdcMem);
		DeleteDC(hdcMask);
	}
}
#endif

//-----------------------------------------------------------------------------
#if MAC || MOTIF || BEOS
BEGIN_NAMESPACE_VSTGUI
// return a degre value between [0, 360 * 64[
long convertPoint2Angle (CPoint &pm, CPoint &pt)
{
	long angle;
	if (pt.h == pm.h)
	{
		if (pt.v < pm.v)
			angle = 5760;	// 90 * 64
		else
			angle = 17280; // 270 * 64
	}
	else if (pt.v == pm.v)
	{
		if (pt.h < pm.h)
			angle = 11520;	// 180 * 64
		else
			angle = 0;	
	}
	else
	{
		// 3666.9299 = 180 * 64 / pi
		angle = (long)(3666.9298 * atan ((double)(pm.v - pt.v) / (double)(pt.h - pm.h)));
    
		if (pt.v < pm.v)
		{
			if (pt.h < pm.h)
				angle += 11520; // 180 * 64
		}
		else
		{
			if (pt.h < pm.h)
				angle += 11520; // 180 * 64
			else
				angle += 23040; // 360 * 64
		}
	}
	return angle;
}
END_NAMESPACE_VSTGUI
#endif


//-----------------------------------------------------------------------------
#if MOTIF
XRectangle rect;
static bool first = true;

//-----------------------------------------------------------------------------
void _destroyCallback (Widget widget, XtPointer clientData, XtPointer callData)
{
	CFrame* pFrame = (CFrame*)clientData;
	if (pFrame)
	{
		pFrame->freeGc ();
		pFrame->setOpenFlag (false);
		pFrame->pSystemWindow = 0;
	}
}

//-----------------------------------------------------------------------------
void _drawingAreaCallback (Widget widget, XtPointer clientData, XtPointer callData)
{
	CFrame* pFrame = (CFrame*)clientData;
	XmDrawingAreaCallbackStruct *cbs = (XmDrawingAreaCallbackStruct *)callData;
	XEvent *event = cbs->event;

	//-------------------------------------
	if (cbs->reason == XmCR_INPUT)
	{
		if (event->xbutton.type == ButtonRelease)
			return;

		if (event->xbutton.type != ButtonPress &&
				event->xbutton.type != KeyPress)
			return;

		Window pWindow = pFrame->getWindow ();
		CDrawContext context (pFrame, pFrame->getGC (), (void*)pWindow);

		CPoint where (event->xbutton.x, event->xbutton.y);
		pFrame->mouse (&context, where);
	}
	//------------------------------------
	else if (cbs->reason == XmCR_EXPOSE)
	{
		XExposeEvent *expose = (XExposeEvent*)event;
#if TEST_REGION
		rect.x      = expose->x;
		rect.y      = expose->y;
		rect.width  = expose->width;
		rect.height = expose->height;
		if (first)
		{
			pFrame->region = XCreateRegion ();
			first = false;
		}

		XUnionRectWithRegion (&rect, pFrame->region, pFrame->region);
#endif
		if (expose->count == 0)
		{
#if TEST_REGION
			XSetRegion (expose->pDisplay, pFrame->getGC (), pFrame->region);

			// add processus of static first to set the region to max after a total draw and destroy it the first time...
#endif
			pFrame->draw ();

#if TEST_REGION
			rect.x      = 0;
			rect.y      = 0;
			rect.width  = pFrame->getWidth ();
			rect.height = pFrame->getHeight ();
			XUnionRectWithRegion (&rect, pFrame->region, pFrame->region);
			XSetRegion (expose->pDisplay, pFrame->getGC (), pFrame->region);
			XDestroyRegion (pFrame->region);
			first = true;
#endif
		}
	}
}

//-----------------------------------------------------------------------------
void _eventHandler (Widget w, XtPointer clientData, XEvent *event, char *p)
{
	switch (event->type)
	{
	case EnterNotify:
		break;

	case LeaveNotify:
		XCrossingEvent *xevent = (XCrossingEvent*)event;
		
		CFrame* pFrame = (CFrame*)clientData;
		if (pFrame && pFrame->getFocusView ())
		{
			if (xevent->x < 0 || xevent->x >= pFrame->getWidth () ||
					xevent->y < 0 || xevent->y >= pFrame->getHeight ())
			{
				// if button pressed => don't defocus
				if (xevent->state & (Button1Mask|Button2Mask|Button3Mask))
					break;
				pFrame->getFocusView ()->looseFocus ();
				pFrame->setFocusView (0);
			}
		}
		break;
	}
}

//-----------------------------------------------------------------------------
long getIndexColor8Bit (CColor color, Display *pDisplay, Colormap colormap)
{
	long i;

	// search in pre-loaded color
	for (i = 0; i < CDrawContext::nbNewColor; i++)
	{
		if ((paletteNewColor[i].red   == color.red)   &&
				(paletteNewColor[i].green == color.green) &&
				(paletteNewColor[i].blue  == color.blue))
			return paletteNewColor[i].alpha;
	}
	
	// Allocate new color cell
	XColor xcolor;
	int red   = color.red   << 8;
	int green = color.green << 8;
	int blue  = color.blue  << 8;
	xcolor.red   = red;
	xcolor.green = green;
	xcolor.blue  = blue;	
	if (XAllocColor (pDisplay, colormap, &xcolor))
	{
		// store this new color
		if (CDrawContext::nbNewColor < 255) 
		{
			paletteNewColor[CDrawContext::nbNewColor].red    = color.red;
			paletteNewColor[CDrawContext::nbNewColor].green  = color.green;
			paletteNewColor[CDrawContext::nbNewColor].blue   = color.blue;
			paletteNewColor[CDrawContext::nbNewColor].alpha = xcolor.pixel;
			CDrawContext::nbNewColor++;
		}
		return xcolor.pixel;
	}
		
	// take the nearest color
	int diff;
	int min = 3 * 65536;
	int index = 0;

	XColor xcolors[256];
	for (i = 0; i < 256; i++)
		xcolors[i].pixel = i;

	XQueryColors (pDisplay, colormap, xcolors, 256);

	for (i = 0; i < 256; i++)
	{
		diff = fabs (xcolors[i].red - red) + fabs (xcolors[i].green - green) + fabs (xcolors[i].blue - blue);
		if (diff < min)
		{
			min = diff;
			index = i;
		}
	}

	// store this new color
	if (CDrawContext::nbNewColor < 255)
	{
		paletteNewColor[CDrawContext::nbNewColor].red    = color.red;
		paletteNewColor[CDrawContext::nbNewColor].green  = color.green;
		paletteNewColor[CDrawContext::nbNewColor].blue   = color.blue;
		paletteNewColor[CDrawContext::nbNewColor].alpha = index;
		CDrawContext::nbNewColor++;
	}
	return (index);
}

//-----------------------------------------------------------------------------
bool xpmGetValues (char **ppDataXpm, long *pWidth, long *pHeight, long *pNcolor, long *pCpp)
{
	// get the size of the pixmap
	sscanf (ppDataXpm[0], "%d %d %d %d", pWidth, pHeight, pNcolor, pCpp);
	
	return true;
}

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#elif BEOS
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
PlugView::PlugView (BRect frame, CFrame* cframe)
	: BView (frame, NULL, B_FOLLOW_ALL, B_WILL_DRAW), cframe (cframe)
{
	SetViewColor (B_TRANSPARENT_COLOR);
}

//-----------------------------------------------------------------------------
void PlugView::Draw (BRect updateRect)
{
	cframe->draw ();
}

//-----------------------------------------------------------------------------
void PlugView::MouseDown (BPoint where)
{
	BMessage*	m = Window ()->CurrentMessage ();
	int32 buttons;
	m->FindInt32 ("buttons", &buttons);
	
	if (buttons & B_SECONDARY_MOUSE_BUTTON && !Window ()->IsFront () && !Window ()->IsFloating ())
	{
		Window ()->Activate (true);
		return;
	}

	CDrawContext context (cframe, this, NULL);
	CPoint here (where.x, where.y);
	cframe->mouse (&context, here);
}

//-----------------------------------------------------------------------------
void PlugView::MessageReceived (BMessage *msg)
{
	if (msg->what == B_SIMPLE_DATA)
	{
		int32		countMax = 0;	// max number of references. Possibly not all valid...
		type_code	typeFound;
		msg->GetInfo ("refs", &typeFound, &countMax);
		if (countMax > 0)
		{ 
			entry_ref	item;
			int			nbRealItems = 0;
			char **		ptrItems = new char* [countMax];
			for (int k = 0; k < countMax; k++)
				if (msg->FindRef ("refs", k, &item) == B_OK)
				{
					BPath path (&item);
					if (path.InitCheck () == B_OK)
						ptrItems[nbRealItems++] = strdup (path.Path ());
				}
			BPoint bwhere = msg->DropPoint ();
			ConvertFromScreen (&bwhere);
			CPoint where (bwhere.x, bwhere.y);
			cframe->onDrop ((void**)ptrItems, nbRealItems, kDropFiles, where);
			for (long i = 0; i < nbRealItems; i++)
				free (ptrItems[i]);
			delete []ptrItems;
		}
	}
	else BView::MessageReceived (msg);
}

#endif


//-----------------------------------------------------------------------------
#if WINDOWS
//-----------------------------------------------------------------------------
// Drop Implementation
//-----------------------------------------------------------------------------
class CDropTarget : public IDropTarget
{	
public:
	CDropTarget (VSTGUI_CFrame* pFrame);
	virtual ~CDropTarget ();

	// IUnknown
	STDMETHOD (QueryInterface) (REFIID riid, void** object);
	STDMETHOD_ (ULONG, AddRef) (void);
	STDMETHOD_ (ULONG, Release) (void);
   
	// IDropTarget
	STDMETHOD (DragEnter) (IDataObject *dataObject, DWORD keyState, POINTL pt, DWORD *effect);
	STDMETHOD (DragOver) (DWORD keyState, POINTL pt, DWORD *effect);
	STDMETHOD (DragLeave) (void);
	STDMETHOD (Drop) (IDataObject *dataObject, DWORD keyState, POINTL pt, DWORD *effect);
private:
	long refCount;
	bool accept;
	VSTGUI_CFrame* pFrame;
};

//-----------------------------------------------------------------------------
// CDropTarget
//-----------------------------------------------------------------------------
void* createDropTarget (VSTGUI_CFrame* pFrame)
{
	return new CDropTarget (pFrame);
}

//-----------------------------------------------------------------------------
CDropTarget::CDropTarget (VSTGUI_CFrame* pFrame)
: refCount (0), pFrame (pFrame)
{
}

//-----------------------------------------------------------------------------
CDropTarget::~CDropTarget ()
{
}

//-----------------------------------------------------------------------------
STDMETHODIMP CDropTarget::QueryInterface (REFIID riid, void** object)
{
	if (riid == IID_IDropTarget || riid == IID_IUnknown)
	{
		*object = this;
		AddRef ();
      return NOERROR;
	}
	*object = 0;
	return E_NOINTERFACE;
}

//-----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CDropTarget::AddRef (void)
{
	return ++refCount;
}

//-----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CDropTarget::Release (void)
{
	refCount--;
	if (refCount <= 0)
	{
		delete this;
		return 0;
	}
	return refCount;
}

//-----------------------------------------------------------------------------
STDMETHODIMP CDropTarget::DragEnter (IDataObject *dataObject, DWORD keyState, POINTL pt, DWORD *effect)
{
	if (dataObject && pFrame)
	{
		gDragContainer = new CDragContainer (dataObject);
		CDrawContext* context = pFrame->createDrawContext ();
		VSTGUI_CPoint where;
		pFrame->getMouseLocation (context, where);
		pFrame->onDragEnter (context, gDragContainer, where);
		context->forget ();
		*effect = DROPEFFECT_MOVE;
	}
	else
	*effect = DROPEFFECT_NONE;
	return S_OK;
}

//-----------------------------------------------------------------------------
STDMETHODIMP CDropTarget::DragOver (DWORD keyState, POINTL pt, DWORD *effect)
{
	if (gDragContainer && pFrame)
	{
		CDrawContext* context = pFrame->createDrawContext ();
		VSTGUI_CPoint where;
		pFrame->getMouseLocation (context, where);
		pFrame->onDragMove (context, gDragContainer, where);
		context->forget ();
		*effect = DROPEFFECT_MOVE;
	}
	return S_OK;
}

//-----------------------------------------------------------------------------
STDMETHODIMP CDropTarget::DragLeave (void)
{
	if (gDragContainer && pFrame)
	{
		CDrawContext* context = pFrame->createDrawContext ();
		VSTGUI_CPoint where;
		pFrame->getMouseLocation (context, where);
		pFrame->onDragLeave (context, gDragContainer, where);
		context->forget ();
		gDragContainer->forget ();
		gDragContainer = 0;
	}
	return S_OK;
}

//-----------------------------------------------------------------------------
STDMETHODIMP CDropTarget::Drop (IDataObject *dataObject, DWORD keyState, POINTL pt, DWORD *effect)
{
	if (gDragContainer && pFrame)
	{
		CDrawContext* context = pFrame->createDrawContext ();
		VSTGUI_CPoint where;
		pFrame->getMouseLocation (context, where);
		pFrame->onDrop (context, gDragContainer, where);
		context->forget ();
		gDragContainer->forget ();
		gDragContainer = 0;
	}
	return S_OK;
}

//-----------------------------------------------------------------------------
bool checkResolveLink (const char* nativePath, char* resolved)
{
	const char* ext = strrchr (nativePath, '.');
	if (ext && _stricmp (ext, ".lnk") == NULL)
	{
		IShellLink* psl;
		IPersistFile* ppf;
		WIN32_FIND_DATA wfd;
		HRESULT hres;
		WORD wsz[2048];
		
		// Get a pointer to the IShellLink interface.
		hres = CoCreateInstance (CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
			IID_IShellLink, (void**)&psl);
		if (SUCCEEDED (hres))
		{
			// Get a pointer to the IPersistFile interface.
			hres = psl->QueryInterface (IID_IPersistFile, (void**)&ppf);
			if (SUCCEEDED (hres))
			{
				// Ensure string is Unicode.
				MultiByteToWideChar (CP_ACP, 0, nativePath, -1, (LPWSTR)wsz, 2048);
				// Load the shell link.
				hres = ppf->Load ((LPWSTR)wsz, STGM_READ);
				if (SUCCEEDED (hres))
				{					
					hres = psl->Resolve (0, MAKELONG (SLR_ANY_MATCH | SLR_NO_UI, 500));
					if (SUCCEEDED (hres))
					{
						// Get the path to the link target.
						hres = psl->GetPath (resolved, 2048, &wfd, SLGP_SHORTPATH);
					}
				}
				// Release pointer to IPersistFile interface.
				ppf->Release ();
			}
			// Release pointer to IShellLink interface.
			psl->Release ();
		}
		return SUCCEEDED(hres);
	}
	return false;	
}

#elif MAC
BEGIN_NAMESPACE_VSTGUI

#if MAC_OLD_DRAG
//-----------------------------------------------------------------------------
// Drop Implementation
//-----------------------------------------------------------------------------
#if !MACX
#include "Drag.h"
#endif

pascal static short drag_receiver (WindowPtr w, void* ref, DragReference drag);
pascal static OSErr drag_tracker (DragTrackingMessage message, WindowRef theWindow, void *handlerRefCon, DragRef theDrag);

static DragReceiveHandlerUPP drh;
static DragTrackingHandlerUPP dth;

static bool gEventDragWorks = false;

//-------------------------------------------------------------------------------------------
void install_drop (CFrame *frame)
{
	drh = NewDragReceiveHandlerUPP (drag_receiver);
	dth = NewDragTrackingHandlerUPP (drag_tracker);
#if TARGET_API_MAC_CARBON
	InstallReceiveHandler (drh, (WindowRef)(frame->getSystemWindow ()), (void*)frame);
	InstallTrackingHandler (dth, (WindowRef)(frame->getSystemWindow ()), (void*)frame);
#else
	InstallReceiveHandler (drh, (GrafPort*)(frame->getSystemWindow ()), (void*)frame);
	InstallTrackingHandler (dth, (GrafPort*)(frame->getSystemWindow ()), (void*)frame);
#endif
}

//-------------------------------------------------------------------------------------------
void remove_drop (CFrame *frame)
{
#if TARGET_API_MAC_CARBON
	RemoveReceiveHandler (drh, (WindowRef)(frame->getSystemWindow ()));
	RemoveTrackingHandler (dth, (WindowRef)(frame->getSystemWindow ()));
#else
	RemoveReceiveHandler (drh, (GrafPort*)(frame->getSystemWindow ()));
	RemoveTrackingHandler (dth, (GrafPort*)(frame->getSystemWindow ()));
#endif
	DisposeDragReceiveHandlerUPP (drh);
	DisposeDragTrackingHandlerUPP (dth);
}

// drag tracking for visual feedback
pascal OSErr drag_tracker (DragTrackingMessage message, WindowRef theWindow, void *handlerRefCon, DragRef dragRef)
{
	#if QUARTZ
	if (gEventDragWorks)
		return noErr;
	#endif

	CFrame* frame = (CFrame*)handlerRefCon;
	switch (message)
	{
		case kDragTrackingEnterWindow:
		{
			if (gDragContainer)
				gDragContainer->forget ();
			gDragContainer = new CDragContainer (dragRef);

			CDrawContext* context = frame->createDrawContext ();
			VSTGUI_CPoint where;
			frame->setCursor (kCursorNotAllowed);
			frame->getMouseLocation (context, where);
			frame->onDragEnter (context, gDragContainer, where);
			context->forget ();
			break;
		}
		case kDragTrackingLeaveWindow:
		{
			CDrawContext* context = frame->createDrawContext ();
			VSTGUI_CPoint where;
			frame->getMouseLocation (context, where);
			frame->onDragLeave (context, gDragContainer, where);
			frame->setCursor (kCursorDefault);
			context->forget ();
			gDragContainer->forget ();
			gDragContainer = NULL;
			break;
		}
		case kDragTrackingInWindow:
		{
			CDrawContext* context = frame->createDrawContext ();
			VSTGUI_CPoint where;
			frame->getMouseLocation (context, where);
			frame->onDragMove (context, gDragContainer, where);
			context->forget ();

			break;
		}
	}
	return noErr;
}

//-------------------------------------------------------------------------------------------
// Drop has happened in one of our's windows.
// The data is either of our own type (flavour type stCA), or comes from
// another app. The only data from outside that is currently accepted are
// HFS-files
//-------------------------------------------------------------------------------------------
pascal short drag_receiver (WindowPtr w, void* ref, DragReference drag)
{
	#if QUARTZ
	if (gEventDragWorks)
		return noErr;
	#endif

	if (!gDragContainer)
		return noErr;
	
	CFrame* frame = (CFrame*) ref;
	
	CDrawContext* context = frame->createDrawContext ();
	VSTGUI_CPoint where;
	frame->getMouseLocation (context, where);
	frame->onDrop (context, gDragContainer, where);
	frame->setCursor (kCursorDefault);
	context->forget ();

	gDragContainer->forget ();
	gDragContainer = NULL;
	return noErr;
}
#endif // MAC_OLD_DRAG

#if QUARTZ
#define defControlStringMask	CFSTR ("net.sourceforge.vstgui.%d")

bool CFrame::registerWithToolbox ()
{
	CFStringRef defControlString = CFStringCreateWithFormat (NULL, NULL, defControlStringMask, this);

	controlSpec.defType = kControlDefObjectClass;
	controlSpec.u.classRef = NULL;

	EventTypeSpec eventTypes[] = {	{kEventClassControl, kEventControlDraw},
									{kEventClassControl, kEventControlHitTest},
									{kEventClassControl, kEventControlClick},
									{kEventClassControl, kEventControlTrack},
									{kEventClassControl, kEventControlContextualMenuClick},
									{kEventClassKeyboard, kEventRawKeyDown},
									{kEventClassKeyboard, kEventRawKeyRepeat},
									{kEventClassMouse, kEventMouseWheelMoved},
									{kEventClassControl, kEventControlDragEnter},
									{kEventClassControl, kEventControlDragWithin},
									{kEventClassControl, kEventControlDragLeave},
									{kEventClassControl, kEventControlDragReceive},
									{kEventClassControl, kEventControlInitialize},
									{kEventClassControl, kEventControlGetClickActivation},
									{kEventClassControl, kEventControlGetOptimalBounds},
									{kEventClassScrollable, kEventScrollableGetInfo},
									{kEventClassScrollable, kEventScrollableScrollTo},
									{kEventClassControl, kEventControlSetFocusPart},
									{kEventClassControl, kEventControlGetFocusPart},
								};

	ToolboxObjectClassRef controlClass = NULL;

	OSStatus status = RegisterToolboxObjectClass (	defControlString,
													NULL,
													GetEventTypeCount (eventTypes),
													eventTypes,
													CFrame::carbonEventHandler,
													this,
													&controlClass);
	if (status == noErr)
		controlSpec.u.classRef = controlClass;

	CFRelease (defControlString);

	return (controlSpec.u.classRef != NULL);
}
//------------------------------------------------------------------------------
static short keyTable[] = {
	VKEY_BACK,		0x33, 
	VKEY_TAB,		0x30, 
	VKEY_RETURN,	0x24, 
	VKEY_PAUSE,		0x71, 
	VKEY_ESCAPE,	0x35, 
	VKEY_SPACE,		0x31, 

	VKEY_END,		0x77, 
	VKEY_HOME,		0x73, 

	VKEY_LEFT,		0x7B, 
	VKEY_UP,		0x7E, 
	VKEY_RIGHT,		0x7C, 
	VKEY_DOWN,		0x7D, 
	VKEY_PAGEUP,	0x74, 
	VKEY_PAGEDOWN,	0x79, 

	VKEY_PRINT,		0x69, 			
	VKEY_ENTER,		0x4C, 
	VKEY_HELP,		0x72, 
	VKEY_DELETE,	0x75, 
	VKEY_NUMPAD0,	0x52, 
	VKEY_NUMPAD1,	0x53, 
	VKEY_NUMPAD2,	0x54, 
	VKEY_NUMPAD3,	0x55, 
	VKEY_NUMPAD4,	0x56, 
	VKEY_NUMPAD5,	0x57, 
	VKEY_NUMPAD6,	0x58, 
	VKEY_NUMPAD7,	0x59, 
	VKEY_NUMPAD8,	0x5B, 
	VKEY_NUMPAD9,	0x5C, 
	VKEY_MULTIPLY,	0x43, 
	VKEY_ADD,		0x45, 
	VKEY_SUBTRACT,	0x4E, 
	VKEY_DECIMAL,	0x41, 
	VKEY_DIVIDE,	0x4B, 
	VKEY_F1,		0x7A, 
	VKEY_F2,		0x78, 
	VKEY_F3,		0x63, 
	VKEY_F4,		0x76, 
	VKEY_F5,		0x60, 
	VKEY_F6,		0x61, 
	VKEY_F7,		0x62, 
	VKEY_F8,		0x64, 
	VKEY_F9,		0x65, 
	VKEY_F10,		0x6D, 
	VKEY_F11,		0x67, 
	VKEY_F12,		0x6F, 
	VKEY_NUMLOCK,	0x47, 
	VKEY_EQUALS,	0x51
};

#ifndef kHIViewFeatureGetsFocusOnClick
#define   kHIViewFeatureGetsFocusOnClick (1 << 8)
#endif

bool hiToolboxAllowFocusChange = false;

//---------------------------------------------------------------------------------------
pascal OSStatus CFrame::carbonEventHandler (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData)
{
	OSStatus result = eventNotHandledErr;
	CFrame* frame = (CFrame*)inUserData;
	UInt32 eventClass = GetEventClass (inEvent);
	UInt32 eventKind = GetEventKind (inEvent);
	WindowRef window = (WindowRef)frame->getSystemWindow ();

	// WARNING :
	// I've not implemented the old style resource file handling.
	// Use the CFBundleCopyResourceURL... functions to get your resources.

	switch (eventClass)
	{
		case kEventClassScrollable:
		{
			switch (eventKind)
			{
				case kEventScrollableGetInfo:
				{
					HISize cs = {frame->getWidth (), frame->getHeight ()};
					SetEventParameter (inEvent, kEventParamImageSize, typeHISize, sizeof (HISize), &cs);
					HIPoint origin = {frame->hiScrollOffset.x, frame->hiScrollOffset.y};
					SetEventParameter (inEvent, kEventParamOrigin, typeHIPoint, sizeof (HIPoint), &origin);
					HISize lineSize = {50.0, 20.0};
					SetEventParameter(inEvent, kEventParamLineSize, typeHISize, sizeof(lineSize), &lineSize);
					HIRect bounds;
					HIViewGetBounds ((HIViewRef)frame->controlRef, &bounds);
					SetEventParameter(inEvent, kEventParamViewSize, typeHISize, sizeof(bounds.size), &bounds.size);
					result = noErr;
					break;
				}
				case kEventScrollableScrollTo:
				{
					HIPoint where;
					GetEventParameter(inEvent, kEventParamOrigin, typeHIPoint, NULL, sizeof(where), NULL, &where);
					frame->hiScrollOffset.x = (CCoord)where.x;
					frame->hiScrollOffset.y = (CCoord)where.y;
					HIViewSetBoundsOrigin((HIViewRef)frame->controlRef, where.x, where.y);
					HIViewSetNeedsDisplay((HIViewRef)frame->controlRef, true);
					result = noErr;
					break;
				}
			}
			break;
		}
		case kEventClassControl:
		{
			switch (eventKind)
			{
				case kEventControlInitialize:
				{
					UInt32 controlFeatures = kControlSupportsDragAndDrop | kControlSupportsFocus | kControlHandlesTracking | kControlSupportsEmbedding | kHIViewFeatureGetsFocusOnClick;
					SetEventParameter (inEvent, kEventParamControlFeatures, typeUInt32, sizeof (UInt32), &controlFeatures);
					result = noErr;
					break;
				}
				case kEventControlDraw:
				{
					CDrawContext* context = 0;
					if (frame->pFrameContext)
					{
						context = frame->pFrameContext;
						context->remember ();
					}
					else
					{
						CGContextRef cgcontext = 0;
						OSStatus res = GetEventParameter (inEvent, kEventParamCGContextRef, typeCGContextRef, NULL, sizeof (cgcontext), NULL, &cgcontext);
						context = new CDrawContext (frame, (res == noErr) ? cgcontext : NULL, window);
					}
					RgnHandle dirtyRegion;
					if (GetEventParameter (inEvent, kEventParamRgnHandle, typeQDRgnHandle, NULL, sizeof (RgnHandle), NULL, &dirtyRegion) == noErr)
					{
						bool frameWasDirty = frame->bDirty;
						Rect bounds;
						GetRegionBounds (dirtyRegion, &bounds);
						CRect updateRect;
						Rect2CRect (bounds, updateRect);
						WindowAttributes windowAttributes;
						GetWindowAttributes (window, &windowAttributes);
						if (!(windowAttributes & kWindowCompositingAttribute))
							updateRect.offset (-context->offsetScreen.x, -context->offsetScreen.y);
						frame->drawRect (context, updateRect);
						if (frameWasDirty && updateRect != frame->size)
							frame->setDirty (true);
					}
					else
						frame->draw (context);
					context->forget ();
					result = noErr;
					break;
				}
				case kEventControlGetClickActivation:
				{
					ClickActivationResult activation = kActivateAndHandleClick;
					SetEventParameter (inEvent, kEventParamClickActivation, typeClickActivationResult, sizeof (ClickActivationResult), &activation);
					result = noErr;
					break;
				}
				case kEventControlHitTest:
				{
					ControlPartCode code = kControlContentMetaPart;
					SetEventParameter (inEvent, kEventParamControlPart, typeControlPartCode, sizeof (ControlPartCode), &code);
					result = noErr;
					break;
				}
				case kEventControlClick:
				{
					EventMouseButton buttonState;
					GetEventParameter (inEvent, kEventParamMouseButton, typeMouseButton, NULL, sizeof (EventMouseButton), NULL, &buttonState);
					if (buttonState == kEventMouseButtonPrimary)
					{
						result = CallNextEventHandler (inHandlerCallRef, inEvent);
						break;
					}
				}
				case kEventControlTrack:
				case kEventControlContextualMenuClick:
				{
					long buttons = 0;
					EventMouseButton buttonState;
					HIPoint hipoint;
					UInt32 modifiers;
					GetEventParameter (inEvent, kEventParamMouseLocation, typeHIPoint, NULL, sizeof (HIPoint), NULL, &hipoint);
					if (eventKind == kEventControlContextualMenuClick)
						buttons = kRButton;
					else if (eventKind == kEventControlTrack)
					{
						buttons = kLButton;
						GetEventParameter (inEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof (UInt32), NULL, &modifiers);
						if (modifiers & cmdKey)
							buttons |= kControl;
						if (modifiers & shiftKey)
							buttons |= kShift;
						if (modifiers & optionKey)
							buttons |= kAlt;
						if (modifiers & controlKey)
							buttons |= kApple;
					}
					else
					{
						GetEventParameter (inEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof (UInt32), NULL, &modifiers);
						GetEventParameter (inEvent, kEventParamMouseButton, typeMouseButton, NULL, sizeof (EventMouseButton), NULL, &buttonState);
						if (buttonState == kEventMouseButtonPrimary)
							buttons |= kLButton;
						if (buttonState == kEventMouseButtonSecondary)
							buttons |= kRButton;
						if (buttonState == kEventMouseButtonTertiary)
							buttons |= kMButton;
						if (modifiers & cmdKey)
							buttons |= kControl;
						if (modifiers & shiftKey)
							buttons |= kShift;
						if (modifiers & optionKey)
							buttons |= kAlt;
						if (modifiers & controlKey)
							buttons |= kApple;
					}
					//SetUserFocusWindow (window);
					//AdvanceKeyboardFocus (window);
					//SetKeyboardFocus (window, frame->controlRef, kControlFocusNextPart);
					WindowAttributes windowAttributes;
					GetWindowAttributes (window, &windowAttributes);
					Point point = {(short)hipoint.y, (short)hipoint.x};
					if (eventKind == kEventControlClick && !(windowAttributes & kWindowCompositingAttribute))
						QDGlobalToLocalPoint (GetWindowPort (window), &point);
					CDrawContext* context = frame->createDrawContext ();
					CPoint p (point.h, point.v);
					if (!(windowAttributes & kWindowCompositingAttribute))
						p.offset (-context->offsetScreen.x, -context->offsetScreen.y);
					frame->mouse (context, p, buttons);
					context->forget ();
					result = noErr;
					break;
				}
				case kEventControlGetOptimalBounds:
				{
					HIRect optimalBounds = { {0, 0}, { frame->getWidth (), frame->getHeight ()}};
					SetEventParameter (inEvent, kEventParamControlOptimalBounds, typeHIRect, sizeof (HIRect), &optimalBounds);
					result = noErr;
					break;
				}
				case kEventControlGetFocusPart:
				{
					if (hiToolboxAllowFocusChange)
					{
						ControlPartCode code = frame->hasFocus ? 127 : kControlFocusNoPart;
						SetEventParameter (inEvent, kEventParamControlPart, typeControlPartCode, sizeof (ControlPartCode), &code);
						result = noErr;
					}
					break;
				}
				case kEventControlSetFocusPart:
				{
					if (hiToolboxAllowFocusChange)
					{
						ControlPartCode code;
						GetEventParameter (inEvent, kEventParamControlPart, typeControlPartCode, NULL, sizeof (ControlPartCode), NULL, &code);
						if (code == kControlFocusNoPart)
						{
							frame->hasFocus = false;
							frame->setFocusView (NULL);
						}
						else
						{
							bool anfResult = false;
							if (code == kControlFocusNextPart)
								anfResult = frame->advanceNextFocusView (frame->pFocusView);
							else if (code == kControlFocusPrevPart)
								anfResult = frame->advanceNextFocusView (frame->pFocusView, true);
							if (anfResult)
							{
								frame->hasFocus = true;
								code = 127;
							}
							else
							{
								frame->hasFocus = false;
								code = kControlFocusNoPart;
							}
						}
						SetEventParameter (inEvent, kEventParamControlPart, typeControlPartCode, sizeof (code), &code);
						result = noErr;
					}
					break;
				}
				case kEventControlDragEnter:
				{
					#if MAC_OLD_DRAG
					gEventDragWorks = true;
					#endif

					DragRef dragRef;
					if (GetEventParameter (inEvent, kEventParamDragRef, typeDragRef, NULL, sizeof (DragRef), NULL, &dragRef) == noErr)
					{
						gDragContainer = new CDragContainer (dragRef);
						
						CDrawContext* context = frame->createDrawContext ();
						VSTGUI_CPoint where;
						frame->setCursor (kCursorNotAllowed);
						frame->getMouseLocation (context, where);
						frame->onDragEnter (context, gDragContainer, where);
						context->forget ();

						bool acceptDrop = true;
						SetEventParameter (inEvent, kEventParamControlWouldAcceptDrop, typeBoolean, sizeof (bool), &acceptDrop);
					}
					result = noErr;
					break;
				}
				case kEventControlDragWithin:
				{
					if (gDragContainer)
					{
						CDrawContext* context = frame->createDrawContext ();
						VSTGUI_CPoint where;
						frame->getMouseLocation (context, where);
						frame->onDragMove (context, gDragContainer, where);
						context->forget ();
					}
					result = noErr;
					break;
				}
				case kEventControlDragLeave:
				{
					if (gDragContainer)
					{
						CDrawContext* context = frame->createDrawContext ();
						VSTGUI_CPoint where;
						frame->getMouseLocation (context, where);
						frame->onDragLeave (context, gDragContainer, where);
						frame->setCursor (kCursorDefault);
						context->forget ();
					}
					result = noErr;
					break;
				}
				case kEventControlDragReceive:
				{
					if (gDragContainer)
					{
						CDrawContext* context = frame->createDrawContext ();
						VSTGUI_CPoint where;
						frame->getMouseLocation (context, where);
						frame->onDrop (context, gDragContainer, where);
						frame->setCursor (kCursorDefault);
						context->forget ();
						gDragContainer->forget ();
						gDragContainer = 0;
					}
					result = noErr;
					break;
				}
			}
			break;
		}
		case kEventClassMouse:
		{
			switch (eventKind)
			{
				case kEventMouseWheelMoved:
				{
					UInt32 modifiers;
					HIPoint windowHIPoint;
					SInt32 wheelDelta;
					EventMouseWheelAxis wheelAxis;
					WindowRef windowRef;
					GetEventParameter (inEvent, kEventParamWindowRef, typeWindowRef, NULL, sizeof (WindowRef), NULL, &windowRef);
					GetEventParameter (inEvent, kEventParamMouseWheelAxis, typeMouseWheelAxis, NULL, sizeof (EventMouseWheelAxis), NULL, &wheelAxis);
					GetEventParameter (inEvent, kEventParamMouseWheelDelta, typeLongInteger, NULL, sizeof (SInt32), NULL, &wheelDelta);
					GetEventParameter (inEvent, kEventParamWindowMouseLocation, typeHIPoint, NULL, sizeof (HIPoint), NULL, &windowHIPoint);
					GetEventParameter (inEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof (UInt32), NULL, &modifiers);
					HIViewConvertPoint (&windowHIPoint, HIViewGetRoot (windowRef), frame->controlRef);
					CPoint p ((CCoord)windowHIPoint.x, (CCoord)windowHIPoint.y);
					CDrawContext* context = frame->createDrawContext ();
					CMouseWheelAxis axis = kMouseWheelAxisX;
					if (wheelAxis == kEventMouseWheelAxisY && !(modifiers & cmdKey))
						axis = kMouseWheelAxisY;
					frame->onWheel (context, p, axis, wheelDelta);
					context->forget ();
					result = noErr;
					break;
				}
			}
			break;
		}
		case kEventClassTextInput:
		{
			switch (eventKind)
			{
				case kEventTextInputUnicodeForKeyEvent:
				{
					// The "Standard Event Handler" of a window would return noErr even though no one has handled the key event. 
					// This prevents the "Standard Handler" to be called for this event, with the exception of the tab key as it is used for control focus changes.
					EventRef rawKeyEvent;
					GetEventParameter (inEvent, kEventParamTextInputSendKeyboardEvent, typeEventRef, NULL, sizeof (EventRef), NULL, &rawKeyEvent);
					if (rawKeyEvent)
					{
						UInt32 keyCode = 0;
						GetEventParameter (rawKeyEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof (UInt32), NULL, &keyCode);
						if (keyCode == keyTable[VKEY_TAB+1])
							return result;
					}
					result = eventPassToNextTargetErr;
					break;
				}
			}
			break;
		}
		case kEventClassKeyboard:
		{
			if (frame->hasFocus)
			{
				switch (eventKind)
				{
					case kEventRawKeyDown:
					case kEventRawKeyRepeat:
					{
						// todo: make this work

						char character = 0;
						UInt32 keyCode = 0;
						UInt32 modifiers = 0;
						GetEventParameter (inEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof (char), NULL, &character);
						GetEventParameter (inEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof (UInt32), NULL, &keyCode);
						GetEventParameter (inEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof (UInt32), NULL, &modifiers);
						char scanCode = keyCode;
						VstKeyCode vstKeyCode;
						memset (&vstKeyCode, 0, sizeof (VstKeyCode));
						KeyboardLayoutRef layout;
						if (KLGetCurrentKeyboardLayout (&layout) == noErr)
						{
							const void* pKCHR = 0;
							KLGetKeyboardLayoutProperty (layout, kKLKCHRData, &pKCHR);
							if (pKCHR)
							{
								static UInt32 keyTranslateState = 0;
								vstKeyCode.character = KeyTranslate (pKCHR, keyCode, &keyTranslateState);
								if (modifiers & shiftKey)
								{
									vstKeyCode.character = toupper (vstKeyCode.character);
								}
							}
						}
						short entries = sizeof (keyTable) / (sizeof (short));
						for (int i = 0; i < entries; i += 2)
						{
							if (keyTable[i + 1] == scanCode)
							{
								vstKeyCode.virt = keyTable[i];
								vstKeyCode.character = 0;
								break;
							}
						}
						if (modifiers & cmdKey)
							vstKeyCode.modifier |= MODIFIER_CONTROL;
						if (modifiers & shiftKey)
							vstKeyCode.modifier |= MODIFIER_SHIFT;
						if (modifiers & optionKey)
							vstKeyCode.modifier |= MODIFIER_ALTERNATE;
						if (modifiers & controlKey)
							vstKeyCode.modifier |= MODIFIER_COMMAND;
						if (frame->onKeyDown (vstKeyCode) != -1)
							result = noErr;
						
						break;
					}
				}
			}
			break;
		}
	}
	return result;
}

// code from CarbonSketch Example Code
#define	kGenericRGBProfilePathStr       "/System/Library/ColorSync/Profiles/Generic RGB Profile.icc"

class QuartzStatics
{
public:
	//-----------------------------------------------------------------------------
	QuartzStatics ()
	: genericRGBColorSpace (0)
	{
		CreateGenericRGBColorSpace ();
        CFBundleRef coregraphicsBundle = CFBundleGetBundleWithIdentifier (CFSTR("com.apple.CoreGraphics"));
        if (coregraphicsBundle)
        {
            _CGImageCreateWithImageInRect = (CGImageCreateWithImageInRectProc)CFBundleGetFunctionPointerForName (coregraphicsBundle, CFSTR("CGImageCreateWithImageInRect"));
            _CGContextStrokeLineSegments = (CGContextStrokeLineSegmentsProc)CFBundleGetFunctionPointerForName (coregraphicsBundle, CFSTR("CGContextStrokeLineSegments"));
        }
	}

	//-----------------------------------------------------------------------------
	~QuartzStatics ()
	{
		// we don't want to leak ;-)
		CGColorSpaceRelease (genericRGBColorSpace);

		if (bmpGI)
			CloseComponent (bmpGI);
		if (pngGI)
			CloseComponent (pngGI);
		if (jpgGI)
			CloseComponent (jpgGI);
		if (pictGI)
			CloseComponent (pictGI);
		bmpGI = 0;
		pngGI = 0;
		jpgGI = 0;
		pictGI = 0;
	}
	
	inline CGColorSpaceRef getGenericRGBColorSpace () { return genericRGBColorSpace; }

protected:
	//-----------------------------------------------------------------------------
	CMProfileRef OpenGenericProfile(void)
	{
		CMProfileLocation 	loc;
		CMProfileRef cmProfile;
			
		loc.locType = cmPathBasedProfile;
		strcpy(loc.u.pathLoc.path, kGenericRGBProfilePathStr);
	
		if (CMOpenProfile(&cmProfile, &loc) != noErr)
			cmProfile = NULL;
		
	    return cmProfile;
	}

	//-----------------------------------------------------------------------------
	void CreateGenericRGBColorSpace(void)
	{
		CMProfileRef genericRGBProfile = OpenGenericProfile();
	
		if (genericRGBProfile)
		{
			genericRGBColorSpace = CGColorSpaceCreateWithPlatformColorSpace(genericRGBProfile);
			
			// we opened the profile so it is up to us to close it
			CMCloseProfile(genericRGBProfile); 
		}
		if (genericRGBColorSpace == NULL)
			genericRGBColorSpace = CGColorSpaceCreateDeviceRGB ();
	}

	CGColorSpaceRef genericRGBColorSpace;
};

static QuartzStatics _gQuartzStatics;

inline CGColorSpaceRef GetGenericRGBColorSpace ()
{
	return _gQuartzStatics.getGenericRGBColorSpace ();
}

END_NAMESPACE_VSTGUI
#endif

#endif

