2003/09/07 03:04:31
[org.ibex.core.git] / src / org / xwt / plat / Carbon.cc
index 92b2dfc..914ba77 100644 (file)
-// Copyright 2002 Adam Megacz, see the COPYING file for licensing [LGPL]
-// see below for copyright information on the second portion of this file
+// 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
 
 #include "POSIX.cc"
-#include <org/xwt/plat/Carbon.h>
-#include <org/xwt/plat/Carbon$CarbonSurface.h>
-#include <org/xwt/plat/Carbon$CarbonPicture.h>
-#include <org/xwt/plat/Carbon$CarbonDoubleBuffer.h>
-#include <org/xwt/plat/Carbon$WrappedRawData.h>
-#include <java/lang/System.h>
+#include "OpenGL.cc"
+
+#include <java/lang/Object.h>
 #include <java/lang/Error.h>
-#include <java/io/PrintStream.h>
-
-// Apple's version of GCC automatically defines this symbol.
-// Since XWT is built with a "stock" version of GCC, we need to define
-// this manually to get the system header files to allow us to include them
-#define __APPLE_CPP__ 1
-
-// Standard GCC doesn't support precompiled headers,
-// meaning that it is WAY faster to just include the individual headers
-#include <CoreFoundation/CFString.h>
-#include <HIToolbox/MacWindows.h>
-#include <HIToolbox/MacApplication.h>
-#include <HIToolbox/Scrap.h>
-#include <HIToolbox/Appearance.h>
-#include <HIToolbox/CarbonEvents.h>
-#include <HIToolbox/HIView.h>
-#include <QD/ATSUnicode.h>
-
-#define min(a, b) ((a) < (b) ? (a) : (b))
-#define max(a, b) ((a) < (b) ? (b) : (a))
-
-#define FORMAT_RECT( x ) x.left, x.top, x.right, x.bottom
-#define PRINT_RECT( x ) fprintf( stderr, #x " = (%d, %d) (%d, %d)\n", x.left, x.top, x.right, x.bottom )
-#define PRINT_CGRECT( rect ) fprintf( stderr, #rect " = %f x %f @ (%f, %f)\n", rect.size.width, rect.size.height, rect.origin.x, rect.origin.y );
-
-
-static const EventTypeSpec CarbonSurfaceEventInfo[] = {
-       { kEventClassWindow, kEventWindowUpdate },
-       { kEventClassWindow, kEventWindowBoundsChanged },
-       { kEventClassWindow, kEventWindowActivated },
-       { kEventClassWindow, kEventWindowDeactivated },
-       { kEventClassWindow, kEventWindowClose },
-       { kEventClassWindow, kEventWindowZoomed },
-       { kEventClassWindow, kEventWindowExpanded },
-       { kEventClassWindow, kEventWindowCollapsed },
-
-
-       { kEventClassKeyboard, kEventRawKeyDown },
-       { kEventClassKeyboard, kEventRawKeyRepeat },
-       { kEventClassKeyboard, kEventRawKeyUp },
-       { kEventClassKeyboard, kEventRawKeyModifiersChanged },
-
-       
-       { kEventClassMouse, kEventMouseDown },
-       { kEventClassMouse, kEventMouseUp },
-       { kEventClassMouse, kEventMouseMoved },
-       { kEventClassMouse, kEventMouseDragged },
-       { kEventClassMouse, kEventMouseExited },
-
-       
-};
 
-static inline UniChar GetCharacterWithoutModifiers( EventRef rawKeyboardEvent )
-{
-       UInt32 keyCode;
-       // Get the key code from the raw key event
-       GetEventParameter( rawKeyboardEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof( keyCode ), NULL, &keyCode );
-
-       // Get the current keyboard layout
- // TODO: If this is a performance sink, we need to cache these values
-       SInt16 lastKeyLayoutID = GetScriptVariable( /*currentKeyScript*/ GetScriptManagerVariable(smKeyScript), smScriptKeys);
-       Handle uchrHandle = GetResource('uchr', lastKeyLayoutID);
-
-       // Translate the key press ignoring ctrl and option
-       UInt32 ignoredDeadKeys = 0;
-       UInt32 ignoredActualLength = 0;
-       UniChar unicodeKey = 0;
-
-       // We actually want the current shift key value
-       UInt32 modifiers = (GetCurrentEventKeyModifiers() & shiftKey) >> 8;
-       OSStatus err = UCKeyTranslate( reinterpret_cast<UCKeyboardLayout*>( *uchrHandle ), keyCode, kUCKeyActionDown,
-                                                               /* modifierKeyState */ modifiers, LMGetKbdType(), kUCKeyTranslateNoDeadKeysMask, &ignoredDeadKeys,
-                                                               /* buffer length */ 1,
-                                                               /* actual length */ &ignoredActualLength,
-                                                               /* string */ &unicodeKey );
-       assert( err == noErr );
-
-       return unicodeKey;
+#include <org/xwt/plat/Carbon.h>
+#include <org/xwt/plat/Carbon$CarbonSurface.h>
+#include <org/xwt/plat/Carbon$GLCarbonSurface.h>
+#include <org/xwt/plat/Carbon$GLCarbonDoubleBuffer.h>
+#include <org/xwt/plat/Carbon$CarbonMessage.h>
+#include <org/xwt/plat/Carbon$CarbonOpenGL.h>
+#include <org/xwt/plat/Carbon$FileDialogHelper.h>
+#include <org/xwt/plat/GCJ$Retainer.h>
+#include <org/xwt/Proxy.h>
+#include <org/xwt/util/Semaphore.h>
+
+#include <Carbon/Carbon.h>
+#include <CoreFoundation/CoreFoundation.h>
+// For proxy stuff
+#include <SystemConfiguration/SystemConfiguration.h>
+// For LSOpenURLRef
+#include <ApplicationServices/ApplicationServices.h>
+
+#include <AGL/agl.h>
+
+#include <stdlib.h>
+
+using namespace org::xwt::plat;
+using gnu::gcj::RawData;
+using org::xwt::util::Semaphore;
+using java::lang::Object;
+
+namespace org { namespace xwt { namespace plat {
+
+namespace carbon { }
+using namespace carbon;
+
+#pragma mark ------ Carbon Namespace ------
+namespace carbon {
+    // We put everything that isn't in org.xwt.plat.Carbon in 
+    // org.xwt.plat.carbon to prevent namespace conflicts
+    
+    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)>();
+
+    void funcFailed(char *func,int r);
+    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 = CFStringGetLength(s);
+        CFRange range = CFRangeMake(0,length);
+        jstring js = JvAllocString(length);
+        UniChar *buf = (UniChar*)JvGetStringChars(js);
+        CFStringGetCharacters(s,range,buf);
+        return js;
+    }
+    
+    #pragma mark ------ SmartCFString ------
+    class SmartCFString {
+        private:
+            CFStringRef p;
+            void release() { if(p) CFRelease(p); }
+            void checkNull() { if(!p) throw new java::lang::Error(JvNewStringLatin1("CFString function failed")); }
+        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 = CFStringCreateWithCString(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 = CFStringCreateWithCharacters(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 CFStringCompare(p,cfs,0) == kCFCompareEqualTo;
+            }
+    };
+    
+    // CHECKME: Is just making up your own four char codes really correct?
+    const static UInt32 kEventClassCarbonMessage = 'xwta';
+    const static UInt32 kEventCarbonMessage = 'xwtb';
+    const static UInt32 kEventParamCarbonMessage = 'xwtc';
+    
+    pascal OSStatus carbon::carbonMessageEventHandler(EventHandlerCallRef handler, EventRef e, void *userData);
+    void fileDialogEventHandler(NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, void *userData);
+
+} // end namespace
+
+jboolean Carbon::isJaguar() {
+    SInt32 version;
+    OSStatus r = Gestalt(gestaltSystemVersion, &version);
+    checkStatus(r,"Gestalt");
+    return version >= 0x1020;
 }
 
-static CFStringRef JavaToCFString(java::lang::String* s) {
-       int len = min(1024, JvGetStringUTFLength(s));
-
-    char* buffer = (char*) malloc( len );
-    JvGetStringUTFRegion(s, 0, s->length(), buffer);
-
-       // Create a CFString from the UTF8 string
-       CFStringRef string = CFStringCreateWithBytes( NULL, (UInt8*) buffer, len, kCFStringEncodingUTF8, false );
-       assert( string != NULL );
-
-       free( buffer );
-       buffer = NULL;
+void Carbon$CarbonMessage::natInit() {
+    OSStatus r;
+    
+    EventHandlerUPP upp = NewEventHandlerUPP(carbonMessageEventHandler);
+    EventTypeSpec eventTypes = { kEventClassCarbonMessage, kEventCarbonMessage };
+    r = InstallEventHandler(GetApplicationEventTarget(),upp,1,&eventTypes,NULL,NULL);
+    checkStatus(r,"InstallEventHandler");
+}
 
-       return string;
+void Carbon$CarbonMessage::add(Carbon$CarbonMessage *msg) {
+    EventRef event;
+    OSStatus r;
+    
+    GCJ$Retainer::retain(msg);
+
+    r = CreateEvent(kCFAllocatorDefault,kEventClassCarbonMessage,kEventCarbonMessage,0,kEventAttributeNone,&event);
+    checkStatus(r,"CreateEvent");
+    r = SetEventParameter(event,kEventParamCarbonMessage,typeVoidPtr,sizeof(msg),(void*)&msg);
+    checkStatus(r,"SetEventParameter");
+    r = PostEventToQueue(GetMainEventQueue(),event,kEventPriorityHigh);
+    checkStatus(r,"PostEventToQueue");
+    ReleaseEvent(event);
 }
 
-static jstring CFToJavaString( CFStringRef s ) {
-       // TODO: I can probably use CFStringCreateExternalRepresentation
-       // First determine the size of the buffer required
-       const CFRange entireString = CFRangeMake( 0, CFStringGetLength( s ) );
-       CFIndex requiredSize = 0;
-       CFIndex charsConverted = CFStringGetBytes( s, entireString, kCFStringEncodingUTF8, 0, false, NULL, 0, &requiredSize );
-       assert( charsConverted == CFStringGetLength( s ) );
 
-       // Allocate the buffer, plus an additional byte for the null byte
-       UInt8* buffer = (UInt8*) malloc( requiredSize + 1 );
-       assert( buffer != NULL );
+pascal OSStatus carbon::carbonMessageEventHandler(EventHandlerCallRef handler, EventRef e, void *userData) {
+    UInt32 eKind = GetEventKind(e);
+    UInt32 eClass = GetEventClass(e);
+    OSStatus r;
+    Carbon$CarbonMessage *msg;
+    if(eClass != kEventClassCarbonMessage || eKind != kEventCarbonMessage)
+        return eventNotHandledErr;
+    r = GetEventParameter(e,kEventParamCarbonMessage,typeVoidPtr,NULL,sizeof(msg),NULL,&msg);
+    checkStatus(r,"GetEventParameter");
+    msg->perform();
+    GCJ$Retainer::release(msg);
+    return noErr;
+}
 
-       // Convert the string
-       charsConverted = CFStringGetBytes( s, entireString, kCFStringEncodingUTF8, 0, false, buffer, requiredSize, NULL );
-       assert( charsConverted == CFStringGetLength( s ) );
 
-       buffer[requiredSize] = '\0';
+#pragma mark ------ Utility Functions ------
 
-       jstring string = JvNewStringUTF( (char*) buffer );
-       assert( string != NULL );
+void carbon::funcFailed(char *func,int r){
+    fprintf(stderr,"%s() failed (%d)\n",func,r);
+    exit(EXIT_FAILURE);
+} 
 
-       free( buffer );
-       buffer = NULL;
+#pragma mark ------ CarbonPicture Methods ------ 
 
-       return string;
-}
+#pragma mark ----- Carbon Surface Methods ----
 
-static jstring UniCharToXWTString( UniChar character )
-{
-       switch ( character ) {
-               case '\t': return JvNewStringLatin1("tab");
-               case kEscapeCharCode: return JvNewStringLatin1("escape");
-               case '\n':
-               case kEnterCharCode:
-               case kReturnCharCode:
-                       return JvNewStringLatin1("enter");
-               case kBackspaceCharCode: return JvNewStringLatin1("back_space");
-                       // escape == clear
-               //case kClearCharCode: return JvNewStringLatin1("clear");
-               //case VK_PAUSE: return JvNewStringLatin1("pause");
-               case kPageUpCharCode: return JvNewStringLatin1("page_up");
-               case kPageDownCharCode: return JvNewStringLatin1("page_down");
-               case kEndCharCode: return JvNewStringLatin1("end");
-               case kHomeCharCode: return JvNewStringLatin1("home");
-               case kLeftArrowCharCode: return JvNewStringLatin1("left");
-               case kUpArrowCharCode: return JvNewStringLatin1("up");
-               case kRightArrowCharCode: return JvNewStringLatin1("right");
-               case kDownArrowCharCode: return JvNewStringLatin1("down");
-                       // TODO: Is help always the insert key in the mac world? on my keyboard it is
-               case kHelpCharCode: return JvNewStringLatin1("insert");
-               case kDeleteCharCode: return JvNewStringLatin1("delete");
-                       // TODO: How can I determine if a numpad key was pressed?
-               //case VK_NUMPAD0: return JvNewStringLatin1("numpad0");
-               //case VK_NUMPAD1: return JvNewStringLatin1("numpad1");
-               //case VK_NUMPAD2: return JvNewStringLatin1("numpad2");
-               //case VK_NUMPAD3: return JvNewStringLatin1("numpad3");
-               //case VK_NUMPAD4: return JvNewStringLatin1("numpad4");
-               //case VK_NUMPAD5: return JvNewStringLatin1("numpad5");
-               //case VK_NUMPAD6: return JvNewStringLatin1("numpad6");
-               //case VK_NUMPAD7: return JvNewStringLatin1("numpad7");
-               //case VK_NUMPAD8: return JvNewStringLatin1("numpad8");
-               //case VK_NUMPAD9: return JvNewStringLatin1("numpad9");
-                       // TODO: How do I get the function key?
-               case kFunctionKeyCharCode: return JvNewStringLatin1("f1");
-               //case VK_F2: return JvNewStringLatin1("f2");
-               //case VK_F3: return JvNewStringLatin1("f3");
-               //case VK_F4: return JvNewStringLatin1("f4");
-               //case VK_F5: return JvNewStringLatin1("f5");
-               //case VK_F6: return JvNewStringLatin1("f6");
-               //case VK_F7: return JvNewStringLatin1("f7");
-               //case VK_F8: return JvNewStringLatin1("f8");
-               //case VK_F9: return JvNewStringLatin1("f9");
-               //case VK_F10: return JvNewStringLatin1("f10");
-               //case VK_F11: return JvNewStringLatin1("f11");
-               //case VK_F12: return JvNewStringLatin1("f12");
-                       
-               default:
-                       // Convert the character into a CFString, then into a java string
-                       CFStringRef string = CFStringCreateWithCharactersNoCopy( NULL, &character, 1, kCFAllocatorNull );
-                       assert( string != NULL );
-
-                       jstring str = CFToJavaString( string );
-
-                       CFRelease( string );
-                       string = NULL;
-
-                       return str;
-       }
-
-       // We should never get here
-       assert( false );
-       return NULL;
-}
 
-static void ModifierKeyTest( org::xwt::plat::Carbon$CarbonSurface* surface, UInt32 changedModifiers, UInt32 currentModifiers, UInt32 keyMask, const char* string )
-{
-       // If the modifier key changed
-       if ( changedModifiers & keyMask ) {
-               jstring str = JvNewStringLatin1( string );
-
-               // And it is currently down, dispatch a keypressed event
-               if ( currentModifiers & keyMask ) surface->KeyPressed( str );
-               // otherwise dispatch a key released event
-               else surface->KeyReleased( str );
-       }
+void Carbon$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;
+    }
+    SetThemeCursor(c);
 }
-
-// TODO: Do I have to make the event handlers "pascal", or use "NewEventHandlerUPP"?
-pascal static OSStatus CarbonSurfaceEventHandler( EventHandlerCallRef handler, EventRef event, void* data ) {
-       UInt32 eventClass = GetEventClass( event );
-       UInt32 eventKind = GetEventKind( event );
-       OSStatus result = eventNotHandledErr;
-       org::xwt::plat::Carbon$CarbonSurface* surface = (org::xwt::plat::Carbon$CarbonSurface*)data;
-
-       //JvSynchronize dummy( surface );
-       
-       switch(eventClass) {
-               case kEventClassWindow:
-                       switch(eventKind)
-                               {
-                               case kEventWindowUpdate:
-                                       {
-                                               //fprintf( stderr, "window update " );
-
-                                               // Create the graphics context
-                                               result = CreateCGContextForPort(GetWindowPort( (WindowRef) surface->window), (CGContextRef*) &surface->gc);
-                                               assert( result == noErr && surface->gc != NULL );
-
-                                               // Quartz uses the bottom left as its origin. Translate to use the top left.
-                                               Rect bounds;
-                                               GetWindowBounds( (WindowRef) surface->window, kWindowContentRgn, &bounds );
-                                               assert( result == noErr );
-                                               CGContextTranslateCTM( (CGContextRef) surface->gc, 0, bounds.bottom - bounds.top );
-                                               CGContextScaleCTM( (CGContextRef) surface->gc, 1, -1 );
-
-                                               // Convert the context to a CGRect with local coordinates
-                                               CGRect contentBounds = CGRectMake( 0, 0, bounds.right - bounds.left, bounds.bottom - bounds.top );
-
-                                               //PRINT_CGRECT( contentBounds );
-
-                                               // Get the invalid region
-                                               Rect globalInvalidRect;
-                                               result = GetWindowBounds( (WindowRef) surface->window, kWindowUpdateRgn, &globalInvalidRect );
-                                               assert( result == noErr );
-
-                                               CGRect invalidRect = CGRectMake( globalInvalidRect.left - bounds.left, globalInvalidRect.top - bounds.top, globalInvalidRect.right - globalInvalidRect.left, globalInvalidRect.bottom - globalInvalidRect.top );
-
-                                               //invalidRect = CGRectIntersection( invalidRect, contentBounds );
-
-                                               //PRINT_CGRECT( invalidRect );
-
-                                               BeginUpdate( (WindowRef) surface->window );
-
-                                               // Erase the region with white
-                                               // TODO: Draw the window background instead
-                                               //result = SetThemeWindowBackground( (WindowRef) surface->window, ThemeBrush inBrush, true );
-                                               CGContextSetRGBFillColor( (CGContextRef) surface->gc, 1.0, 1.0, 1.0, 1.0 );
-                                               CGContextFillRect( (CGContextRef) surface->gc, invalidRect );                   
-
-                                               //CGContextSetRGBFillColor( (CGContextRef) surface->gc, red, green, blue, 0.5 );
-                                               //CGContextFillRect( (CGContextRef) surface->gc, CGRectMake( 0, 0, (bounds.right - bounds.left), (bounds.bottom - bounds.top) ) );
-                                               // Add the invalid region to XWT's dirty regions
-                                               surface->Dirty( (jint) invalidRect.origin.x, (jint) invalidRect.origin.y, (jint) invalidRect.size.width, (jint) invalidRect.size.height );
-                                               // Then tell it to actually do the drawing
-                                               surface->blitDirtyScreenRegions();
-
-                                               EndUpdate( (WindowRef) surface->window );
-
-                                               // Free the context
-                                               CGContextFlush( (CGContextRef) surface->gc );
-                                               CGContextRelease( (CGContextRef) surface->gc );
-                                               surface->gc = NULL;
-                                               result = noErr;
-                                               break;
-                                       }
-
-                               case kEventWindowBoundsChanged:
-                                       {
-                                               // We can't use the event parameter: it is the window bounds, not the content area bounds
-                                               HIRect currentBounds;
-                                               result = GetEventParameter( event, kEventParamCurrentBounds, typeHIRect, NULL, sizeof( currentBounds ), NULL, &currentBounds );
-                                               assert( result == noErr );
-                                               
-                                               // Get the event attributes to determine if size and/or origin have changed
-                                               UInt32 attributes;
-                                               result = GetEventParameter( event, kEventParamAttributes, typeUInt32, NULL, sizeof( attributes ), NULL, &attributes );
-                                               assert( result == noErr );
-
-                                               if ( attributes & kWindowBoundsChangeSizeChanged ) {
-                                                       // If maximize is set, unset it
-                                                       if ( attributes & kWindowBoundsChangeUserResize && surface->maximized ) {
-                                                               //fprintf( stderr, "maximized = 0\n" );
-                                                               surface->Maximized( false );
-                                                       }
-                                                       
-                                                       //fprintf( stderr, "size changed\n" );
-                                                       surface->SizeChange( (jint) currentBounds.size.width, (jint) currentBounds.size.height );
-
-                                                       
-                                               }
-                                               
-                                               if ( attributes & kWindowBoundsChangeOriginChanged ) {
-                                                       //fprintf( stderr, "origin changed\n" );
-                                                       surface->PosChange( (jint) currentBounds.origin.x, (jint) currentBounds.origin.y );
-                                               }
-
-                                               result = noErr;
-                                               break;
-                                       }
-
-                               case kEventWindowActivated:
-                               case kEventWindowDeactivated:
-                                       {
-                                               //fprintf( stderr, "focus = %d\n", (eventKind == kEventWindowActivated) );
-                                               surface->Focused( (eventKind == kEventWindowActivated) );
-                                               result = noErr;
-                                               break;
-                                       }
-
-                               case kEventWindowZoomed:
-                                       {
-                                               // Toggle maximized whenever we recieve this event
-                                               //fprintf( stderr, "maximized: %d\n", ! surface->maximized );
-                                               surface->Maximized( ! surface->maximized );
-                                               result = noErr;
-                                               break;
-                                       }
-                                       
-                               case kEventWindowCollapsed:
-                                       {
-                                               //fprintf( stderr, "minimized true\n" );
-                                               surface->Minimized( true );
-                                               result = noErr;
-                                               break;
-                                       }
-
-                               case kEventWindowExpanded:
-                                       {
-                                               //fprintf( stderr, "minimized false\n" );
-                                               surface->Minimized( false );
-                                               result = noErr;
-                                               break;
-                                       }
-                                       
-                               case kEventWindowClose:
-                                       {
-                                               //fprintf( stderr, "close\n" );
-                                               surface->Close();
-                                               result = noErr;
-                                               break;
-                                       }
-                               default:
-                                       throw new java::lang::Error(JvNewStringLatin1("Unhandled Window Event"));
-                               }
-                       break;
-                       
-               case kEventClassMouse:
-                       {
-                               HIPoint where;
-                               result = GetEventParameter( event, kEventParamMouseLocation, typeHIPoint, NULL, sizeof(where), NULL, &where );
-                               assert( result == noErr );
-
-                               // Create a hit test event to ask the standard window event handler where this press is
-                               EventRef hitTest;
-                               result = CreateEvent( NULL, kEventClassWindow, kEventWindowHitTest, 0, kEventAttributeNone, &hitTest );
-                               assert( result == noErr );
-
-                               result = SetEventParameter( hitTest, kEventParamMouseLocation, typeHIPoint, sizeof(where), &where );
-                               assert( result == noErr );
-
-                               result = SetEventParameter( hitTest, kEventParamDirectObject, typeWindowRef, sizeof(surface->window), &surface->window );
-                               assert( result == noErr );
-
-                               result = SendEventToEventTarget( hitTest, GetWindowEventTarget( (WindowRef) surface->window ) );
-                               assert( result == noErr );
-
-                               WindowDefPartCode part;
-                               result = GetEventParameter( hitTest, kEventParamWindowDefPart, typeWindowDefPartCode, NULL, sizeof(part), NULL, &part );
-                               assert( result == noErr );
-
-                               ReleaseEvent( hitTest );
-                               hitTest = NULL;
-
-                               // ignore the event if it is not in the content region.
-                               if ( part != wInContent )
-                                       {
-                                       return eventNotHandledErr;
-                                       }
-
-                               // TODO: Can I get the content region's bounds as an HIRect?
-                               Rect bounds;
-                               GetWindowBounds( (WindowRef) surface->window, kWindowContentRgn, &bounds );
-                               assert( result == noErr );
-                               // Convert the context to a CGRect with local coordinates
-                               CGRect contentBounds = CGRectMake( bounds.left, bounds.top, bounds.right - bounds.left, bounds.bottom - bounds.top );
-
-                               // Now convert the point to content area relative coordinates:
-                               where.x -= contentBounds.origin.x;
-                               where.y -= contentBounds.origin.y;
-                               
-                               switch ( eventKind )
-                                       {
-                                       case kEventMouseDown:
-                                               {
-                                                       //fprintf( stderr, "mouse down (%f, %f)\n", where.x, where.y );
-                                                       EventMouseButton mouseButton;
-                                                       result = GetEventParameter( event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(mouseButton), NULL, &mouseButton );
-                                                       assert( result == noErr );
-
-                                                       surface->Press( mouseButton );
-                                                       result = eventNotHandledErr;
-                                                       break;
-                                               }
-
-                                       case kEventMouseUp:
-                                               {
-                                                       //fprintf( stderr, "mouse up (%f, %f)\n", where.x, where.y );
-                                                       EventMouseButton mouseButton;
-                                                       result = GetEventParameter( event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(mouseButton), NULL, &mouseButton );
-                                                       assert( result == noErr );
-
-                                                       UInt32 clickCount;
-                                                       result = GetEventParameter( event, kEventParamClickCount, typeUInt32, NULL, sizeof(clickCount), NULL, &clickCount );
-                                                       assert( result == noErr );
-
-                                                       surface->Release( mouseButton );
-
-                                                       // deliver click/double click events
-                                                       if ( clickCount == 1 ) {
-                                                               //fprintf( stderr, "click (%f, %f)\n", where.x, where.y );
-                                                               surface->Click( mouseButton );
-
-                                                               //result = ActivateWindow( (WindowRef) surface->window, true );
-                                                               //assert( result == noErr );
-
-                                                               //ProcessSerialNumber psn = { 0, kCurrentProcess };
-                                                               //result = SetFrontProcess( &psn );
-                                                               //assert( result == noErr );
-                                                       } else if ( clickCount == 2 ) {
-                                                               //fprintf( stderr, "double click (%f, %f)\n", where.x, where.y );
-                                                               surface->DoubleClick( mouseButton );
-                                                       }
-                                                       
-                                                       result = noErr;
-                                                       break;
-                                               }
-
-                                       case kEventMouseMoved:
-                                       case kEventMouseDragged:
-                                               {
-                                                       surface->Move( (jint) where.x, (jint) where.y );
-                                                       result = noErr;
-                                                       //fprintf( stderr, "mousemoved (%f, %f)\n", where.x, where.y );
-                                                       break;
-                                               }
-
-                                       /*case kEventMouseExited:
-                                               {
-                                                       // Move the mouse to (-1, -1) when it exits the window 
-                                                       surface->Move( -1, -1 );
-                                                       result = noErr;
-                                                       fprintf( stderr, "mouse exited\n" );
-                                                       break;
-                                               }*/
-                                               
-
-                                       /*case kEventMouseWheelMoved:
-                                       {
-                                               EventMouseWheelAxis inAxis;
-                                               result = inEvent.GetParameter<EventMouseWheelAxis>( kEventParamMouseWheelAxis, typeMouseWheelAxis, &inAxis );
-                                               assert( noErr == result );
-
-                                               SInt32 inDelta;
-                                               result = inEvent.GetParameter<SInt32>( kEventParamMouseWheelDelta, typeSInt32, &inDelta );
-                                               assert( noErr == result );
-
-                                               result = MouseWheelMoved( inAxis, inDelta, inKeyModifiers );
-                                               break;
-                                       }
-                                       */
-
-
-                                               // some other kind of Mouse event: This is (in my opinion) an error
-                                       default:
-                                               assert( false );
-                                               break;
-                                       }
-                               break;
-                       }
-
-
-               case kEventClassKeyboard:
-                       switch (eventKind)
-                       {
-                               case kEventRawKeyDown:
-                               case kEventRawKeyRepeat:
-                                       {
-                                               // TODO: This breaks international input
-                                               UniChar character = GetCharacterWithoutModifiers( event );
-                                               surface->KeyPressed( UniCharToXWTString( character ) );
-                                               
-                                               result = noErr;
-                                               break;
-                                       }
-
-                               case kEventRawKeyUp:
-                                       {
-                                               UniChar character = GetCharacterWithoutModifiers( event );
-                                               surface->KeyReleased( UniCharToXWTString( character ) );
-                                               
-                                               result = noErr;
-                                               break;
-                                       }
-
-                               case kEventRawKeyModifiersChanged:
-                                       {
-                                               static UInt32 previousModifiers = 0;
-                                               UInt32 currentModifiers = GetCurrentEventKeyModifiers();
-                                               UInt32 changedModifiers = previousModifiers ^ currentModifiers;
-
-                                               ModifierKeyTest( surface, changedModifiers, currentModifiers, shiftKey, "shift" );
-                                               ModifierKeyTest( surface, changedModifiers, currentModifiers, alphaLock, "caps_lock" );
-                                               ModifierKeyTest( surface, changedModifiers, currentModifiers, controlKey, "control" );
-                                               ModifierKeyTest( surface, changedModifiers, currentModifiers, optionKey, "alt" );
-                                               ModifierKeyTest( surface, changedModifiers, currentModifiers, kEventKeyModifierNumLockMask, "num_lock" );
-                                               
-                                               previousModifiers = currentModifiers;
-                                               result = noErr;
-                                               break;
-                                       }
-                                       
-                               default:
-                                       assert( false );
-                                       break;
-                       }
-                       break;
-                       
-               default:
-                       throw new java::lang::Error(JvNewStringLatin1("Unhandled Window Event"));
-       }
-
-       return result;
+   
+void Carbon$CarbonSurface::natSetInvisible(jboolean b) {
+    WindowRef window = (WindowRef) rawWindowRef;
+    fprintf(stderr,"Making window %s\n",b?"invisible":"visible");
+    if(b) HideWindow(window);
+    else ShowWindow(window);
 }
 
-/** Creates a next layout from string and style. If unicodeBuffer is not null, the caller is responsable for releasing it. */
-static ATSUTextLayout CreateTextLayout( CFStringRef string, ATSUStyle style, CFStringRef* unicodeBuffer ) {
-       assert( string != NULL && unicodeBuffer != NULL && *unicodeBuffer == NULL && style != NULL );
-
-       // Create layout
-       ATSUTextLayout layout;
-       OSStatus result = ATSUCreateTextLayout( &layout );
-       assert( result == noErr && layout != NULL );
-
-       // Try to get the unicode buffer directly
-       CFIndex unicodeLength = CFStringGetLength( string );
-       assert( unicodeLength != 0 );
-       const UniChar* unicodeString = CFStringGetCharactersPtr( string );
-       if ( unicodeString == NULL )
-               {
-               // That failed. Allocate a buffer using CFAllocator so the CFString can own it
-               UniChar* buffer = (UniChar*) CFAllocatorAllocate( NULL, unicodeLength * sizeof( UniChar ), 0 );
-               assert( buffer != NULL );
-
-               // Get a copy of the text
-               CFStringGetCharacters( string, CFRangeMake( 0, unicodeLength ), buffer );
-
-               // Create a CFString which wraps and takes ownership of the buffer
-               *unicodeBuffer = CFStringCreateWithCharactersNoCopy( NULL, buffer, unicodeLength, NULL );
-               assert( *unicodeBuffer != NULL );
-
-               unicodeString = buffer;
-               }
-               
-       assert( unicodeString != NULL );
-       //UniChar* unicode_string = malloc( sizeof( UniChar ) * unicode_length );
-       //CFStringGetCharacters( string, CFRangeMake( 0, unicode_length ), unicode_string );
-       ATSUSetTextPointerLocation( layout, unicodeString, kATSUFromTextBeginning, kATSUToTextEnd, unicodeLength );
-
-       // Set the style
-       result = ATSUSetRunStyle( layout, style, kATSUFromTextBeginning, kATSUToTextEnd );
-       assert( result == noErr );
-
-       // Using this setting makes rendering match TextEdit's (except for the antialiasing rules)
-       ATSLineLayoutOptions rendering = kATSLineFractDisable; //kATSLineUseDeviceMetrics;
-       ATSUAttributeTag tag = kATSULineLayoutOptionsTag;
-       ByteCount size = sizeof( rendering );
-       ATSUAttributeValuePtr value = &rendering;
-       result = ATSUSetLayoutControls( layout, 1, &tag, &size, &value );
-       assert( noErr == result );
-
-       // Allow ATSUI to use its default font fallbacks for Unicode. This means that the font may not
-       // match exactly, but it will display the characters if it can.
-       result = ATSUSetTransientFontMatching( layout, true );
-       assert( noErr == result );
-
-    return layout;
+void Carbon$CarbonSurface::nat_setMaximized(jboolean b) {
+    WindowRef window = (WindowRef) rawWindowRef;
+    Point ideal = { 10000, 10000 };
+    OSStatus r = ZoomWindowIdeal(window,(b?inZoomOut:inZoomIn),&ideal);
+    checkStatus(r,"ZoomWindowIdeal");
 }
 
-static void SetARGBFillColor( CGContextRef gc, jint argb )
-{
-       uint8_t* colour = (uint8_t*) &argb;
-       float alpha = colour[0] / 255.0;
-       float red = colour[1] / 255.0;
-       float green = colour[2] / 255.0;
-       float blue = colour[3] / 255.0;
-
-       CGContextSetRGBFillColor( gc, red, green, blue, alpha );
+void Carbon$CarbonSurface::nat_setMinimized(jboolean b) {
+    WindowRef window = (WindowRef) rawWindowRef;
+    if((IsWindowCollapsed(window) ? 1 : 0) == (b ? 1 : 0)) return;
+    OSStatus r = CollapseWindow(window,b);
+    checkStatus(r,"CollapseWindow");
 }
 
-// CarbonDoubleBuffer //////////////////////////////////////////////////////////////////////
-
-void org::xwt::plat::Carbon$CarbonDoubleBuffer::setClip(jint x1, jint y1, jint x2, jint y2) {
-       // Restore the previous graphics state, which should be the initial state as saved in
-       // natInit(). This sets the clipping region to the entire buffer.
-       CGContextRestoreGState( (CGContextRef) gc );
-       // We then immediately save the state again, so the we can reset the clipping area again
-       CGContextSaveGState( (CGContextRef) gc );
-
-       // Set the clipping area to the rectangle
-    CGContextClipToRect( (CGContextRef) gc, CGRectMake( x1, y1, x2 - x1, y2 - y1 ) );
+void Carbon$CarbonSurface::natSetTitleBarText(jstring js) {
+    SmartCFString s = js;
+    WindowRef window = (WindowRef) rawWindowRef;
+    SetWindowTitleWithCFString(window,s);
 }
 
-void org::xwt::plat::Carbon$CarbonDoubleBuffer::drawPicture(org::xwt::Picture* s, jint x, jint y) {
-       org::xwt::plat::Carbon$CarbonPicture* source = (org::xwt::plat::Carbon$CarbonPicture*)s;
-
-       CGRect destination = CGRectMake( x, y, source->width, source->height );
-       HIViewDrawCGImage( (CGContextRef) gc, &destination, (CGImageRef) source->image );
+void Carbon$CarbonSurface::natToBack() {
+    WindowRef window = (WindowRef) rawWindowRef;
+    SendBehind(window,NULL);
 }
 
-void org::xwt::plat::Carbon$CarbonDoubleBuffer::drawPicture(org::xwt::Picture* s,
-                                                           jint dx1, jint dy1, jint dx2, jint dy2, jint sx1, jint sy1, jint sx2, jint sy2) {
-    org::xwt::plat::Carbon$CarbonPicture* source = (org::xwt::plat::Carbon$CarbonPicture*)s;
-
-       //fprintf( stderr, "drawing stretched picture\n" );
-       //CGContextSetRGBFillColor( (CGContextRef) gc, 1.0, 0.0, 0.0, 1.0 );
-       //CGContextFillRect( (CGContextRef) gc, CGRectMake( dx1, dy1, dx2 - dx1, dy2 - dy1 ) );
-       //return;
-       
-       // Some fancy clipping work is required here: draw only inside of the destination points
-       CGContextSaveGState( (CGContextRef) gc );
-       CGContextClipToRect( (CGContextRef) gc, CGRectMake( dx1, dy1, dx2 - dx1, dy2 - dy1 ) );
-
-       // Some fancy scaling work is required here as well:
-       // We want to copy a rectangle from the source image to a destination rectangle.
-       // We are clipped to the destination rectangle, so now we must scale the source image
-       // and line it up correctly.
-       float destinationRectWidth = dx2 - dx1;
-       float destinationRectHeight = dy2 - dy1;
-       float sourceRectWidth = sx2 - sx1;
-       float sourceRectHeight = sy2 - sy1;
-       float horizontalScalingFactor = destinationRectWidth / sourceRectWidth;
-       float verticalScalingFactor = destinationRectHeight / sourceRectHeight;
-
-       // TODO: Work out the math for doing this. For now, no scaling is possible.
-       CGRect destinationRect = CGRectMake( dx1 - sx1 * horizontalScalingFactor, dy1 - sy1 * verticalScalingFactor,
-                                                                         source->width * horizontalScalingFactor, source->height * verticalScalingFactor );
-       HIViewDrawCGImage( (CGContextRef) gc, &destinationRect, (CGImageRef) source->image );
-
-       // Undo the clipping fun
-       CGContextRestoreGState( (CGContextRef) gc );
+void Carbon$CarbonSurface::natToFront() {
+    WindowRef window = (WindowRef) rawWindowRef;
+    fprintf(stderr,"SelectWindow()\n");
+    SelectWindow(window);
 }
 
-/*void CarbonPictureRelease( void* info, const void* data, size_t size )
-{
-       // TODO: This should release a java reference, which should be
-       // obtained when this is created.
-       // It'll work without it, but that's only by "chance".
-}*/
-
-static CGImageRef CreateCGImageFromData( void* data, int width, int height, CGImageAlphaInfo alphaFormat )
-{
-       // I'm assuming that data is in RGBA format
-       const size_t NUM_COMPONENTS = 4;
-       const size_t BITS_PER_COMPONENT = 8;
-       const size_t BITS_PER_PIXEL = BITS_PER_COMPONENT * NUM_COMPONENTS;
-       const size_t BYTES_PER_PIXEL = BITS_PER_PIXEL / 8;
-       const size_t BYTES_PER_ROW = BYTES_PER_PIXEL * width;
-
-       CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
-       assert( colorSpace != NULL );
-
-       CGDataProviderRef dataProvider = CGDataProviderCreateWithData( NULL, data, width * height * BYTES_PER_PIXEL, NULL /*CarbonPictureRelease*/ );
-       assert( dataProvider != NULL );
-
-       CGImageRef image = CGImageCreate ( width, height, BITS_PER_COMPONENT, BITS_PER_PIXEL, BYTES_PER_ROW,
-                                                                       colorSpace, alphaFormat, dataProvider, NULL, 1, kCGRenderingIntentDefault );
-       assert( image != NULL );
-
-       CGDataProviderRelease( dataProvider );
-       dataProvider = NULL;
-
-       CGColorSpaceRelease( colorSpace );
-       colorSpace = NULL;
-
-       return image;
+#pragma mark ---- Window Event Handler ----
+namespace carbon {
+static const EventTypeSpec eventTypeSpecs[] = {
+    // kEventClassCommand
+    // { kEventClassCommand, ??? },
+    
+    // kEventClassWindow
+    { kEventClassWindow, kEventWindowUpdate },
+    { kEventClassWindow, kEventWindowBoundsChanged },
+    { kEventClassWindow, kEventWindowActivated },
+    { kEventClassWindow, kEventWindowDeactivated },
+    { kEventClassWindow, kEventWindowZoomed },
+    { kEventClassWindow, kEventWindowCollapsed },
+    { kEventClassWindow, kEventWindowExpanded },
+    { kEventClassWindow, kEventWindowClose },
+    { kEventClassWindow, kEventWindowClosed },
+    
+    // kEventClassKeyboard
+    { kEventClassKeyboard, kEventRawKeyDown },
+    { kEventClassKeyboard, kEventRawKeyRepeat },
+    { kEventClassKeyboard, kEventRawKeyUp },
+    { kEventClassKeyboard, kEventRawKeyModifiersChanged },
+    
+    // kEventClassMouse
+    { kEventClassMouse, kEventMouseDown },
+    { kEventClassMouse, kEventMouseUp },
+    { kEventClassMouse, kEventMouseMoved },
+    { kEventClassMouse, kEventMouseDragged },
+    { kEventClassMouse, kEventMouseWheelMoved },
+};
+    
+pascal OSStatus windowEventHandler(EventHandlerCallRef handler, EventRef e, void *userData) {
+    Carbon$CarbonSurface *surface = (Carbon$CarbonSurface*) userData;
+    UInt32 eKind = GetEventKind(e);
+    UInt32 eClass = GetEventClass(e);
+    OSStatus r;
+    
+    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 = 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 = 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 = 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 xwtKey;
+                    } 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 = 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].xwtKey);
+                        else
+                            surface->KeyReleased(modifiersTable[i].xwtKey);
+                    }
+                    return noErr;
+                }
+            }
+            break;
+        case kEventClassMouse:
+            // The default handler gets first dibs on mouse events
+            // (this catches the titlebar, resize box, etc)
+            r = 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 = GetEventParameter(e,kEventParamMouseLocation,typeQDPoint,NULL,sizeof(p),NULL,&p);
+                    checkStatus(r,"GetEventParameter");
+                    r = 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 xwtButton;
+                    r = GetEventParameter(e,kEventParamMouseButton,typeMouseButton,NULL,sizeof(button),NULL,&button);
+                    checkStatus(r,"GetEventParameter");
+                    r = GetEventParameter(e,kEventParamClickCount,typeUInt32,NULL,sizeof(clickCount),NULL,&clickCount);
+                    checkStatus(r,"GetEventParameter");
+                    
+                    switch(button) {
+                        case kEventMouseButtonPrimary:   xwtButton = 1; break;
+                        case kEventMouseButtonSecondary: xwtButton = 2; break;
+                        case kEventMouseButtonTertiary:  xwtButton = 3; break;
+                        default: return noErr;
+                    }
+                    if(eKind == kEventMouseDown) {
+                        surface->Press(xwtButton);
+                    } else {
+                        surface->Release(xwtButton);
+                        while(clickCount > 1) {
+                            surface->DoubleClick(xwtButton);
+                            clickCount-=2;
+                        }
+                        if(clickCount) surface->Click(xwtButton);
+                    }
+                    return noErr;
+                }
+                case kEventMouseWheelMoved: {
+                    EventMouseWheelAxis axis;
+                    SInt32 delta;
+                    r = GetEventParameter(e,kEventParamMouseWheelAxis,typeMouseWheelAxis,NULL,sizeof(axis),NULL,&axis);
+                    checkStatus(r,"GetEventParameter");
+                    if(axis != kEventMouseWheelAxisY) break;
+                    r = 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 xwt
+                    return noErr;
+                }
+            }
+            break;
+        
+        case kEventClassWindow: {
+            WindowRef window;
+            r = GetEventParameter(e,kEventParamDirectObject,typeWindowRef,NULL,sizeof(window),NULL,&window);
+            checkStatus(r,"kEventClassWindow/GetEventParameter");
+            
+            if((RawData*)window != surface->rawWindowRef) Carbon::abort(JvNewStringLatin1("window != surface->window"));
+            
+            switch(eKind) {
+                case kEventWindowUpdate: {
+                    surface->Dirty(0,0,surface->width,surface->height);
+                    return noErr;
+                }
+                case kEventWindowBoundsChanged: {
+                    UInt32 attr;
+                    Rect rect;
+                    r = GetEventParameter(e,kEventParamAttributes,typeUInt32,NULL,sizeof(attr),NULL,&attr);
+                    checkStatus(r,"kEventWindowBoundsChanged/GetEventParameter");
+                    r = GetWindowBounds(window,kWindowContentRgn,&rect);
+                    checkStatus(r,"GetWindowBounds");
+                    if(attr & kWindowBoundsChangeSizeChanged) {
+                        jint w = rect.right-rect.left;
+                        jint h = rect.bottom-rect.top;
+                        if(attr & kWindowBoundsChangeUserResize && surface->maximized)
+                            surface->Maximized(false);
+                        surface->reshape(w,h);
+                        surface->SizeChange(w,h);
+                        surface->Dirty(0,0,w,h);
+                        surface->blitDirtyScreenRegions();
+                    }
+                    if(attr & kWindowBoundsChangeOriginChanged) {
+                        surface->PosChange(rect.left,rect.top);
+                    }
+                    return noErr;
+                }
+                case kEventWindowActivated:
+                case kEventWindowDeactivated: {
+                    surface->Focused(eKind == kEventWindowActivated);
+                    return noErr;
+                }
+                case kEventWindowZoomed: {
+                    fprintf(stderr,"Zoomed....\n");
+                    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: {
+                    DisposeEventHandlerUPP((EventHandlerUPP)surface->rawEventHandlerUPP);
+                    GCJ$Retainer::release(surface);
+                    return noErr;
+                }
+            }
+        }
+        break;
+    }
+    return eventNotHandledErr;
 }
-
-void org::xwt::plat::Carbon$CarbonDoubleBuffer::natInit() {
-       // FIRST: We create a CGBitmapContextRef so we can draw on this buffer
-       const int BYTES_PER_PIXEL = 4; // RGBA
-       const int BITS_PER_COMPONENT = 8;
-       
-    // Create a new bitmap context, along with the RAM for the bitmap itself
-       const int bitmapBytesPerRow   = (width * BYTES_PER_PIXEL);
-       const int bitmapByteCount     = (bitmapBytesPerRow * height);
-
-       //fprintf( stderr, "alloced %ld bytes for %d x %d double buffer\n", bitmapByteCount, width, height );
-       
-       // create an RGB color space
-       CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
-       assert( colorSpace != NULL );
-
-       // create the bitmap
-       bitmapData = (gnu::gcj::RawData*) malloc( bitmapByteCount );
-       assert( bitmapData != NULL );
-
-       // create the context
-       // TODO: Use kCGImageAlphaPremultipliedLast for better performance
-       gc = (gnu::gcj::RawData*) CGBitmapContextCreate( bitmapData, width, height, BITS_PER_COMPONENT, bitmapBytesPerRow, colorSpace, kCGImageAlphaPremultipliedFirst );
-       assert( gc != NULL );
-
-       // the context retains the color space, so we can release it
-       // OPTIMIZATION: We could pass this colorSpace into CreateCGImageFromData
-       CGColorSpaceRelease( colorSpace );
-       colorSpace = NULL;
-
-       // Clear the double buffer to transparent
-       CGContextClearRect( (CGContextRef) gc, CGRectMake( 0, 0, width, height ) );
-       //CGContextSetRGBFillColor( (CGContextRef) gc, 1.0, 1.0, 1.0, 1.0 );
-       //CGContextFillRect( (CGContextRef) gc, CGRectMake( 0, 0, width, height ) );
-
-       // Shift the coordinate origin to the top left corner (default = bottom right)
-       CGContextTranslateCTM( (CGContextRef) gc, 0, height );
-       CGContextScaleCTM( (CGContextRef) gc, 1, -1 );
-
-
-       // SECOND: We create a CGImageRef that wraps this buffer, so we can copy it to a Surface
-       image = (gnu::gcj::RawData*) CreateCGImageFromData( bitmapData, width, height, kCGImageAlphaPremultipliedFirst );
-       assert( image != NULL );
-
-       // THIRD: Save the current graphics state so we can set and reset the clipping state
-       // We need to do this because the only way to make the clipping region larger is to
-       // restore a previous graphics state. See setClip.
-       CGContextSaveGState( (CGContextRef) gc );
+} // end namespace
+
+void Carbon$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 = 0; rect.left = 0; rect.bottom = 10; rect.right=10;
+    r = CreateNewWindow(wc,attr,&rect,&window);
+    checkStatus(r,"CreateNewWindow");
+    
+    GCJ$Retainer::retain(this); // Need to account for the EventHandlers pointer to us
+    EventHandlerUPP upp = NewEventHandlerUPP(windowEventHandler);
+    
+    r = InstallWindowEventHandler(window,upp,sizeof(eventTypeSpecs)/sizeof(EventTypeSpec),eventTypeSpecs,this,NULL);
+    checkStatus(r,"InstallWindowEventHandler");
+    
+    rawWindowRef = (RawData*) window;
+    rawEventHandlerUPP = (RawData*) upp;  
 }
 
-void org::xwt::plat::Carbon$CarbonDoubleBuffer::finalize() {
-       CGContextRelease( (CGContextRef) gc );
-       CGImageRelease( (CGImageRef) image );
-    free( bitmapData );
-       bitmapData = NULL;
+void Carbon$CarbonSurface::natDispose() {
+    WindowRef window = (WindowRef) rawWindowRef;
+    DisposeWindow(window);
 }
 
-void org::xwt::plat::Carbon$CarbonSurface::blit(org::xwt::DoubleBuffer* db, jint sx, jint sy, jint dx1, jint dy1, jint dx2, jint dy2) {
-    org::xwt::plat::Carbon$CarbonDoubleBuffer *xdb = (org::xwt::plat::Carbon$CarbonDoubleBuffer*)db;
-       assert( xdb != NULL && xdb->gc != NULL && xdb->image != NULL );
-
-       // This method is synchronized to prevent crappy threading fun
-       //JvSynchronize dummy(this);
-       
-       /*fprintf( stderr, "reading image data...\n" );
-       uint32_t* data = (uint32_t*) xdb->bitmapData;
-       for ( int i = 0; i < xdb->width * xdb->height; ++ i )
-               {
-               uint32_t temp = data[i];
-               ++ temp;
-               }
-       fprintf( stderr, "DONE\n" );*/
-
-       
-       // If we do not have a graphics context we simply mark this area as dirty and return.
-       // We'll get a WindowPaint event later on.
-       if ( gc == NULL )
-               {
-               Rect area;
-               area.left = dx1;
-               area.top = dy1;
-               area.right = dx2;
-               area.bottom = dy2;
-               // Make the rectangle where we would blit this buffer as invalid
-               OSStatus err = InvalWindowRect( (WindowRef) window, &area );
-               //OSStatus err = QDAddRectToDirtyRegion( GetWindowPort( (WindowRef) window ), &area );
-               assert( err == noErr );
-
-               //fprintf( stderr, "blit: but marking invalid " );
-               //PRINT_RECT( area );
-               return;
-               }
-       assert( gc != NULL );
-
-       //fprintf( stderr, "blit\n" );
-       
-       // Make sure that the CGImage is up to date
-       CGContextFlush( (CGContextRef) xdb->gc );
-
-       // Some fancy clipping work is required here: draw only inside of the destination rectangle
-       CGContextSaveGState( (CGContextRef) gc );
-       CGContextClipToRect( (CGContextRef) gc, CGRectMake( dx1, dy1, dx2 - dx1, dy2 - dy1 ) );
-
-       // Draw the image on the surface
-       CGRect destination = CGRectMake( dx1 - sx, dy1 - sy, xdb->width, xdb->height );
-       HIViewDrawCGImage( (CGContextRef) gc, &destination, (CGImageRef) xdb->image );
-
-       // Undo the clipping fun
-       CGContextRestoreGState( (CGContextRef)gc );     
+void Carbon$CarbonSurface::natSetIcon(org::xwt::Picture *_p) {
 }
 
-void org::xwt::plat::Carbon$CarbonDoubleBuffer::fillRect (jint x, jint y, jint x2, jint y2, jint argb) {
-       // Set the Fill color to match
-       SetARGBFillColor( (CGContextRef) gc, argb );
-       CGContextFillRect( (CGContextRef) gc, CGRectMake( x, y, x2 - x, y2 - y ) );
+void Carbon$CarbonSurface::natSetLocation(jint x, jint y) {
+    WindowRef window = (WindowRef) rawWindowRef;
+    Rect rect;
+    OSStatus r = 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 = SetWindowBounds(window,kWindowStructureRgn,&rect);
+    checkStatus(r,"SetWindowBounds");
+    r = ConstrainWindowToScreen(window,kWindowStructureRgn,kWindowConstrainMoveRegardlessOfFit,NULL,NULL);
+    checkStatus(r,"ConstrainWindowToScreen");
 }
 
-void org::xwt::plat::Carbon$CarbonDoubleBuffer::drawString(::java::lang::String* font, ::java::lang::String* text, jint x, jint y, jint argb) {
-       ATSUStyle style = (ATSUStyle) ((org::xwt::plat::Carbon*)org::xwt::plat::Carbon::platform)->_getATSUStyle( font );
-       CFStringRef string = JavaToCFString( text );
-
-       CFStringRef unicodeBuffer = NULL;
-       ATSUTextLayout layout = CreateTextLayout( string, style, &unicodeBuffer );
-
-       // Associate the graphics context with the text layout object
-       ATSUAttributeTag tag = kATSUCGContextTag;
-       ByteCount size = sizeof( gc );
-       ATSUAttributeValuePtr value = &gc;
-       OSStatus result = ATSUSetLayoutControls( layout, 1, &tag, &size, &value );
-       assert( result == noErr );
-
-    // The Quartz RGB fill color influences the ATSUI color
-       SetARGBFillColor( (CGContextRef) gc, argb );
-
-       // I've flipped the context to "standard" coordinates, but draw text needs it to be flipped back
-       CGContextSaveGState( (CGContextRef) gc );
-       CGContextScaleCTM( (CGContextRef) gc, 1.0, -1.0 );
-       y = -y;
-
-       // Draw text
-       result = ATSUDrawText( layout, kATSUFromTextBeginning, kATSUToTextEnd, X2Fix( x ), X2Fix( y ) );
-       assert( result == noErr );
-
-       CGContextRestoreGState( (CGContextRef) gc );
-
-       result = ATSUDisposeTextLayout( layout );
-       assert( result == noErr );
-       layout = NULL;
-
-       if ( unicodeBuffer != NULL ) {
-               CFRelease( unicodeBuffer );
-               unicodeBuffer = NULL;
-       }
-
-       CFRelease( string );
-       string = NULL;
+void Carbon$CarbonSurface::natSetSize(jint w, jint h) {
+    WindowRef window = (WindowRef) rawWindowRef;
+    Rect rect;
+    OSStatus r = GetWindowBounds(window,kWindowStructureRgn,&rect);
+    checkStatus(r,"GetWindowBounds");
+    rect.bottom = rect.top + h;
+    rect.right = rect.left + w;
+    r = SetWindowBounds(window,kWindowStructureRgn,&rect);
+    checkStatus(r,"SetWindowBounds");
+    r = ConstrainWindowToScreen(window,kWindowStructureRgn,kWindowConstrainMoveRegardlessOfFit,NULL,NULL);
+    checkStatus(r,"ConstrainWindowToScreen");
 }
 
-// CarbonSurface //////////////////////////////////////////////////////////////////////
-
-void org::xwt::plat::Carbon$CarbonSurface::setIcon(org::xwt::Picture* pic) {
-       org::xwt::plat::Carbon$CarbonPicture *picture = (org::xwt::plat::Carbon$CarbonPicture*)pic;
-
-       // TODO: This sets the dock icon. Maybe I should set the document icon (the icon beside the window title)?
-       //       or set the "window preview" that is shown when a window is collapsed?
-       // TODO: This doesn't seem to work. Maybe it is a size problem?
-       OSStatus result = SetApplicationDockTileImage( (CGImageRef) picture->image );
-       assert( result == noErr );
+void Carbon$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 = SetWindowResizeLimits(window,&min,&max);
+    checkStatus(r,"SetWindowResizeLimits");
 }
 
-void org::xwt::plat::Carbon$CarbonSurface::setTitleBarText(java::lang::String* s) {
-       CFStringRef string = JavaToCFString( s );
-       OSStatus result = SetWindowTitleWithCFString( (WindowRef) window, string );
-    assert( result == noErr );
 
-       CFRelease( string );
-       string = NULL;
+#pragma mark ------ Carbon Methods ------
+void carbon::fileDialogEventHandler(NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, void *userData) {
+    Carbon$FileDialogHelper *helper = (Carbon$FileDialogHelper*) userData;
+    NavDialogRef dialog = callBackParms->context;
+    OSStatus r;
+    switch(callBackSelector) {
+        case kNavCBUserAction: {
+            NavUserAction action = NavDialogGetUserAction(dialog);
+            if(action == kNavUserActionNone || action == kNavUserActionCancel) {
+                helper->fileName = 0;
+            } else {
+                NavReplyRecord reply;
+                r = NavDialogGetReply(dialog,&reply);
+                checkStatus(r,"NavDialogGetReply");
+
+                AEKeyword keyword;
+                FSRef ref;
+                char buf[4096];
+                r = AEGetNthPtr(&reply.selection,1,typeFSRef,&keyword,NULL,&ref,sizeof(ref),NULL);
+                checkStatus(r,"AEGetNthPtr");
+                r = FSRefMakePath(&ref,(UInt8*)buf,sizeof(buf)-1);
+                checkStatus(r,"FSRefMakePath");
+                helper->fileName = JvNewStringLatin1(buf);
+                if(helper->save) helper->saveName = cfStringToJString(reply.saveFileName);
+                r = NavDisposeReply(&reply);
+                checkStatus(r,"NavDialogGetReply");
+            }
+            helper->sem->release();
+            break;
+        }
+        case kNavCBTerminate:
+            DisposeNavEventUPP((NavEventUPP)helper->rawUPP);
+            NavDialogDispose(dialog);
+            break;
+    }
 }
 
-void org::xwt::plat::Carbon$CarbonSurface::setSize (jint width, jint height) {
-       Rect bounds;
-       OSStatus result = GetWindowBounds( (WindowRef) window, kWindowContentRgn, &bounds );
-       assert( result == noErr );
-
-       bounds.right = bounds.left + width;
-       bounds.bottom = bounds.top + height;
-       
-    result = SetWindowBounds( (WindowRef) window, kWindowContentRgn, &bounds );
-       assert( result == noErr );
-       result = ConstrainWindowToScreen( (WindowRef) window, kWindowContentRgn, kWindowConstrainStandardOptions, NULL, NULL );
-       assert( result == noErr );
-
-       fprintf( stderr, "set size (%d, %d) (%d, %d)\n", FORMAT_RECT( bounds ) );
-       // TODO: Shouldn't this deliver a "size changed" event automatically?
-       //SizeChange( width, height );
+void Carbon::natFileDialog(Carbon$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 XWT application permission to access that file.");
+    OSStatus r;
+    WindowRef window = FrontWindow();
+    NavDialogCreationOptions options;
+        
+    NavEventUPP handler = NewNavEventUPP(carbon::fileDialogEventHandler);
+    
+    NavGetDefaultDialogCreationOptions(&options);
+    options.optionFlags =
+        (options.optionFlags|kNavAllFilesInPopup|kNavSelectAllReadableItem|kNavDontUseCustomFrame|kNavDontConfirmReplacement)
+        &~(kNavAllowStationery|kNavAllowMultipleFiles);
+    options.clientName = CFSTR("XWT");
+    if(write)
+        options.saveFileName  = suggestion;
+    options.message = message;
+    options.modality = window ? kWindowModalityWindowModal : kWindowModalityAppModal;
+    options.parentWindow = window;
+    
+    if(write)
+        r = NavCreatePutFileDialog(&options,0,0,handler,helper,&dlg);
+    else
+        r = NavCreateGetFileDialog(&options,NULL,handler,NULL,NULL,helper,&dlg);
+    checkStatus(r,"NavCreate(Get/Put)FileDialog");
+    
+    helper->rawUPP = (RawData*)handler;
+    NavDialogRun(dlg);
 }
 
-void org::xwt::plat::Carbon$CarbonSurface::setLocation (jint x, jint y) {
-       Rect bounds;
-       OSStatus result = GetWindowBounds( (WindowRef) window, kWindowStructureRgn, &bounds );
-       assert( result == noErr );
-
-       int temp = bounds.right - bounds.left;
-       bounds.left = x;
-       bounds.right = x + temp;
-       temp = bounds.bottom - bounds.top;
-       bounds.top = y;
-       bounds.bottom = y + temp;
-
-    result = SetWindowBounds( (WindowRef) window, kWindowStructureRgn, &bounds );
-       assert( result == noErr );
-       result = ConstrainWindowToScreen( (WindowRef) window, kWindowStructureRgn, kWindowConstrainStandardOptions, NULL, NULL );
-       assert( result == noErr );
-
-       fprintf( stderr, "set location (%d, %d) (%d, %d)\n", FORMAT_RECT( bounds ) );
+jstring Carbon::natGetClipBoard() {
+    ScrapRef scrap;
+    OSStatus r;
+    Size size,size2;
+
+    r = GetCurrentScrap(&scrap);
+    checkStatus(r,"GetCurrentScrap");
+    
+    r = 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 = GetScrapFlavorData(scrap,kScrapFlavorTypeUnicode,&size2,buf);
+    if(r == scrapFlavorNotFoundErr);
+    checkStatus(r,"GetScrapFlavorData");
+    if(size2 != size) return JvNewStringLatin1("");
+    
+    return js;
 }
 
-void org::xwt::plat::Carbon$CarbonSurface::natInit (jboolean framed) {
-       // Create a standard window. Maybe I should be using the Appearance Manager ones?
-       OSStatus result = noErr;
-       Rect bounds;
-       bounds.left = 0;
-       bounds.top = 0;
-       bounds.right = 100;
-       bounds.bottom = 100;
-       if ( framed ) {
-               OSStatus result = CreateNewWindow( kDocumentWindowClass,
-                                                                         kWindowStandardDocumentAttributes | kWindowStandardHandlerAttribute | kWindowLiveResizeAttribute,
-                                                                         &bounds,
-                                                                         (WindowRef*) &window
-                                                                         );
-       }
-       else {
-               OSStatus result = CreateNewWindow( kPlainWindowClass,
-                                                                         kWindowStandardHandlerAttribute | kWindowLiveResizeAttribute,
-                                                                         &bounds,
-                                                                         (WindowRef*) &window
-                                                                         );
-       }
-       assert( result == noErr && window != NULL );
-
-       // Install the event handler
-       result = InstallEventHandler( GetWindowEventTarget( (WindowRef) window ),
-                                                          CarbonSurfaceEventHandler,
-                                                          GetEventTypeCount( CarbonSurfaceEventInfo ), CarbonSurfaceEventInfo,
-                                                          this,
-                                                          NULL );
-       assert( result == noErr );
-       
-       // Make sure that this window is NOT visible
-       //HideWindow( (WindowRef) window );
-}
+void Carbon::natSetClipBoard(jstring js) {
+    unsigned int length = js->length();
+    ScrapRef scrap;
+    OSStatus r;
 
-void org::xwt::plat::Carbon$CarbonSurface::toFront() {
-    BringToFront( (WindowRef) window );
-       //OSStatus result = ActivateWindow( (WindowRef) window, true );
-       //assert( result == noErr );
-
-       // Using the default "current process" or actually fetching the current process doesn't work
-       ProcessSerialNumber currentProcess = { 0, kCurrentProcess }; 
-       OSStatus result = GetCurrentProcess( &currentProcess );
-       assert( result == noErr );
-       result = SetFrontProcessWithOptions( &currentProcess, kSetFrontProcessFrontWindowOnly );
-       assert( result == noErr );
+    r = GetCurrentScrap(&scrap);
+    checkStatus(r,"GetCurrentScrap");
+    
+    r = PutScrapFlavor(scrap,kScrapFlavorTypeUnicode,0,sizeof(UniChar)*length,JvGetStringChars(js));
+    checkStatus(r,"PutScrapFlavor");
 }
 
-void org::xwt::plat::Carbon$CarbonSurface::toBack() {
-    SendBehind( (WindowRef) window, NULL );
+Proxy *Carbon::natDetectProxy() {
+    using org::xwt::Proxy;
+    Proxy *p=0;
+    CFStringRef string;
+    CFNumberRef number;
+    SmartCFString smartString;
+    CFArrayRef exceptionList;
+    int i;
+    
+    CFDictionaryRef proxyInfo = SCDynamicStoreCopyProxies(NULL);
+    if(proxyInfo == NULL) return 0;
+    
+#define doproto(proto,var) \
+    number = (CFNumberRef) CFDictionaryGetValue(proxyInfo,kSCPropNetProxies ## proto ## Enable);    \
+    if(number != NULL && CFGetTypeID(number) != CFNumberGetTypeID()) number = NULL;                 \
+    if(number && CFNumberGetValue(number,kCFNumberIntType,&i) && i) {                               \
+        string = (CFStringRef) CFDictionaryGetValue(proxyInfo, kSCPropNetProxies ## proto ## Proxy);\
+        if(string != NULL && CFGetTypeID(string) != CFStringGetTypeID()) string = NULL;             \
+        number = (CFNumberRef) CFDictionaryGetValue(proxyInfo, kSCPropNetProxies ## proto ## Port); \
+        if(number != NULL && CFGetTypeID(number) != CFNumberGetTypeID()) number = NULL;    \
+        if(string && number && CFNumberGetValue(number,kCFNumberIntType,&i) && i) {        \
+            if(!p) p = new Proxy();                                                        \
+            p->var ## ProxyHost = cfStringToJString(string);                           \
+            p->var ## ProxyPort = i;                                                   \
+        }                                                                                  \
+    }                                                                                      
+doproto(HTTP,http)
+doproto(HTTPS,https)
+doproto(SOCKS,socks)
+#undef doproto
+
+    exceptionList = (CFArrayRef) CFDictionaryGetValue(proxyInfo,kSCPropNetProxiesExceptionsList);
+    if(exceptionList != NULL && CFGetTypeID(exceptionList) != CFArrayGetTypeID()) exceptionList = NULL;
+    if(p && exceptionList && CFArrayGetCount(exceptionList)) {
+        CFIndex count = CFArrayGetCount(exceptionList);
+        p->excluded = (JArray<java::lang::String*>*)
+            JvNewObjectArray(count,&java::lang::String::class$,0);
+        for(i=0;i<count;i++) {
+            string = (CFStringRef) CFArrayGetValueAtIndex(exceptionList,i);
+            if(string != NULL && CFGetTypeID(string) != CFStringGetTypeID()) string = NULL;
+            elements(p->excluded)[i] = string ? cfStringToJString(string) : JvNewStringLatin1("(null)");
+        }
+    }
+    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::xwt::Proxy;
+    AutoARP pool;
+    Proxy *p=0;
+    NSString *host;
+    NSNumber *port;
+    NSArray *exceptionList;
+    unsigned int i;
+    NSDictionary *proxyInfo = (NSDictionary*)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;
+*/
 }
 
-void org::xwt::plat::Carbon$CarbonSurface::syncCursor() {
-       ThemeCursor curs;
-    if (cursor->equals(JvNewStringLatin1("crosshair"))) curs = kThemeCrossCursor;
-    //else if (cursor->equals(east)) curs = kThemeArrowCursor;
-    else if (cursor->equals(JvNewStringLatin1("hand"))) curs = kThemePointingHandCursor;
-    //else if (cursor->equals(move)) curs = kThemeArrowCursor;
-    //else if (cursor->equals(north)) curs = kThemeArrowCursor;
-    //else if (cursor->equals(northeast)) curs = kThemeArrowCursor;
-    //else if (cursor->equals(northwest)) curs = kThemeArrowCursor;
-    //else if (cursor->equals(south)) curs = kThemeArrowCursor;
-    //else if (cursor->equals(southeast)) curs = kThemeArrowCursor;
-    //else if (cursor->equals(southwest)) curs = kThemeArrowCursor;
-    else if (cursor->equals(JvNewStringLatin1("text"))) curs = kThemeIBeamCursor;
-    //else if (cursor->equals(west)) curs = kThemeArrowCursor;
-    else if (cursor->equals(JvNewStringLatin1("wait_string"))) curs = kThemeSpinningCursor;
-    else curs = kThemeArrowCursor;
-       
-       // TODO: This should PROBABLY be activated/deactivated when over the window using mouse tracking regions
-       SetThemeCursor( curs );
+jint Carbon::cgScreenWidth() {
+    return CGDisplayPixelsWide(kCGDirectMainDisplay);
 }
 
-void org::xwt::plat::Carbon$CarbonSurface::_dispose() {
-    ReleaseWindow( (WindowRef) window );
-       window = NULL;
+jint Carbon::cgScreenHeight() {
+    return CGDisplayPixelsHigh(kCGDirectMainDisplay);
 }
 
-void org::xwt::plat::Carbon$CarbonSurface::setInvisible(jboolean i) {
-       //fprintf( stderr, "invisible = %d\n", i );
-    if ( i ) {
-               HideWindow( (WindowRef) window );
-       } else {
-               ShowWindow( (WindowRef) window );
-       }
+void Carbon::_newBrowserWindow(jstring js) {
+    SmartCFString cfs = js;
+    CFURLRef url = CFURLCreateWithString(kCFAllocatorDefault,cfs,NULL);
+    SmartCFString scheme = CFURLCopyScheme(url);
+    if(scheme.equals(CFStringRef("http")))
+        LSOpenCFURLRef(url,NULL);
+    CFRelease(url);
 }
 
-void org::xwt::plat::Carbon$CarbonSurface::_setMaximized(jboolean b) {
-       Point ideal;
-       // TODO: Probably should use the actual screen size here
-       ideal.h = CGDisplayPixelsWide( kCGDirectMainDisplay );
-       ideal.v = CGDisplayPixelsHigh( kCGDirectMainDisplay );
-       //fprintf( stderr, "maximized = %d\n", b );
-    OSStatus result = ZoomWindowIdeal( (WindowRef) window, ( b ? inZoomOut : inZoomIn ), &ideal );
-       // TODO: It seems to work, so why does it return an error? Theory: XWT is not in a bundle.
-       assert( result == noErr );
+void Carbon::_exit() {
+    QuitApplicationEventLoop();
 }
 
-void org::xwt::plat::Carbon$CarbonSurface::_setMinimized(jboolean b) {
-    OSStatus result = CollapseWindow( (WindowRef) window, b );
-       // TODO: It seems to work, so why does it return an error? Theory: XWT is not in a bundle.
-       //assert( result == noErr );
+#define XWT_CARBON_NO_BUNDLE_HACK
+#ifdef XWT_CARBON_NO_BUNDLE_HACK
+extern "C" {
+    OSErr CPSEnableForegroundOperation(ProcessSerialNumber *psn);
+    OSErr CPSSetFrontProcess(ProcessSerialNumber *psn);
 }
-
-void org::xwt::plat::Carbon$CarbonPicture::natInit() {
-       assert( data->length == width * height );
-       image = (gnu::gcj::RawData*) CreateCGImageFromData( elements(data), width, height, kCGImageAlphaFirst );
-       assert( image != NULL );
+#endif
+void Carbon::natInit() {     
+    OSStatus r;
+    #ifdef XWT_CARBON_NO_BUNDLE_HACK
+    {        
+        ProcessSerialNumber currentProcess = { 0, kCurrentProcess };
+        
+        ::fprintf(stderr,"Doing XWT_CARBON_NO_BUNDLE_HACK\n");
+        r = GetCurrentProcess(&currentProcess);
+        checkStatus(r,"GetCurrentProcess");
+        r = CPSEnableForegroundOperation( &currentProcess );
+        checkStatus(r,"CPSEnableForegroundOperation");
+        r = 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);
+        
+        // FIXME: Install menu event handler
+    }
+    #endif
 }
 
-void org::xwt::plat::Carbon$CarbonPicture::finalize() {
-       CGImageRelease( (CGImage*) image );
-       image = NULL;
+void Carbon::_running() {
+    RunApplicationEventLoop();
+    ExitToShell();
 }
 
-// Carbon ///////////////////////////////////////////////////////////////////
+#pragma mark ------ OpenGL Functions -----
 
-jint org::xwt::plat::Carbon::_getScreenWidth() {
-       //fprintf( stderr, "screen width = %d\n", CGDisplayPixelsWide( kCGDirectMainDisplay ) );
-       return CGDisplayPixelsWide( kCGDirectMainDisplay );
+void Carbon$CarbonOpenGL::activateSharedContext() {
+    AGLContext ctx = (AGLContext) rawSharedContext;
+    aglSetCurrentContext(ctx);
 }
 
-jint org::xwt::plat::Carbon::_getScreenHeight() {
-       //fprintf( stderr, "screen height = %d\n", CGDisplayPixelsHigh( kCGDirectMainDisplay ) );
-    return CGDisplayPixelsHigh( kCGDirectMainDisplay );
+jboolean Carbon$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*) aglChoosePixelFormat(NULL,0,attr);
+    return rawPixelFormat != 0;
 }
 
-jstring org::xwt::plat::Carbon::_getClipBoard() {
-       // Get the clipboard reference
-       ScrapRef scrap = NULL;
-       OSStatus result = GetCurrentScrap( &scrap );
-       assert( result == noErr );
-
-       ScrapFlavorFlags flavorFlags;
-       result = GetScrapFlavorFlags ( scrap, kScrapFlavorTypeUnicode, &flavorFlags );
-
-       if ( result == noErr ) {
-               // No error, we have unicode data in a Scrap. Find out how many bytes of data it is.
-               Size bytes = 0;
-               result = GetScrapFlavorSize( scrap, kScrapFlavorTypeUnicode, &bytes );
-               assert( result == noErr );
-               const Size numUniChars = bytes / sizeof( UniChar );
-
-               // Allocate a buffer for the text using Core Foundation
-               UniChar* buffer = reinterpret_cast<UniChar*>( CFAllocatorAllocate( NULL, bytes, 0 ) );
-               assert( buffer != NULL );
-
-               // Get a copy of the text
-               Size nextBytes = bytes;
-               result = GetScrapFlavorData( scrap, kScrapFlavorTypeUnicode, &nextBytes, buffer );
-               assert( result == noErr );
-
-               // Create a CFString which wraps and takes ownership of the buffer
-               CFStringRef string = CFStringCreateWithCharactersNoCopy( NULL, buffer, numUniChars, NULL );
-               assert( string != NULL );
-               buffer = NULL; // string now owns this buffer
-
-               jstring ret = CFToJavaString( string );
-
-               // Default allocator releases both the CFString and the UniChar buffer (text)
-               CFRelease( string );
-               string = NULL;
-
-               return ret;
-       } else {
-               return JvNewStringLatin1("");
-       }       
+void Carbon$CarbonOpenGL::initSharedContext() {
+    AGLPixelFormat fmt =  (AGLPixelFormat) rawPixelFormat;
+    rawSharedContext = (RawData*) aglCreateContext(fmt,NULL);
+    checkStatus(rawSharedContext,"aglCreateContext");
 }
 
-void org::xwt::plat::Carbon::_setClipBoard(jstring s) {
-       CFStringRef string = JavaToCFString( s );
-
-       OSStatus result = ClearCurrentScrap();
-       assert( result == noErr );
-
-       ScrapRef scrap = NULL;
-       result = GetCurrentScrap( &scrap );
-       assert( result == noErr );
-
-       CFIndex numUniChars = CFStringGetLength( string );
-
-       // Try to get a pointer to the unicode data first, then do the copy if needed
-       const UniChar* buffer = CFStringGetCharactersPtr( string );
-       if ( buffer != NULL )
-               {
-               result = PutScrapFlavor ( scrap, kScrapFlavorTypeUnicode, 0, sizeof( UniChar ) * numUniChars, buffer );
-               assert( result == noErr );
-               }
-       else
-               {
-               UniChar* buffer = (UniChar*) malloc( sizeof( UniChar ) * numUniChars );
-               assert( buffer != NULL );
-               CFStringGetCharacters( string, CFRangeMake( 0, numUniChars ), buffer );
-
-               result = PutScrapFlavor ( scrap, kScrapFlavorTypeUnicode, 0, sizeof( UniChar ) * numUniChars, buffer );
-               assert( result == noErr );
-
-               // Done with the UniChar* buffer
-               free( buffer );
-               buffer = NULL;
-               }
-               
-       // Done with the CFString
-       CFRelease( string );
-       string = NULL;
+void Carbon$GLCarbonDoubleBuffer::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 = CreateNewWindow(wc,attr,&rect,&window);
+    checkStatus(r,"CreateNewWindow");
+        
+    shared = (AGLContext) gl->rawSharedContext;
+    fmt = (AGLPixelFormat) gl->rawPixelFormat;
+    ctx = aglCreateContext(fmt,shared);
+    checkStatus(ctx, "aglCreateContext");
+    
+    b = aglSetDrawable(ctx,GetWindowPort(window));
+    checkStatus(b,"aglSetDrawable");
+    
+    aglSetCurrentContext(ctx);
+    aglUpdateContext(ctx);
+    drawableInit(width,height);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    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);
+    aglSurfaceTexture (shared, target, GL_RGBA, ctx);
+    checkGLError();
+    glDisable(target);
+    
+    //ShowWindow(window);
+    textureName = (jint) tex;
+    rawWindowRef = (RawData*) window;
+    rawCTX = (RawData*) ctx;
 }
 
-/*
-JArray<java::lang::String*>* org::xwt::plat::Carbon::listNativeFonts() {
-       ATSFontFamilyIterator iterator;
-       OSStatus result = ATSFontFamilyIteratorCreate( kATSFontContextUnspecified, NULL, NULL, kATSOptionFlagsDefault, &iterator );
-       if ( result != noErr ) throw new java::lang::Error(JvNewStringLatin1("ASSERT"));
-
-       // Iterate over fonts twice: The first time just to count the fonts so we can create the array
-       // The second time gets the font names
-       ATSFontFamilyRef font = NULL;
-       int i = -1;
-       while ( result == noErr )
-               {
-               i ++;
-               result = ATSFontFamilyIteratorNext( iterator, &font );
-               }
-       if ( result != kATSIterationCompleted ) throw new java::lang::Error(JvNewStringLatin1("ASSERT"));
-
-       result = ATSFontFamilyIteratorReset( kATSFontContextUnspecified, NULL, NULL, kATSOptionFlagsDefault, &iterator );
-       if ( result != noErr ) throw new java::lang::Error(JvNewStringLatin1("ASSERT"));
-
-       JArray<jstring>* fonts = (JArray<jstring>*)JvNewObjectArray( i, &(::java::lang::String::class$), NULL);
-
-       ATSFontFamilyRef font = NULL;
-       result = ATSFontFamilyIteratorNext( iterator, &font );
-       while( result == noErr )
-               {
-               CFStringRef name = NULL;
-               result = ATSFontFamilyGetName( font, kATSOptionFlagsDefault, &name );
-               if ( result != noErr || name == NULL ) throw new java::lang::Error(JvNewStringLatin1("ASSERT"));
-
-               //const char* cstring = CFStringGetCStringPtr( name, kCFStringEncodingMacRoman );
-               //if ( cstring != NULL ) fprintf( stderr, "%s\n", cstring );
-               
-               jstring xwtName = CFToJavaString( name );
-
-               // 
-               xwtName = xwtName->replace(' ', '_')->toLowerCase()->concat( "0" ); 
-               CFRelease( name );
-               name = NULL;
-
-               result = ATSFontFamilyIteratorNext( iterator, &font );
-               i ++;
-               }
-       if ( result != kATSIterationCompleted ) throw new java::lang::Error(JvNewStringLatin1("ASSERT"));
-
-       result = ATSFontFamilyIteratorRelease ( &iterator );
-       if ( result != noErr ) throw new java::lang::Error(JvNewStringLatin1("ASSERT"));
-
-    return fonts;
+void Carbon$GLCarbonDoubleBuffer::activateContext() {
+    AGLContext ctx = (AGLContext) rawCTX;
+    aglSetCurrentContext(ctx);
 }
-*/
-
 
-/*gnu::gcj::RawData* org::xwt::plat::Carbon::fontStringToStruct(jstring s) {
-    throw new java::lang::Error(JvNewStringLatin1("FIXME"));
-}*/
-
-// HACK: WARNING: Undocumented Hack! This may break in the future
-// For now, however, it allows a non-bundled app to create Windows! Yay!
-extern "C" { OSErr CPSEnableForegroundOperation(ProcessSerialNumber *psn); }
-
-void org::xwt::plat::Carbon::natInit() {
-       // HACK: WARNING: Undocumented Hack! This may break in the future
-       // For now, however, it allows a non-bundled app to create Windows! Yay!
-       ProcessSerialNumber currentProcess = { 0, kCurrentProcess }; // Using the default "current process" doesn't work
-       OSStatus result = GetCurrentProcess( &currentProcess );
-       assert( result == noErr );
-       result = CPSEnableForegroundOperation( &currentProcess );
-       assert( result == noErr );
-
-       // Initiaize the native font hashtable
-       // Get a copy of all available fonts
-       ItemCount numFonts;
-       result = ATSUFontCount( &numFonts );
-       assert( result == noErr );
-
-       ATSFontRef* fonts = (ATSFontRef*) malloc( sizeof(ATSFontRef) * numFonts );
-       assert( fonts != NULL );
-
-       ItemCount currentNumFonts;
-       result = ATSUGetFontIDs( fonts, numFonts, &currentNumFonts );
-       assert( result == noErr );
-       numFonts = min( currentNumFonts, numFonts ); // Just to be safe, maybe the number of fonts changed (unlikely!)
-
-       const ByteCount MAX_NAME_LENGTH = 100;
-       char familyName[MAX_NAME_LENGTH+1];
-       for ( ItemCount i = 0; i < numFonts; i ++ ) {
-               ByteCount actualBytes = 0;
-               result = ATSUFindFontName( fonts[i], kFontFamilyName, (FontPlatformCode) kFontMacintoshPlatform, kFontNoScriptCode, kFontNoLanguageCode,
-                                                         MAX_NAME_LENGTH, familyName, &actualBytes, NULL );
-
-               // If we were able to get a macintosh string for the font family name, use it to make a jstring
-               if ( result == noErr && actualBytes > 0 )
-                       {
-                       familyName[actualBytes] = '\0';
-
-                       jstring xwtName = JvNewStringLatin1( familyName, actualBytes );
-
-                       // Convert the font family name to an XWT font name
-                       xwtName = xwtName->replace(' ', '_')->toLowerCase();
-                       // Map the first font we find to this family name. The first font is the "Regular" font.
-                       if ( nativeFontCache->get( xwtName ) == NULL )
-                               nativeFontCache->put( (java::lang::Object*) xwtName, new org::xwt::plat::Carbon$WrappedRawData( (::gnu::gcj::RawData*) fonts[i] ) );
-                       }
-               else
-                       {
-                       //fprintf( stderr, "FONT HAS NO MAC NAME\n" );
-                       }
-       }
-       
-       free( fonts );
-       fonts = NULL;
+void Carbon$GLCarbonDoubleBuffer::natCleanup(RawData* rawWindowRef, RawData* rawCTX) {
+    WindowRef window = (WindowRef) rawWindowRef;
+    AGLContext ctx = (AGLContext) rawCTX;
+    aglDestroyContext(ctx);
+    DisposeWindow(window);
 }
 
-jint org::xwt::plat::Carbon::_stringWidth(::java::lang::String* font, ::java::lang::String* text) {
-       // If the string doesn't have any characters, return zero immediately 
-       if ( text->length() == 0 ) return 0;
-       
-       ATSUStyle style = (ATSUStyle) _getATSUStyle( font );
-       CFStringRef string = JavaToCFString( text );
-
-       CFStringRef unicodeBuffer = NULL;
-       ATSUTextLayout layout = CreateTextLayout( string, style, &unicodeBuffer );
-
-       unsigned long actualNumberOfBounds = 0;
-       ATSTrapezoid glyphBounds;
-
-       // We get a single bound, since the text should only require one. If it requires more, there is an issue
-       OSStatus result = ATSUGetGlyphBounds( layout, 0, 0, kATSUFromTextBeginning, kATSUToTextEnd, kATSUseDeviceOrigins, 1, &glyphBounds, &actualNumberOfBounds );
-       assert( result == noErr && actualNumberOfBounds == 1 );
-
-       ATSUDisposeTextLayout( layout );
-       layout = NULL;
-
-       if ( unicodeBuffer != NULL ) {
-               CFRelease( unicodeBuffer );
-               unicodeBuffer = NULL;
-               }
-
-       CFRelease( string );
-       string = NULL;
-
-       return Fix2Long( glyphBounds.upperRight.x - glyphBounds.upperLeft.x );
+void Carbon$GLCarbonSurface::natBlit(Carbon$GLCarbonDoubleBuffer *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);
+    db->activateContext();
+    glFlush();
+    checkGLError();
+    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();
+    }
+    glFlush();
 }
 
-jint org::xwt::plat::Carbon::_getMaxAscent(::java::lang::String* font) {
-       ATSUStyle style = (ATSUStyle) _getATSUStyle( font );
-       
-       ByteCount actualSize = 0;
-       ATSUTextMeasurement ascent;
-       OSStatus result = ATSUGetAttribute( style, kATSUAscentTag, sizeof( ascent ), &ascent, &actualSize );
-       assert( result == kATSUNotSetErr );
-
-       //fprintf( stderr, "ascent = %ld\n", Fix2Long( ascent ) );
-
-       return Fix2Long( ascent );
+void Carbon$GLCarbonSurface::natReshape(jint w, jint h) {
+    AGLContext ctx = (AGLContext) rawCTX;
+    
+    aglSetCurrentContext (ctx);
+    aglUpdateContext(ctx);
+    
+    glViewport(0, 0, w, h);
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity(); 
+    glOrtho(0, w, h, 0, -1, 1);   
+    glMatrixMode(GL_MODELVIEW);
+    glLoadIdentity();
+    glTranslatef (0.375, 0.375, 0.0);
+    checkGLError();
 }
-jint org::xwt::plat::Carbon::_getMaxDescent(::java::lang::String* font) {
-       ATSUStyle style = (ATSUStyle) _getATSUStyle( font );
-
-       ByteCount actualSize = 0;
-       ATSUTextMeasurement descent;
-       OSStatus result = ATSUGetAttribute( style, kATSUDescentTag, sizeof( descent ), &descent, &actualSize );
-       assert( result == kATSUNotSetErr );
-
-       //fprintf( stderr, "descent = %ld\n", Fix2Long( descent ) );
 
-       return Fix2Long( descent );
+void Carbon$GLCarbonSurface::natInit() {
+    WindowRef window = (WindowRef) rawWindowRef;
+    AGLContext ctx,shared;
+    AGLPixelFormat fmt;
+    GLboolean b;
+    
+    shared = (AGLContext) gl->rawSharedContext;
+    fmt = (AGLPixelFormat) gl->rawPixelFormat;
+    ctx = aglCreateContext(fmt,shared);
+    checkStatus(ctx, "aglCreateContext");
+    
+    b = aglSetDrawable(ctx,GetWindowPort(window));
+    checkStatus(b,"aglSetDrawable");
+
+    aglSetCurrentContext(ctx);
+    checkGLError();
+    
+    rawCTX = (RawData*)ctx;
+    
+    reshape(10,10);
+
+    aglSetCurrentContext(ctx);
+    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
 }
 
-gnu::gcj::RawData* org::xwt::plat::Carbon::_createATSUStyle( gnu::gcj::RawData* fontRef, jint fontSize, jboolean isBold, jboolean isItalic, jboolean isUnderline ) {
-       ATSUStyle style;
-       OSStatus result = ATSUCreateStyle( &style );
-       assert( result == noErr && style != NULL );
-
-    // Font
-    ATSFontRef font = (ATSFontRef) fontRef;
-       Fixed size = X2Fix( fontSize );
-       Boolean bold = isBold;
-       Boolean italic = isItalic;
-       Boolean underline = isUnderline;
-
-       const ATSUAttributeTag tags[] = { kATSUFontTag, kATSUSizeTag, kATSUQDBoldfaceTag, kATSUQDItalicTag, kATSUQDUnderlineTag };
-       ByteCount sizes[] = { sizeof( font ), sizeof( size ), sizeof( bold ), sizeof( italic ), sizeof( underline ) };
-       ATSUAttributeValuePtr values[] = { &font, &size, &bold, &italic, &underline };
-
-       result = ATSUSetAttributes( style, sizeof( tags ) / sizeof( *tags ), tags, sizes, values );
-       assert( result == noErr );
-
-       // TODO: Why do I have to turn this off manually? This shouldn't this be the default?
-       ATSUFontFeatureType featureType = kLigaturesType;
-       ATSUFontFeatureSelector selector = kCommonLigaturesOffSelector;
-       result = ATSUSetFontFeatures( style, 1, &featureType, &selector );
-       assert( result == noErr );
-
-       return (gnu::gcj::RawData*) style;
+void Carbon$GLCarbonSurface::natDispose() {
+    AGLContext ctx = (AGLContext) rawCTX;
+    aglDestroyContext(ctx);
+    Carbon$CarbonSurface::natDispose();
 }
 
-
-/** Called once XWT is initialized and the application is running. */
-void org::xwt::plat::Carbon::_running() {
-       // TODO: This is going to be a bit magical:
-       // Let's see what happens when we mix multithreading and OS X applications.
-       // Theory: Bad stuff may happen if events are delivered and other stuff is going on at
-       // the same time. However, I'm going to pray that XWT's Java stuff locks things for me,
-       // So by the time I call into the Java code, i'm the only code path active?
-       RunApplicationEventLoop();
-
-       org::xwt::plat::Carbon::exit(); 
-}
+} } } // end namepsace org::xwt::plat