mass rename and rebranding from xwt to ibex - fixed to use ixt files
[org.ibex.core.git] / src / org / ibex / plat / Darwin.cc
diff --git a/src/org/ibex/plat/Darwin.cc b/src/org/ibex/plat/Darwin.cc
new file mode 100644 (file)
index 0000000..7adf0ee
--- /dev/null
@@ -0,0 +1,1284 @@
+// Copyright 2003 Adam Megacz, see the COPYING file for licensing [LGPL]
+// Authors: Brian Alliet and Evan Jones
+#ifndef __APPLE_CC__
+#define FSF_GCC
+#define __APPLE_CC__
+#else
+#define APPLE_GCC
+#endif
+
+#define __private_extern__
+#include <mach-o/dyld.h>
+
+#include "POSIX.cc"
+#include "OpenGL.cc"
+
+#include <java/lang/Object.h>
+#include <java/lang/Error.h>
+
+#include <org/ibex/plat/Darwin.h>
+#include <org/ibex/plat/Darwin$CarbonSurface.h>
+#include <org/ibex/plat/Darwin$GLCarbonSurface.h>
+#include <org/ibex/plat/Darwin$GLCarbonPixelBuffer.h>
+#include <org/ibex/plat/Darwin$CarbonMessage.h>
+#include <org/ibex/plat/Darwin$CarbonOpenGL.h>
+#include <org/ibex/plat/Darwin$FileDialogHelper.h>
+#include <org/ibex/plat/GCJ$Retainer.h>
+#include <org/ibex/HTTP$Proxy.h>
+#include <org/ibex/util/Semaphore.h>
+
+#include <stdlib.h>
+#include <pthread.h>
+
+#include "DarwinCarbonHeaders.h"
+
+#define Ibex_CARBON_NO_BUNDLE_HACK
+#ifdef Ibex_CARBON_NO_BUNDLE_HACK
+extern "C" {
+    OSErr CPSEnableForegroundOperation(ProcessSerialNumber *psn);
+    OSErr CPSSetFrontProcess(ProcessSerialNumber *psn);
+}
+#endif
+
+static const mach_header* CarbonHandle = NULL;
+static const mach_header* AGLHandle = NULL;
+static const mach_header* SCHandle = NULL;
+#define CARBON_LIBRARY_PATH "/System/Library/Frameworks/Carbon.framework/Versions/A/Carbon"
+#define AGL_LIBRARY_PATH "/System/Library/Frameworks/AGL.framework/Versions/A/AGL"
+#define SC_LIBRARY_PATH "/System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration"
+
+static void* dlsym(char* symbol) {
+  if (CarbonHandle == NULL) CarbonHandle = NSAddImage(CARBON_LIBRARY_PATH, NSADDIMAGE_OPTION_NONE);
+  if (AGLHandle == NULL) AGLHandle = NSAddImage(AGL_LIBRARY_PATH, NSADDIMAGE_OPTION_NONE);
+  if (SCHandle == NULL) SCHandle = NSAddImage(SC_LIBRARY_PATH, NSADDIMAGE_OPTION_NONE);
+  void* ret = NSAddressOfSymbol(NSLookupSymbolInImage(CarbonHandle, symbol,
+                                                      NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
+  if (ret == NULL) ret = NSAddressOfSymbol(NSLookupSymbolInImage(AGLHandle, symbol,
+                                                                 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
+  if (ret == NULL) ret = NSAddressOfSymbol(NSLookupSymbolInImage(SCHandle, symbol,
+                                                                 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
+  /*printf("linking symbol %s to address %x\n", symbol, ret);
+  fflush(stdout);*/
+  return ret;
+}
+
+#define declare_weak(symbol) typeof(symbol) *symbol##_weak = NULL
+#define WC(func) \
+    (*((func##_weak != NULL) ? func##_weak : func##_weak = (typeof(func##_weak))dlsym("_" #func)))
+
+declare_weak(GetRegionBounds);
+declare_weak(RegisterToolboxObjectClass);
+declare_weak(GetWindowProperty);
+declare_weak(SetWindowProperty);
+declare_weak(CreateCustomWindow);
+declare_weak(InstallWindowContentPaintProc);
+declare_weak(AEGetNthPtr);
+declare_weak(CFArrayGetCount);
+declare_weak(CFArrayGetTypeID);
+declare_weak(CFArrayGetValueAtIndex);
+declare_weak(CFDictionaryGetValue);
+declare_weak(CFGetTypeID);
+declare_weak(CFNumberGetTypeID);
+declare_weak(CFNumberGetValue);
+declare_weak(CFRelease);
+declare_weak(CFStringCompare);
+declare_weak(CFStringCreateWithCString);
+declare_weak(CFStringCreateWithCharacters);
+declare_weak(CFStringGetCharacters);
+declare_weak(CFStringGetLength);
+declare_weak(CFStringGetTypeID);
+declare_weak(CFURLCopyScheme);
+declare_weak(CFURLCreateWithString);
+declare_weak(CGDisplayPixelsHigh);
+declare_weak(CGDisplayPixelsWide);
+declare_weak(CallNextEventHandler);
+declare_weak(CollapseWindow);
+declare_weak(ConstrainWindowToScreen);
+declare_weak(CreateEvent);
+declare_weak(CreateNewWindow);
+declare_weak(DisposeEventHandlerUPP);
+declare_weak(DisposeNavEventUPP);
+declare_weak(DisposeWindow);
+declare_weak(ExitToShell);
+declare_weak(FSRefMakePath);
+declare_weak(FrontWindow);
+declare_weak(Gestalt);
+declare_weak(GetApplicationEventTarget);
+declare_weak(GetCurrentProcess);
+declare_weak(GetCurrentScrap);
+declare_weak(GetEventClass);
+declare_weak(GetEventKind);
+declare_weak(GetEventParameter);
+declare_weak(GetMainEventQueue);
+declare_weak(GetScrapFlavorData);
+declare_weak(GetScrapFlavorSize);
+declare_weak(GetWindowBounds);
+declare_weak(GetWindowEventTarget);
+declare_weak(GetWindowPort);
+declare_weak(HideWindow);
+declare_weak(InstallEventHandler);
+declare_weak(IsWindowCollapsed);
+declare_weak(LSOpenCFURLRef);
+declare_weak(NavCreateGetFileDialog);
+declare_weak(NavCreatePutFileDialog);
+declare_weak(NavDialogDispose);
+declare_weak(NavDialogGetReply);
+declare_weak(NavDialogGetUserAction);
+declare_weak(NavDialogRun);
+declare_weak(NavDisposeReply);
+declare_weak(NavGetDefaultDialogCreationOptions);
+declare_weak(NewEventHandlerUPP);
+declare_weak(NewNavEventUPP);
+declare_weak(PostEventToQueue);
+declare_weak(PutScrapFlavor);
+declare_weak(QuitApplicationEventLoop);
+declare_weak(ReleaseEvent);
+declare_weak(RunApplicationEventLoop);
+declare_weak(SCDynamicStoreCopyProxies);
+declare_weak(SelectWindow);
+declare_weak(SendBehind);
+declare_weak(SetEventParameter);
+declare_weak(SetThemeCursor);
+declare_weak(SetWindowBounds);
+declare_weak(SetWindowResizeLimits);
+declare_weak(SetWindowTitleWithCFString);
+declare_weak(ShowWindow);
+declare_weak(ZoomWindowIdeal);
+declare_weak(__CFStringMakeConstantString);
+declare_weak(aglChoosePixelFormat);
+declare_weak(aglCreateContext);
+declare_weak(aglDestroyContext);
+declare_weak(aglSetCurrentContext);
+declare_weak(aglSetDrawable);
+declare_weak(aglSurfaceTexture);
+declare_weak(aglUpdateContext);
+declare_weak(CPSEnableForegroundOperation);
+declare_weak(CPSSetFrontProcess);
+declare_weak(kCFAllocatorDefault);
+declare_weak(NewWindowPaintUPP);
+
+#define GetWindowEventTarget WC(GetWindowEventTarget)
+#define InstallEventHandler WC(InstallEventHandler)
+#define __CFStringMakeConstantString WC(__CFStringMakeConstantString)
+
+using namespace org::ibex::plat;
+using gnu::gcj::RawData;
+using org::ibex::util::Semaphore;
+using java::lang::Object;
+
+namespace org { namespace ibex { namespace plat {
+
+
+#pragma mark ----- Blit Locks ------
+static pthread_mutex_t blit_mutex;
+static pthread_cond_t blit_cond;
+
+static inline void blit_lock() { if(pthread_mutex_lock(&blit_mutex) != 0) abort(); }
+static inline void blit_unlock() { if(pthread_mutex_unlock(&blit_mutex) != 0) abort(); }
+static inline void blit_wait() { if(pthread_cond_wait(&blit_cond,&blit_mutex) != 0) abort(); }
+static inline void blit_signal() { if(pthread_cond_signal(&blit_cond) != 0) abort(); }
+
+void Darwin$CarbonSurface::blitLock() { blit_lock(); }
+void Darwin$CarbonSurface::blitUnlock() { blit_unlock(); }
+void Darwin$CarbonSurface::blitWait() { blit_wait(); }
+
+
+template <bool CHECK> static inline int CompileTimeCheck() { const int something_is_wrong=1; something_is_wrong++; return 0; }
+template <> static inline int CompileTimeCheck<true>() { return 0; }
+const static int unichar_check = CompileTimeCheck<sizeof(jchar)==sizeof(UniChar)>();
+
+static void funcFailed(const char *func,int r);
+static inline void funcFailed(const char *func) { funcFailed(func,-1); }
+
+static inline void checkStatus(OSStatus r, char *func) { if(r != noErr) funcFailed(func,r); }
+static inline void checkStatus(GLboolean b, char *func) { if(!b) funcFailed(func,-1); }
+static inline void checkStatus(void *p, char *func) { if(!p) funcFailed(func,-1); }
+
+jstring cfStringToJString(CFStringRef s) {
+    CFIndex length = WC(CFStringGetLength)(s);
+    CFRange range = CFRangeMake(0,length);
+    jstring js = JvAllocString(length);
+    UniChar *buf = (UniChar*)JvGetStringChars(js);
+    WC(CFStringGetCharacters)(s,range,buf);
+    return js;
+}
+
+#pragma mark ------ SmartCFString ------
+class SmartCFString {
+    private:
+        CFStringRef p;
+        void release() { if(p) WC(CFRelease)(p); }
+        void checkNull() { if(!p) funcFailed("CFString function"); }
+    public:
+        // Constructors
+        SmartCFString() : p(0) { }
+        SmartCFString(const char *s) : p(0) { *this = s; }
+        SmartCFString(jstring js) : p(0) { *this = js; }
+        SmartCFString(CFStringRef cf) : p(0) { *this = cf; }
+        // Destructor
+        ~SmartCFString() { release(); }
+        // Assignment
+        SmartCFString& operator= (const char *s) {
+            release();
+            if(!s) s = "(null)";
+            p = WC(CFStringCreateWithCString)(WC(kCFAllocatorDefault),s,kCFStringEncodingISOLatin1);
+            checkNull();
+            return *this;
+        }
+        SmartCFString& operator= (jstring js) {
+            if(!js) return *this = "(null)";
+            release();
+            UniChar *buf = (UniChar*) JvGetStringChars(js);
+            CFIndex length = js->length();
+            p = WC(CFStringCreateWithCharacters)(WC(kCFAllocatorDefault),buf,length);
+            checkNull();
+            return *this;
+        }
+        SmartCFString& operator= (CFStringRef cf) {
+            if(cf == NULL) return *this = "(null)";
+            release();
+            p = cf;
+            return *this;
+        }
+        operator CFStringRef() { return p; }
+        operator jstring() { return getJString(); }
+        
+        jstring getJString() { return cfStringToJString(p); }
+        
+        bool equals(const char *s) {
+            SmartCFString cfs(s);
+            return equals(cfs);
+        }
+        
+        bool equals(CFStringRef cfs) {
+            return WC(CFStringCompare)(p,cfs,0) == kCFCompareEqualTo;
+        }
+};
+
+// CHECKME: Is just making up your own four char codes really correct?
+const static UInt32 kEventClassCarbonMessage = 'ibexa';
+const static UInt32 kEventCarbonMessage = 'ibexb';
+const static UInt32 kEventParamCarbonMessage = 'ibexc';
+
+static OSStatus carbonMessageEventHandler(EventHandlerCallRef handler, EventRef e, void *userData);
+static EventHandlerUPP carbonMessageEventHandlerUPP;
+
+static void fileDialogEventHandler(NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, void *userData);
+static NavEventUPP fileDialogEventHandlerUPP;
+
+static OSStatus windowEventHandler(EventHandlerCallRef handler, EventRef e, void *userData);
+static EventHandlerUPP windowEventHandlerUPP;
+
+static OSStatus paintProc(GDHandle device,GrafPtr qdContext,WindowRef window,RgnHandle inClientPaintRgn,RgnHandle outSystemPaintRgn,void *userData);
+static WindowPaintUPP paintProcUPP;
+
+jboolean Darwin::isJaguar() {
+    SInt32 version;
+    OSStatus r = WC(Gestalt)(gestaltSystemVersion, &version);
+    checkStatus(r,"Gestalt");
+    return version >= 0x1020;
+}
+
+void Darwin$CarbonMessage::natInit() {
+    OSStatus r;
+    
+    EventTypeSpec eventTypes = { kEventClassCarbonMessage, kEventCarbonMessage };
+    r = InstallEventHandler(WC(GetApplicationEventTarget)(),carbonMessageEventHandlerUPP,1,&eventTypes,NULL,NULL);
+    checkStatus(r,"InstallEventHandler");
+}
+
+void Darwin$CarbonMessage::add(Darwin$CarbonMessage *msg) {
+    EventRef event;
+    OSStatus r;
+    
+    GCJ$Retainer::retain(msg);
+
+    r = WC(CreateEvent)(WC(kCFAllocatorDefault),kEventClassCarbonMessage,kEventCarbonMessage,0,kEventAttributeNone,&event);
+    checkStatus(r,"CreateEvent");
+    r = WC(SetEventParameter)(event,kEventParamCarbonMessage,typeVoidPtr,sizeof(msg),(void*)&msg);
+    checkStatus(r,"SetEventParameter");
+    r = WC(PostEventToQueue)(WC(GetMainEventQueue)(),event,kEventPriorityHigh);
+    checkStatus(r,"PostEventToQueue");
+    WC(ReleaseEvent)(event);
+}
+
+
+static OSStatus carbonMessageEventHandler(EventHandlerCallRef handler, EventRef e, void *userData) {
+    UInt32 eKind = WC(GetEventKind)(e);
+    UInt32 eClass = WC(GetEventClass)(e);
+    OSStatus r;
+    Darwin$CarbonMessage *msg;
+    if(eClass != kEventClassCarbonMessage || eKind != kEventCarbonMessage)
+        return eventNotHandledErr;
+    r = WC(GetEventParameter)(e,kEventParamCarbonMessage,typeVoidPtr,NULL,sizeof(msg),NULL,&msg);
+    checkStatus(r,"GetEventParameter");
+    msg->perform();
+    GCJ$Retainer::release(msg);
+    return noErr;
+}
+
+
+#pragma mark ------ Utility Functions ------
+
+static void funcFailed(const char *func,int r){
+    fprintf(stderr,"%s() failed (%d)\n",func,r);
+    exit(EXIT_FAILURE);
+} 
+
+#pragma mark ------ CarbonPicture Methods ------ 
+
+#pragma mark ----- Carbon Surface Methods ----
+
+
+void Darwin$CarbonSurface::natSyncCursor(jint n) {
+    ThemeCursor c;
+    // see Carbon.java for what these numbers mean
+    switch(n) {
+        case 1: c = kThemeWatchCursor;
+        case 2: c = kThemePlusCursor;
+        case 3: c = kThemeIBeamCursor;
+        case 4: c = kThemePointingHandCursor;
+        case 5: c = kThemeOpenHandCursor;
+        case 6: c = kThemeResizeLeftRightCursor;
+        default: c = kThemeArrowCursor;
+    }
+    WC(SetThemeCursor)(c);
+}
+   
+void Darwin$CarbonSurface::natSetInvisible(jboolean b) {
+    WindowRef window = (WindowRef) rawWindowRef;
+    fprintf(stderr,"Making window %s\n",b?"invisible":"visible");
+    if(b) WC(HideWindow)(window);
+    else WC(ShowWindow)(window);
+}
+
+void Darwin$CarbonSurface::nat_setMaximized(jboolean b) {
+    WindowRef window = (WindowRef) rawWindowRef;
+    Point ideal = { 10000, 10000 };
+    OSStatus r = WC(ZoomWindowIdeal)(window,(b?inZoomOut:inZoomIn),&ideal);
+    checkStatus(r,"ZoomWindowIdeal");
+}
+
+void Darwin$CarbonSurface::nat_setMinimized(jboolean b) {
+    WindowRef window = (WindowRef) rawWindowRef;
+    if((WC(IsWindowCollapsed)(window) ? 1 : 0) == (b ? 1 : 0)) return;
+    OSStatus r = WC(CollapseWindow)(window,b);
+    checkStatus(r,"CollapseWindow");
+}
+
+void Darwin$CarbonSurface::natSetTitleBarText(jstring js) {
+    SmartCFString s = js;
+    WindowRef window = (WindowRef) rawWindowRef;
+    WC(SetWindowTitleWithCFString)(window,s);
+}
+
+void Darwin$CarbonSurface::natToBack() {
+    WindowRef window = (WindowRef) rawWindowRef;
+    WC(SendBehind)(window,NULL);
+}
+
+void Darwin$CarbonSurface::natToFront() {
+    WindowRef window = (WindowRef) rawWindowRef;
+    fprintf(stderr,"SelectWindow)()\n");
+    WC(SelectWindow)(window);
+}
+
+#pragma mark ---- Window Event Handler ----
+static const EventTypeSpec eventTypeSpecs[] = {
+    // kEventClassCommand
+    // { kEventClassCommand, ??? },
+    
+    // kEventClassWindow
+    { kEventClassWindow, kEventWindowUpdate },
+    { kEventClassWindow, kEventWindowBoundsChanged },
+    { kEventClassWindow, kEventWindowBoundsChanging },
+    { kEventClassWindow, kEventWindowActivated },
+    { kEventClassWindow, kEventWindowDeactivated },
+    { kEventClassWindow, kEventWindowZoomed },
+    { kEventClassWindow, kEventWindowCollapsed },
+    { kEventClassWindow, kEventWindowExpanded },
+    { kEventClassWindow, kEventWindowClose },
+    { kEventClassWindow, kEventWindowClosed },
+    { kEventClassWindow, kEventWindowDrawFrame },
+    { kEventClassWindow, kEventWindowDrawPart },
+
+    // kEventClassControl
+    { kEventClassControl, kEventControlApplyBackground },
+    
+    // kEventClassKeyboard
+    { kEventClassKeyboard, kEventRawKeyDown },
+    { kEventClassKeyboard, kEventRawKeyRepeat },
+    { kEventClassKeyboard, kEventRawKeyUp },
+    { kEventClassKeyboard, kEventRawKeyModifiersChanged },
+    
+    // kEventClassMouse
+    { kEventClassMouse, kEventMouseDown },
+    { kEventClassMouse, kEventMouseUp },
+    { kEventClassMouse, kEventMouseMoved },
+    { kEventClassMouse, kEventMouseDragged },
+    { kEventClassMouse, kEventMouseWheelMoved },
+};
+    
+static OSStatus windowEventHandler(EventHandlerCallRef handler, EventRef e, void *userData) {
+  Darwin$CarbonSurface *surface = (Darwin$CarbonSurface*)userData;
+  UInt32 eKind = WC(GetEventKind)(e);
+  UInt32 eClass = WC(GetEventClass)(e);
+  OSStatus r;
+  char* ec = (char*)&eClass;
+  if (surface == NULL) return eventNotHandledErr;
+    
+
+    switch(eClass) {
+        case kEventClassCommand:
+            switch(eKind) {
+                // TODO: handle menu items
+            }
+            break;
+        case kEventClassKeyboard:
+            switch(eKind) {
+                case kEventRawKeyDown:
+                case kEventRawKeyRepeat: 
+                case kEventRawKeyUp: {
+                    UInt32 keyCode;
+                    jstring js;
+                    
+                    r = WC(GetEventParameter)(e,kEventParamKeyCode,typeUInt32,NULL,sizeof(keyCode),NULL,&keyCode);
+                    checkStatus(r,"GetEventParameter");
+                    
+                    switch(keyCode) {
+                        // These values were obtained by experimentation. I can't find any constants for them
+                        // in the header files
+                        case 126: js = JvNewStringLatin1("up"); break;
+                        case 125: js = JvNewStringLatin1("down"); break;
+                        case 124: js = JvNewStringLatin1("right"); break;
+                        case 123: js = JvNewStringLatin1("left"); break;
+                        case 122: js = JvNewStringLatin1("f1"); break;
+                        case 120: js = JvNewStringLatin1("f2"); break;
+                        case 99:  js = JvNewStringLatin1("f3"); break;
+                        case 118: js = JvNewStringLatin1("f4"); break;
+                        case 96:  js = JvNewStringLatin1("f5"); break;
+                        case 97:  js = JvNewStringLatin1("f6"); break;
+                        case 98:  js = JvNewStringLatin1("f7"); break;
+                        case 100: js = JvNewStringLatin1("f8"); break;
+                        case 101: js = JvNewStringLatin1("f9"); break;
+                        case 109: js = JvNewStringLatin1("f10"); break;
+                        case 103: js = JvNewStringLatin1("f11"); break;
+                        case 111: js = JvNewStringLatin1("f12"); break;
+                        case 105: js = JvNewStringLatin1("f13"); break;
+                        case 114: js = JvNewStringLatin1("insert"); break;
+                        case 117: js = JvNewStringLatin1("delete"); break;
+                        case 116: js = JvNewStringLatin1("page_up"); break;
+                        case 121: js = JvNewStringLatin1("page_down"); break;
+                        case 115: js = JvNewStringLatin1("home"); break;
+                        case 119: js = JvNewStringLatin1("end"); break;
+                        case 71:  js = JvNewStringLatin1("num_lock"); break;
+                        case 53:  js = JvNewStringLatin1("escape"); break;
+                        case 51:  js = JvNewStringLatin1("back_space"); break;
+                        case 36:  js = JvNewStringLatin1("enter"); break;
+                        case 48:  js = JvNewStringLatin1("tab"); break;
+                        case 76:  js = JvNewStringLatin1("enter"); break; // number pad enter
+                        default: {                            
+                            UInt32 size;
+                            UInt32 modifiers = surface->modifiers;
+                            r = WC(GetEventParameter)(e,kEventParamKeyUnicodes,typeUnicodeText,NULL,0,&size,NULL);
+                            checkStatus(r,"GetEventParameter");
+                            if(size == 0 || (modifiers & controlKey && size>sizeof(UniChar))) return eventNotHandledErr;
+                            
+                            js = JvAllocString(size/sizeof(UniChar));
+                            UniChar *buf = (UniChar*)JvGetStringChars(js);
+                            r = WC(GetEventParameter)(e,kEventParamKeyUnicodes,typeUnicodeText,NULL,size,NULL,buf);
+                            checkStatus(r,"GetEventParameter");
+
+                            if(!buf[0]) return eventNotHandledErr; // shouldn't happen
+                            // odd, when the ctrl key is pressed a-"`" become 1-31, this brings them back to the corect values
+                            if(modifiers & controlKey && buf[0] < 32) buf[0] += 0x60;
+                            break;
+                        }
+                    }
+                    
+                    if(eKind == kEventRawKeyUp)
+                        surface->KeyReleased(js);
+                    else
+                        surface->KeyPressed(js);
+                    return noErr;
+                }
+                case kEventRawKeyModifiersChanged: {
+                    const static struct {
+                        UInt32 mask;
+                        jstring ibexKey;
+                    } modifiersTable[] = {
+                        { shiftKey,  JvNewStringLatin1("shift")     },
+                        { alphaLock, JvNewStringLatin1("caps_lock") },
+                        { controlKey,  JvNewStringLatin1("control")   },
+                        { optionKey,  JvNewStringLatin1("alt")       },
+                        { kEventKeyModifierNumLockMask,  JvNewStringLatin1("num_lock")  },
+                        { 0, 0 }                    
+                    };
+                    
+                    UInt32 oldModifiers = (UInt32) surface->modifiers;
+                    UInt32 newModifiers;
+                    r = WC(GetEventParameter)(e,kEventParamKeyModifiers,typeUInt32,NULL,sizeof(newModifiers),NULL,&newModifiers);
+                    checkStatus(r,"GetEventParameter");
+                    surface->modifiers = (jint) newModifiers;
+                    UInt32 changedModifiers = oldModifiers ^ newModifiers;
+                    
+                    for(int i=0;modifiersTable[i].mask;i++) {
+                        UInt32 mask = modifiersTable[i].mask;
+                        if(!(changedModifiers & mask)) continue;
+                        if(newModifiers & mask)
+                            surface->KeyPressed(modifiersTable[i].ibexKey);
+                        else
+                            surface->KeyReleased(modifiersTable[i].ibexKey);
+                    }
+                    return noErr;
+                }
+            }
+            break;
+        case kEventClassMouse:
+            // The default handler gets first dibs on mouse events
+            // (this catches the titlebar, resize box, etc)
+            r = WC(CallNextEventHandler)(handler, e);
+            if(r != eventNotHandledErr && eKind != kEventMouseMoved && eKind != kEventMouseDragged) return r;
+            
+            switch(eKind) {
+                case kEventMouseMoved:
+                case kEventMouseDragged: {
+                    WindowRef window = (WindowRef) surface->rawWindowRef;
+                    Point p;
+                    Rect rect;
+                    
+                    r = WC(GetEventParameter)(e,kEventParamMouseLocation,typeQDPoint,NULL,sizeof(p),NULL,&p);
+                    checkStatus(r,"GetEventParameter");
+                    r = WC(GetWindowBounds)(window,kWindowContentRgn,&rect);
+                    checkStatus(r,"GetWindowBounds");
+                    surface->Move(p.h-rect.left,p.v-rect.top);
+                    return noErr;
+                }
+                case kEventMouseDown: 
+                case kEventMouseUp: {
+                    EventMouseButton button;
+                    UInt32 clickCount;
+                    jint ibexButton;
+                    r = WC(GetEventParameter)(e,kEventParamMouseButton,typeMouseButton,NULL,sizeof(button),NULL,&button);
+                    checkStatus(r,"GetEventParameter");
+                    r = WC(GetEventParameter)(e,kEventParamClickCount,typeUInt32,NULL,sizeof(clickCount),NULL,&clickCount);
+                    checkStatus(r,"GetEventParameter");
+                    
+                    switch(button) {
+                        case kEventMouseButtonPrimary:   ibexButton = 1; break;
+                        case kEventMouseButtonSecondary: ibexButton = 2; break;
+                        case kEventMouseButtonTertiary:  ibexButton = 3; break;
+                        default: return noErr;
+                    }
+                    if(eKind == kEventMouseDown) {
+                        surface->Press(ibexButton);
+                    } else {
+                        surface->Release(ibexButton);
+                        while(clickCount > 1) {
+                            surface->DoubleClick(ibexButton);
+                            clickCount-=2;
+                        }
+                        if(clickCount) surface->Click(ibexButton);
+                    }
+                    return noErr;
+                }
+                case kEventMouseWheelMoved: {
+                    EventMouseWheelAxis axis;
+                    SInt32 delta;
+                    r = WC(GetEventParameter)(e,kEventParamMouseWheelAxis,typeMouseWheelAxis,NULL,sizeof(axis),NULL,&axis);
+                    checkStatus(r,"GetEventParameter");
+                    if(axis != kEventMouseWheelAxisY) break;
+                    r = WC(GetEventParameter)(e,kEventParamMouseWheelDelta,typeSInt32,NULL,sizeof(delta),NULL,&delta);
+                    checkStatus(r,"GetEventParameter");
+                    fprintf(stderr,"kEventMouseWheelMoved: delta: %d",delta);
+                    // surface->MouseWheelMoved(...) IMPROVMENT: mouse wheel support in ibex
+                    return noErr;
+                }
+            }
+            break;
+        
+        case kEventClassWindow: {
+            WindowRef window;
+            r = WC(GetEventParameter)(e,kEventParamDirectObject,typeWindowRef,NULL,sizeof(window),NULL,&window);
+            checkStatus(r,"kEventClassWindow/WC(GetEventParameter");
+            
+            if((RawData*)window != surface->rawWindowRef) Darwin::abort(JvNewStringLatin1("window != surface->window"));
+            
+            switch(eKind) {
+                case kEventWindowBoundsChanging: {
+                    UInt32 attr;
+                    Rect rect;
+                    
+                    r = WC(GetEventParameter)(e,kEventParamAttributes,typeUInt32,NULL,sizeof(attr),NULL,&attr);
+                    checkStatus(r,"kEventWindowBoundsChanged/GetEventParameter");
+                    
+                    r = WC(GetEventParameter)(e,kEventParamCurrentBounds,typeQDRectangle,NULL,sizeof(rect),NULL,&rect);
+                    checkStatus(r,"kEventWindowBoundsChanging/GetEventParameter"); 
+                    
+                    if(attr & kWindowBoundsChangeSizeChanged) {
+                        jint w = rect.right-rect.left;
+                        jint h = rect.bottom-rect.top;
+                            
+                        blit_lock();
+                        
+                        surface->winWidth = w;
+                        surface->winHeight = h;
+                        surface->pendingResize = true;
+                        surface->needsReshape();
+                            
+                        blit_unlock();
+    
+                        surface->SizeChange(w,h);
+                        if(attr & kWindowBoundsChangeUserResize && surface->maximized)
+                                surface->Maximized(false);
+                    }
+                    
+                    if(attr & kWindowBoundsChangeOriginChanged) {
+                        surface->PosChange(rect.left,rect.top);
+                    }
+                    
+                    return noErr;
+                }
+                case kEventWindowBoundsChanged: {
+                    UInt32 attr;
+                    r = WC(GetEventParameter)(e,kEventParamAttributes,typeUInt32,NULL,sizeof(attr),NULL,&attr);
+                    checkStatus(r,"kEventWindowBoundsChanged/GetEventParameter");
+                    
+                    if(attr & kWindowBoundsChangeSizeChanged) {
+                        blit_lock();
+
+                        surface->pendingResize = false;
+                        
+                        blit_signal();
+                        blit_unlock();
+                    }
+                    return noErr;
+                }
+                case kEventWindowActivated:
+                case kEventWindowDeactivated: {
+                    surface->Focused(eKind == kEventWindowActivated);
+                    return noErr;
+                }
+                case kEventWindowZoomed: {
+                    surface->Maximized(true);
+                    return noErr;
+                }
+                case kEventWindowCollapsed: {
+                    surface->Minimized(true);
+                    return noErr;
+                }
+                case kEventWindowExpanded: {
+                    surface->Minimized(false);
+                    return noErr;
+                }
+                case kEventWindowClose: {
+                    surface->Close();
+                    return noErr;
+                }
+                case kEventWindowClosed: {
+                    GCJ$Retainer::release(surface);
+                    return noErr;
+                }
+                case kEventWindowUpdate: {
+                    fprintf(stderr,"kEventWindowUpdate: Should not be here\n");
+                    abort();
+                }
+            }
+        }
+        break;
+    }
+    return eventNotHandledErr;
+}
+
+static OSStatus paintProc (
+   GDHandle device,
+   GrafPtr qdContext,
+   WindowRef window,
+   RgnHandle inClientPaintRgn,
+   RgnHandle outSystemPaintRgn,
+   void *userData
+) {
+    Darwin$CarbonSurface *surface = (Darwin$CarbonSurface*) userData;
+    Rect rect;
+    WC(GetRegionBounds)(inClientPaintRgn, &rect);
+    surface->Dirty(rect.left,rect.top,rect.right-rect.left,rect.bottom-rect.top);
+    return noErr;
+}
+
+void Darwin$CarbonSurface::natInit(jboolean framed) {
+    WindowRef window;
+    Rect rect;
+    WindowClass wc = framed ? kDocumentWindowClass : kPlainWindowClass;
+    // FIXME: unframed windows should appear in the window menu
+    // This probably needs a hack similar to whats in Cocoa.mm
+    WindowAttributes attr =  kWindowStandardHandlerAttribute|
+      (framed ? kWindowInWindowMenuAttribute|kWindowStandardDocumentAttributes|kWindowLiveResizeAttribute : 0);
+    OSStatus r;
+    rect.top = rect.left = 0;
+    rect.bottom = rect.right = 10;
+    winWidth = winHeight = 10;
+    
+    r = WC(CreateNewWindow)(wc, attr, &rect, &window);
+    checkStatus(r,"CreateNewWindow");
+
+    rawWindowRef = (RawData*) window;
+
+    GCJ$Retainer::retain(this); // Need to account for the EventHandlers pointer to us
+    
+    r = InstallWindowEventHandler(window,windowEventHandlerUPP,sizeof(eventTypeSpecs)/sizeof(EventTypeSpec),eventTypeSpecs,this,NULL);
+    checkStatus(r,"InstallWindowEventHandler");
+
+    r = WC(InstallWindowContentPaintProc)(window,paintProcUPP,kWindowPaintProcOptionsNone,this);
+    checkStatus(r,"InstallWindowContentPaintProc");
+    
+    WC(ShowWindow)(window);        
+}
+
+void Darwin$CarbonSurface::natDispose() {
+    WindowRef window = (WindowRef) rawWindowRef;
+    WC(DisposeWindow)(window);
+}
+
+void Darwin$CarbonSurface::natSetIcon(org::ibex::Picture *_p) {
+}
+
+void Darwin$CarbonSurface::natSetLocation() {
+    WindowRef window = (WindowRef) rawWindowRef;
+    Rect rect;
+    jint x = root->x;
+    jint y = root->y;
+    OSStatus r = WC(GetWindowBounds)(window,kWindowStructureRgn,&rect);
+    checkStatus(r,"GetWindowBounds");
+    rect.bottom = y + (rect.bottom - rect.top);
+    rect.right = x + (rect.right - rect.left);
+    rect.top = y;
+    rect.left = x;
+    r = WC(SetWindowBounds)(window,kWindowStructureRgn,&rect);
+    checkStatus(r,"SetWindowBounds");
+    r = WC(ConstrainWindowToScreen)(window,kWindowStructureRgn,kWindowConstrainMoveRegardlessOfFit,NULL,NULL);
+    checkStatus(r,"ConstrainWindowToScreen");
+}
+
+void Darwin$CarbonSurface::natSetSize(jint w, jint h) {
+    WindowRef window = (WindowRef) rawWindowRef;
+    Rect rect;
+    OSStatus r = WC(GetWindowBounds)(window,kWindowContentRgn,&rect);
+    checkStatus(r,"GetWindowBounds");
+    rect.bottom = rect.top + h;
+    rect.right = rect.left + w;
+    r = WC(SetWindowBounds)(window,kWindowContentRgn,&rect);
+    checkStatus(r,"SetWindowBounds");
+    r = WC(ConstrainWindowToScreen)(window,kWindowStructureRgn,kWindowConstrainMoveRegardlessOfFit,NULL,NULL);
+    checkStatus(r,"ConstrainWindowToScreen");
+}
+
+void Darwin$CarbonSurface::natSetLimits(jint minw, jint minh, jint maxw, jint maxh) {
+    WindowRef window = (WindowRef) rawWindowRef;
+    const int maxMax = 32767;
+    const int minMinW = 80;
+    const int minMinH = 20;
+    HISize min,max;
+    min.width  = minw > maxMax ? maxMax : (minw < minMinW ? minMinW : minw);
+    min.height = minh > maxMax ? maxMax : (minh < minMinH ? minMinH : minh);
+    max.width  = maxw > maxMax ? maxMax : (maxw < minMinW ? minMinW : maxw);
+    max.height = maxh > maxMax ? maxMax : (maxh < minMinH ? minMinH : maxh);
+    OSStatus r = WC(SetWindowResizeLimits)(window,&min,&max);
+    checkStatus(r,"SetWindowResizeLimits");
+}
+
+
+#pragma mark ------ Carbon Methods ------
+void fileDialogEventHandler(NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, void *userData) {
+    Darwin$FileDialogHelper *helper = (Darwin$FileDialogHelper*) userData;
+    NavDialogRef dialog = callBackParms->context;
+    OSStatus r;
+    switch(callBackSelector) {
+        case kNavCBUserAction: {
+            NavUserAction action = WC(NavDialogGetUserAction)(dialog);
+            if(action == kNavUserActionNone || action == kNavUserActionCancel) {
+                helper->fileName = 0;
+            } else {
+                NavReplyRecord reply;
+                r = WC(NavDialogGetReply)(dialog,&reply);
+                checkStatus(r,"NavDialogGetReply");
+
+                AEKeyword keyword;
+                FSRef ref;
+                char buf[4096];
+                r = WC(AEGetNthPtr)(&reply.selection,1,typeFSRef,&keyword,NULL,&ref,sizeof(ref),NULL);
+                checkStatus(r,"AEGetNthPtr");
+                r = WC(FSRefMakePath)(&ref,(UInt8*)buf,sizeof(buf)-1);
+                checkStatus(r,"FSRefMakePath");
+                helper->fileName = JvNewStringLatin1(buf);
+                if(helper->save) helper->saveName = cfStringToJString(reply.saveFileName);
+                r = WC(NavDisposeReply)(&reply);
+                checkStatus(r,"NavDialogGetReply");
+            }
+            helper->sem->release();
+            break;
+        }
+        case kNavCBTerminate:
+            WC(NavDialogDispose)(dialog);
+            break;
+    }
+}
+
+void Darwin::natFileDialog(Darwin$FileDialogHelper *helper,jstring suggestion_, jboolean write) {
+    NavDialogRef dlg;
+    SmartCFString suggestion = suggestion_;
+    CFStringRef message = CFSTR("By selecting a file in this dialog you are giving this Ibex application permission to access that file.");
+    OSStatus r;
+    WindowRef window = WC(FrontWindow)();
+    NavDialogCreationOptions options;
+    
+    WC(NavGetDefaultDialogCreationOptions)(&options);
+    options.optionFlags =
+        (options.optionFlags|kNavAllFilesInPopup|kNavSelectAllReadableItem|kNavDontUseCustomFrame|kNavDontConfirmReplacement)
+        &~(kNavAllowStationery|kNavAllowMultipleFiles);
+    options.clientName = CFSTR("Ibex");
+    if(write)
+        options.saveFileName  = suggestion;
+    options.message = message;
+    options.modality = window ? kWindowModalityWindowModal : kWindowModalityAppModal;
+    options.parentWindow = window;
+    
+    if(write)
+        r = WC(NavCreatePutFileDialog)(&options,0,0,fileDialogEventHandlerUPP,helper,&dlg);
+    else
+        r = WC(NavCreateGetFileDialog)(&options,NULL,fileDialogEventHandlerUPP,NULL,NULL,helper,&dlg);
+    checkStatus(r,"NavCreate(Get/Put)FileDialog");
+    
+    WC(NavDialogRun)(dlg);
+}
+
+jstring Darwin::natGetClipBoard() {
+    ScrapRef scrap;
+    OSStatus r;
+    Size size,size2;
+
+    r = WC(GetCurrentScrap)(&scrap);
+    checkStatus(r,"GetCurrentScrap");
+    
+    r = WC(GetScrapFlavorSize)( scrap, kScrapFlavorTypeUnicode, &size);
+    if(r == scrapFlavorNotFoundErr) return JvNewStringLatin1("");
+    checkStatus(r,"GetScrapFlavorSize");
+    
+    unsigned int length = size/sizeof(UniChar);
+    
+    jstring js = JvAllocString(length);
+    UniChar *buf = (UniChar*) JvGetStringChars(js);
+    size2 = size;
+    r = WC(GetScrapFlavorData)(scrap,kScrapFlavorTypeUnicode,&size2,buf);
+    if(r == scrapFlavorNotFoundErr);
+    checkStatus(r,"GetScrapFlavorData");
+    if(size2 != size) return JvNewStringLatin1("");
+    
+    return js;
+}
+
+void Darwin::natSetClipBoard(jstring js) {
+    unsigned int length = js->length();
+    ScrapRef scrap;
+    OSStatus r;
+
+    r = WC(GetCurrentScrap)(&scrap);
+    checkStatus(r,"GetCurrentScrap");
+    
+    r = WC(PutScrapFlavor)(scrap,kScrapFlavorTypeUnicode,0,sizeof(UniChar)*length,JvGetStringChars(js));
+    checkStatus(r,"PutScrapFlavor");
+}
+
+HTTP$Proxy *Darwin::natDetectProxy() {
+    using org::ibex::HTTP$Proxy;
+    HTTP$Proxy *p=0;
+    CFStringRef string;
+    CFNumberRef number;
+    SmartCFString smartString;
+    CFArrayRef exceptionList;
+    int i;
+    
+    CFDictionaryRef proxyInfo = WC(SCDynamicStoreCopyProxies)(NULL);
+    if(proxyInfo == NULL) return 0;
+    
+#define doproto(proto,var) \
+    number = (CFNumberRef) WC(CFDictionaryGetValue)(proxyInfo,kSCPropNetProxies ## proto ## Enable);    \
+    if(number != NULL && WC(CFGetTypeID)(number) != WC(CFNumberGetTypeID)()) number = NULL;                 \
+    if(number && WC(CFNumberGetValue)(number,kCFNumberIntType,&i) && i) {                               \
+        string = (CFStringRef) WC(CFDictionaryGetValue)(proxyInfo, kSCPropNetProxies ## proto ## Proxy);\
+        if(string != NULL && WC(CFGetTypeID)(string) != WC(CFStringGetTypeID)()) string = NULL;             \
+        number = (CFNumberRef) WC(CFDictionaryGetValue)(proxyInfo, kSCPropNetProxies ## proto ## Port); \
+        if(number != NULL && WC(CFGetTypeID)(number) != WC(CFNumberGetTypeID)()) number = NULL;    \
+        if(string && number && WC(CFNumberGetValue)(number,kCFNumberIntType,&i) && i) {        \
+            if(!p) p = new HTTP$Proxy();                                                        \
+            p->var ## ProxyHost = cfStringToJString(string);                           \
+            p->var ## ProxyPort = i;                                                   \
+        }                                                                                  \
+    }                                                                                      
+doproto(HTTP,http)
+doproto(HTTPS,https)
+doproto(SOCKS,socks)
+#undef doproto
+
+    exceptionList = (CFArrayRef) WC(CFDictionaryGetValue)(proxyInfo,kSCPropNetProxiesExceptionsList);
+    if(exceptionList != NULL && WC(CFGetTypeID)(exceptionList) != WC(CFArrayGetTypeID)()) exceptionList = NULL;
+    if(p && exceptionList && WC(CFArrayGetCount)(exceptionList)) {
+        CFIndex count = WC(CFArrayGetCount)(exceptionList);
+        p->excluded = (JArray<java::lang::String*>*)
+            JvNewObjectArray(count,&java::lang::String::class$,0);
+        for(i=0;i<count;i++) {
+            string = (CFStringRef) WC(CFArrayGetValueAtIndex)(exceptionList,i);
+            if(string != NULL && WC(CFGetTypeID)(string) != WC(CFStringGetTypeID)()) string = NULL;
+            elements(p->excluded)[i] = string ? cfStringToJString(string) : JvNewStringLatin1("(null)");
+        }
+    }
+    WC(CFRelease)(proxyInfo);
+    
+    return p;
+/*
+    exceptionList = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesExceptionsList];
+    if(p && exceptionList && [exceptionList count]) {
+        NSLog(@"excl: %@",exceptionList);
+        p->excluded = (JArray<java::lang::String*>*)
+            JvNewObjectArray([exceptionList count],&java::lang::String::class$,0);
+        for(i=0;i<[exceptionList count];i++)
+            elements(p->excluded)[i] = [[exceptionList objectAtIndex: i] jstring];
+    }
+    return p;
+    */    
+            
+/*
+    using org::ibex::Proxy;
+    AutoARP pool;
+    Proxy *p=0;
+    NSString *host;
+    NSNumber *port;
+    NSArray *exceptionList;
+    unsigned int i;
+    NSDictionary *proxyInfo = (NSDictionary*)WC(SCDynamicStoreCopyProxies)(NULL);
+    
+    if(proxyInfo == NULL) return 0;
+    if([[proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPEnable] boolValue]) {
+        host = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPProxy];
+        port = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPPort];
+        if(host && [port intValue]) {
+            if(!p) p = new Proxy();
+            p->httpProxyHost = [host jstring];
+            p->httpProxyPort = [port intValue];
+        }
+    }
+    if([[proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPSEnable] boolValue]) {
+        host = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPSProxy];
+        port = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPSPort];
+        if(host && [port intValue]) {
+            if(!p) p = new Proxy();
+            p->httpsProxyHost = [host jstring];
+            p->httpsProxyPort = [port intValue];
+        }
+    }
+    if([[proxyInfo objectForKey: (NSString*) kSCPropNetProxiesSOCKSEnable] boolValue]) {
+        host = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesSOCKSProxy];
+        port = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesSOCKSPort];
+        if(host && [port intValue]) {
+            if(!p) p = new Proxy();
+            p->socksProxyHost = [host jstring];
+            p->socksProxyPort = [port intValue];
+        }
+    }
+   
+    exceptionList = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesExceptionsList];
+    if(p && exceptionList && [exceptionList count]) {
+        NSLog(@"excl: %@",exceptionList);
+        p->excluded = (JArray<java::lang::String*>*)
+            JvNewObjectArray([exceptionList count],&java::lang::String::class$,0);
+        for(i=0;i<[exceptionList count];i++)
+            elements(p->excluded)[i] = [[exceptionList objectAtIndex: i] jstring];
+    }
+    return p;
+*/
+}
+
+jint Darwin::cgScreenWidth() {
+    return WC(CGDisplayPixelsWide)(((CGDirectDisplayID)0));
+}
+
+jint Darwin::cgScreenHeight() {
+    return WC(CGDisplayPixelsHigh)(((CGDirectDisplayID)0));
+}
+
+void Darwin::_newBrowserWindow(jstring js) {
+    SmartCFString cfs = js;
+    CFURLRef url = WC(CFURLCreateWithString)(WC(kCFAllocatorDefault),cfs,NULL);
+    SmartCFString scheme = WC(CFURLCopyScheme)(url);
+    if(scheme.equals(CFStringRef("http")))
+        WC(LSOpenCFURLRef)(url,NULL);
+    WC(CFRelease)(url);
+}
+
+void Darwin::natInit() {     
+    OSStatus r;
+    
+    if(pthread_mutex_init(&blit_mutex,NULL) != 0) funcFailed("pthread_mutex_init");
+    if(pthread_cond_init(&blit_cond,NULL) != 0) funcFailed("pthread_cond_init");
+    
+    carbonMessageEventHandlerUPP = WC(NewEventHandlerUPP)(carbonMessageEventHandler);
+    windowEventHandlerUPP = WC(NewEventHandlerUPP)(windowEventHandler);
+    fileDialogEventHandlerUPP = WC(NewNavEventUPP)(fileDialogEventHandler);
+    paintProcUPP = WC(NewWindowPaintUPP)(paintProc);
+
+    #ifdef Ibex_CARBON_NO_BUNDLE_HACK
+    {        
+        ProcessSerialNumber currentProcess = { 0, kCurrentProcess };
+        
+        ::fprintf(stderr,"Doing Ibex_CARBON_NO_BUNDLE_HACK\n");
+        r = WC(GetCurrentProcess)(&currentProcess);
+        checkStatus(r,"GetCurrentProcess");
+        r = WC(CPSEnableForegroundOperation)( &currentProcess );
+        checkStatus(r,"CPSEnableForegroundOperation");
+        r = WC(CPSSetFrontProcess)(&currentProcess);
+        checkStatus(r,"CPSSetFrontProcess");        
+    }
+    #else
+    {
+        IBNibRef nib;
+        r = CreateNibReference(CFSTR("MainMenu"), &nib);
+        checkStatus(r,"CreateNibReference");
+        r = SetMenuBarFromNib(nib, CFSTR("MenuBar"));
+        checkStatus(r,"SetMenuBarFromNib");
+        DisposeNibReference(nib);
+        
+        // FEATURE: Install menu event handler
+    }
+    #endif
+}
+
+void Darwin::runApplicationEventLoop() {
+    WC(RunApplicationEventLoop)();
+    WC(ExitToShell)();
+}
+
+#pragma mark ------ OpenGL Functions -----
+
+void Darwin$CarbonOpenGL::activateSharedContext() {
+    AGLContext ctx = (AGLContext) rawSharedContext;
+    WC(aglSetCurrentContext)(ctx);
+}
+
+jboolean Darwin$CarbonOpenGL::initPixelFormat() {
+    GLint attr[] = {
+        AGL_NO_RECOVERY,
+        AGL_RGBA,
+        AGL_DEPTH_SIZE, 32,
+        AGL_RED_SIZE, 8,
+        AGL_GREEN_SIZE, 8,
+        AGL_RED_SIZE, 8,
+        AGL_ALPHA_SIZE, 8,
+        AGL_NONE
+    };
+    
+    rawPixelFormat = (RawData*) WC(aglChoosePixelFormat)(NULL,0,attr);
+    return rawPixelFormat != 0;
+}
+
+void Darwin$CarbonOpenGL::initSharedContext() {
+    AGLPixelFormat fmt =  (AGLPixelFormat) rawPixelFormat;
+    rawSharedContext = (RawData*) WC(aglCreateContext)(fmt,NULL);
+    checkStatus(rawSharedContext,"aglCreateContext");
+}
+
+void Darwin$GLCarbonPixelBuffer::natInit() {
+    WindowClass wc = kPlainWindowClass;
+    WindowAttributes attr = 0;
+    WindowRef window;
+    Rect rect;
+    OSStatus r;
+    AGLContext ctx,shared;
+    AGLPixelFormat fmt;
+    GLboolean b;
+    GLuint tex;
+    GLuint target;
+    
+    rect.top = rect.left = 0;
+    rect.right = width + rect.left;
+    rect.bottom = height + rect.top; 
+    
+    r = WC(CreateNewWindow)(wc,attr,&rect,&window);
+    checkStatus(r,"CreateNewWindow");
+        
+    shared = (AGLContext) gl->rawSharedContext;
+    fmt = (AGLPixelFormat) gl->rawPixelFormat;
+    ctx = WC(aglCreateContext)(fmt,shared);
+    checkStatus(ctx, "aglCreateContext");
+    
+    b = WC(aglSetDrawable)(ctx,WC(GetWindowPort)(window));
+    checkStatus(b,"aglSetDrawable");
+    
+    WC(aglSetCurrentContext)(ctx);
+    WC(aglUpdateContext)(ctx);
+    drawableInit(width,height);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    WC(aglSetCurrentContext)(shared);
+    target = rectTexture ? GL_TEXTURE_RECTANGLE_EXT : GL_TEXTURE_2D;
+    glEnable(target);
+    glGenTextures(1,&tex);
+    glBindTexture(target,tex);
+    glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    WC(aglSurfaceTexture) (shared, target, GL_RGBA, ctx);
+    checkGLError();
+    glDisable(target);
+    
+    //WC(ShowWindow)(window);
+    textureName = (jint) tex;
+    rawWindowRef = (RawData*) window;
+    rawCTX = (RawData*) ctx;
+}
+
+void Darwin$GLCarbonPixelBuffer::activateContext() {
+    AGLContext ctx = (AGLContext) rawCTX;
+    WC(aglSetCurrentContext)(ctx);
+}
+
+void Darwin$GLCarbonPixelBuffer::natCleanup(RawData* rawWindowRef, RawData* rawCTX) {
+    WindowRef window = (WindowRef) rawWindowRef;
+    AGLContext ctx = (AGLContext) rawCTX;
+    WC(aglDestroyContext)(ctx);
+    WC(DisposeWindow)(window);
+}
+
+void Darwin$GLCarbonSurface::clear() {
+    AGLContext ctx = (AGLContext) rawCTX;
+    WC(aglSetCurrentContext)(ctx);
+    glColor4f(1.0f,1.0f,1.0f,1.0f);
+
+    glMatrixMode (GL_MODELVIEW);
+    glPushMatrix ();
+    glLoadIdentity ();
+    glMatrixMode (GL_PROJECTION);
+    glPushMatrix ();
+    glLoadIdentity ();
+    glBegin (GL_QUADS);
+    glVertex3i (-1, -1, -1);
+    glVertex3i (1, -1, -1);
+    glVertex3i (1, 1, -1);
+    glVertex3i (-1, 1, -1);
+    glEnd ();
+    glPopMatrix ();
+    glMatrixMode (GL_MODELVIEW);
+    glPopMatrix ();
+}
+
+void Darwin$GLCarbonSurface::flush() {
+    AGLContext ctx = (AGLContext) rawCTX;
+    WC(aglSetCurrentContext)(ctx);
+    glFlush();
+}
+
+// blit_lock is assumed to be held
+void Darwin$GLCarbonSurface::reshape(jint w, jint h) {
+    AGLContext ctx = (AGLContext) rawCTX;
+    WC(aglSetCurrentContext)(ctx);
+    WC(aglUpdateContext)(ctx);
+    
+    glViewport(0,0,w,h);
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity(); 
+    glOrtho(0,w,h,0,-1,1);   
+    glMatrixMode(GL_MODELVIEW);
+    glLoadIdentity();
+    glTranslatef (0.375f, 0.375f, 0.0f);
+    checkGLError();
+}
+
+// blit_lock is assumed to be held
+void Darwin$GLCarbonSurface::natBlit(Darwin$GLCarbonPixelBuffer *db, jint sx1, jint sy1, jint dx1, jint dy1, jint dx2, jint dy2) {
+    AGLContext ctx = (AGLContext) rawCTX;
+    int sx2 = sx1 + (dx2-dx1);
+    int sy2 = sy1 + (dy2-dy1);
+    jint w, h;
+    db->activateContext();
+    glFlush();
+    checkGLError();
+
+    WC(aglSetCurrentContext)(ctx);
+    checkGLError();
+        
+    if(db->rectTexture) {
+        glEnable(GL_TEXTURE_RECTANGLE_EXT);
+        checkGLError();
+        glBindTexture(GL_TEXTURE_RECTANGLE_EXT, db->textureName);
+        checkGLError();
+        glBegin(GL_QUADS); 
+            glTexCoord2i (sx1, sy1   );
+            glVertex3i   (dx1, dy1, 0);   
+            glTexCoord2i (sx2, sy1   ); 
+            glVertex3i   (dx2, dy1, 0);
+            glTexCoord2i (sx2, sy2   ); 
+            glVertex3i   (dx2, dy2, 0);
+            glTexCoord2i (sx1, sy2   );
+            glVertex3i   (dx1, dy2, 0);
+        glEnd();
+        checkGLError();
+        glDisable(GL_TEXTURE_RECTANGLE_EXT);
+        checkGLError();
+    } else {
+        float tx1,ty1,tx2,ty2; // normalized texture coords
+        tx1 = (float) sx1 / (float) db->width;
+        ty1 = (float) sy1 / (float) db->height;
+        tx2 = (float) sx2 / (float) db->width;
+        ty2 = (float) sy2 / (float) db->height;
+
+        glColor4f(1.0f,1.0f,1.0f,1.0f);
+        glEnable(GL_TEXTURE_2D);
+        glBindTexture(GL_TEXTURE_2D, db->textureName);    
+        checkGLError();
+        glBegin(GL_QUADS); 
+            glTexCoord2f (tx1, ty1   );
+            glVertex3i   (dx1, dy1, 0);
+            glTexCoord2f (tx2, ty1   ); 
+            glVertex3i   (dx2, dy1, 0);
+            glTexCoord2f (tx2, ty2   ); 
+            glVertex3i   (dx2, dy2, 0);
+            glTexCoord2f (tx1, ty2   );
+            glVertex3i   (dx1, dy2, 0);
+        glEnd();
+        glDisable(GL_TEXTURE_2D);
+        checkGLError();
+    }
+}
+
+void Darwin$GLCarbonSurface::natInit() {
+    WindowRef window = (WindowRef) rawWindowRef;
+    AGLContext ctx,shared;
+    AGLPixelFormat fmt;
+    GLboolean b;
+    
+    shared = (AGLContext) gl->rawSharedContext;
+    fmt = (AGLPixelFormat) gl->rawPixelFormat;
+    ctx = WC(aglCreateContext)(fmt,shared);
+    checkStatus(ctx, "aglCreateContext");
+    
+    b = WC(aglSetDrawable)(ctx,WC(GetWindowPort)(window));
+    checkStatus(b,"aglSetDrawable");    
+
+    WC(aglSetCurrentContext)(ctx);
+    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
+    
+    glClearColor (1.0f, 1.0f, 1.0f, 1.0f);
+    glClearDepth( 0.0f );
+    
+    needsReshape();
+    
+    rawCTX = (RawData*)ctx;
+}
+
+void Darwin$GLCarbonSurface::natDispose() {
+    AGLContext ctx = (AGLContext) rawCTX;
+    WC(aglDestroyContext)(ctx);
+    Darwin$CarbonSurface::natDispose();
+}
+
+} } } // end namepsace org::ibex::plat
+
+
+