summaryrefslogtreecommitdiff
path: root/vendor/vstsdk2.4/vstgui.sf/vstgui/vstgui.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/vstsdk2.4/vstgui.sf/vstgui/vstgui.cpp')
-rw-r--r--vendor/vstsdk2.4/vstgui.sf/vstgui/vstgui.cpp9851
1 files changed, 9851 insertions, 0 deletions
diff --git a/vendor/vstsdk2.4/vstgui.sf/vstgui/vstgui.cpp b/vendor/vstsdk2.4/vstgui.sf/vstgui/vstgui.cpp
new file mode 100644
index 0000000..9375e6f
--- /dev/null
+++ b/vendor/vstsdk2.4/vstgui.sf/vstgui/vstgui.cpp
@@ -0,0 +1,9851 @@
+//-----------------------------------------------------------------------------
+// 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
+