diff --git a/src/osx/carbon/Info.plist.in b/src/osx/carbon/Info.plist.in
new file mode 100644
index 0000000000..de35d6de27
--- /dev/null
+++ b/src/osx/carbon/Info.plist.in
@@ -0,0 +1,36 @@
+
+
+
+
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleIdentifier
+ org.wxwindows.IDENTIFIER
+ CFBundleDevelopmentRegion
+ English
+ CFBundleExecutable
+ EXECUTABLE
+ CFBundleIconFile
+ wxmac.icns
+ CFBundleName
+ EXECUTABLE
+ CFBundlePackageType
+ APPL
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ VERSION
+ CFBundleShortVersionString
+ VERSION
+ CFBundleGetInfoString
+ EXECUTABLE version VERSION, (c) 2002-2006 wxWidgets
+ CFBundleLongVersionString
+ VERSION, (c) 2002-2006 wxWidgets
+ NSHumanReadableCopyright
+ Copyright 2002-2006 wxWidgets
+ LSRequiresCarbon
+
+ CSResourcesFileMapped
+
+
+
diff --git a/src/osx/carbon/aboutdlg.cpp b/src/osx/carbon/aboutdlg.cpp
new file mode 100644
index 0000000000..243de8b7d7
--- /dev/null
+++ b/src/osx/carbon/aboutdlg.cpp
@@ -0,0 +1,92 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name: mac/carbon/aboutdlg.cpp
+// Purpose: native wxAboutBox() implementation for wxMac
+// Author: Vadim Zeitlin
+// Created: 2006-10-08
+// RCS-ID: $Id$
+// Copyright: (c) 2006 Vadim Zeitlin
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+// for compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#if wxUSE_ABOUTDLG
+
+#ifndef WX_PRECOMP
+#endif //WX_PRECOMP
+
+#include "wx/aboutdlg.h"
+#include "wx/generic/aboutdlgg.h"
+
+#include "wx/mac/private.h"
+
+// helper class for HIAboutBox options
+class AboutBoxOptions : public wxCFRef
+{
+public:
+ AboutBoxOptions() : wxCFRef
+ (
+ CFDictionaryCreateMutable
+ (
+ kCFAllocatorDefault,
+ 4, // there are at most 4 values
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks
+ )
+ )
+ {
+ }
+
+ void Set(CFStringRef key, const wxString& value)
+ {
+ CFDictionarySetValue(*this, key, wxCFStringRef(value));
+ }
+};
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+void wxAboutBox(const wxAboutDialogInfo& info)
+{
+ // Mac native about box currently can show only name, version, copyright
+ // and description fields and we also shoehorn the credits text into the
+ // description but if we have anything else we must use the generic version
+#ifndef __LP64__
+ if ( info.IsSimple() )
+ {
+ AboutBoxOptions opts;
+
+ opts.Set(kHIAboutBoxNameKey, info.GetName());
+
+ if ( info.HasVersion() )
+ {
+ opts.Set(kHIAboutBoxVersionKey,
+ wxString::Format(_("Version %s"), info.GetVersion()));
+ }
+
+ if ( info.HasCopyright() )
+ opts.Set(kHIAboutBoxCopyrightKey, info.GetCopyright());
+
+ opts.Set(kHIAboutBoxDescriptionKey, info.GetDescriptionAndCredits());
+
+ HIAboutBox(opts);
+ }
+ else // simple "native" version is not enough
+#endif
+ {
+ // we need to use the full-blown generic version
+ wxGenericAboutBox(info);
+ }
+}
+
+#endif // wxUSE_ABOUTDLG
diff --git a/src/osx/carbon/accel.cpp b/src/osx/carbon/accel.cpp
new file mode 100644
index 0000000000..f33bbe28e0
--- /dev/null
+++ b/src/osx/carbon/accel.cpp
@@ -0,0 +1,109 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/accel.cpp
+// Purpose: wxAcceleratorTable
+// Author: Stefan Csomor
+// Modified by:
+// Created: 1998-01-01
+// RCS-ID: $Id$
+// Copyright: (c) Stefan Csomor
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/wxprec.h"
+
+#include "wx/accel.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/string.h"
+#endif
+
+#ifndef __WXUNIVERSAL__
+
+IMPLEMENT_DYNAMIC_CLASS(wxAcceleratorTable, wxObject)
+
+// ----------------------------------------------------------------------------
+// wxAccelList: a list of wxAcceleratorEntries
+// ----------------------------------------------------------------------------
+
+WX_DECLARE_LIST(wxAcceleratorEntry, wxAccelList);
+#include "wx/listimpl.cpp"
+WX_DEFINE_LIST(wxAccelList)
+
+// ----------------------------------------------------------------------------
+// wxAccelRefData: the data used by wxAcceleratorTable
+// ----------------------------------------------------------------------------
+
+class WXDLLEXPORT wxAcceleratorRefData: public wxObjectRefData
+{
+ friend class wxAcceleratorTable;
+public:
+ wxAcceleratorRefData();
+ virtual ~wxAcceleratorRefData();
+
+ wxAccelList m_accels;
+};
+
+#define M_ACCELDATA ((wxAcceleratorRefData *)m_refData)
+
+wxAcceleratorRefData::wxAcceleratorRefData()
+ : m_accels()
+{
+}
+
+wxAcceleratorRefData::~wxAcceleratorRefData()
+{
+ WX_CLEAR_LIST( wxAccelList, m_accels );
+}
+
+wxAcceleratorTable::wxAcceleratorTable()
+{
+ m_refData = NULL;
+}
+
+wxAcceleratorTable::~wxAcceleratorTable()
+{
+}
+
+// Create from an array
+wxAcceleratorTable::wxAcceleratorTable(int n, const wxAcceleratorEntry entries[])
+{
+ m_refData = new wxAcceleratorRefData;
+
+ for (int i = 0; i < n; i++)
+ {
+ int flag = entries[i].GetFlags();
+ int keycode = entries[i].GetKeyCode();
+ int command = entries[i].GetCommand();
+ if ((keycode >= (int)'a') && (keycode <= (int)'z')) keycode = (int)toupper( (char)keycode );
+ M_ACCELDATA->m_accels.Append( new wxAcceleratorEntry( flag, keycode, command ) );
+ }
+}
+
+bool wxAcceleratorTable::IsOk() const
+{
+ return (m_refData != NULL);
+}
+
+int wxAcceleratorTable::GetCommand( wxKeyEvent &event )
+{
+ if (!Ok()) return -1;
+
+ wxAccelList::compatibility_iterator node = M_ACCELDATA->m_accels.GetFirst();
+ while (node)
+ {
+ wxAcceleratorEntry *entry = node->GetData();
+ if ((event.m_keyCode == entry->GetKeyCode()) &&
+ (((entry->GetFlags() & wxACCEL_CTRL) != 0) == event.ControlDown()) &&
+ (((entry->GetFlags() & wxACCEL_SHIFT) != 0) == event.ShiftDown()) &&
+ (((entry->GetFlags() & wxACCEL_ALT) != 0) == event.AltDown()) &&
+ (((entry->GetFlags() & wxACCEL_CMD) != 0) == event.CmdDown()))
+ {
+ return entry->GetCommand();
+ }
+ node = node->GetNext();
+ }
+
+ return -1;
+}
+
+#endif
\ No newline at end of file
diff --git a/src/osx/carbon/app.cpp b/src/osx/carbon/app.cpp
new file mode 100644
index 0000000000..a75a511279
--- /dev/null
+++ b/src/osx/carbon/app.cpp
@@ -0,0 +1,1648 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/app.cpp
+// Purpose: wxApp
+// Author: Stefan Csomor
+// Modified by:
+// Created: 1998-01-01
+// RCS-ID: $Id$
+// Copyright: (c) Stefan Csomor
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/wxprec.h"
+
+#include "wx/app.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/intl.h"
+ #include "wx/log.h"
+ #include "wx/utils.h"
+ #include "wx/window.h"
+ #include "wx/frame.h"
+ #include "wx/dc.h"
+ #include "wx/button.h"
+ #include "wx/menu.h"
+ #include "wx/pen.h"
+ #include "wx/brush.h"
+ #include "wx/palette.h"
+ #include "wx/icon.h"
+ #include "wx/cursor.h"
+ #include "wx/dialog.h"
+ #include "wx/msgdlg.h"
+ #include "wx/textctrl.h"
+ #include "wx/memory.h"
+ #include "wx/gdicmn.h"
+ #include "wx/module.h"
+#endif
+
+#include "wx/tooltip.h"
+#include "wx/docview.h"
+#include "wx/filename.h"
+#include "wx/link.h"
+#include "wx/thread.h"
+
+#include
+
+// mac
+
+#include "wx/mac/uma.h"
+
+#ifdef __DARWIN__
+# include
+# if defined(WXMAKINGDLL_CORE)
+# include
+# endif
+#endif
+
+// Keep linker from discarding wxStockGDIMac
+wxFORCE_LINK_MODULE(gdiobj)
+
+// statics for implementation
+static bool s_inYield = false;
+static bool s_inReceiveEvent = false ;
+static EventTime sleepTime = kEventDurationNoWait ;
+
+
+IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
+BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
+ EVT_IDLE(wxApp::OnIdle)
+ EVT_END_SESSION(wxApp::OnEndSession)
+ EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
+END_EVENT_TABLE()
+
+
+// platform specific static variables
+static const short kwxMacAppleMenuId = 1 ;
+
+wxWindow* wxApp::s_captureWindow = NULL ;
+long wxApp::s_lastModifiers = 0 ;
+
+long wxApp::s_macAboutMenuItemId = wxID_ABOUT ;
+long wxApp::s_macPreferencesMenuItemId = wxID_PREFERENCES ;
+long wxApp::s_macExitMenuItemId = wxID_EXIT ;
+wxString wxApp::s_macHelpMenuTitleName = wxT("&Help") ;
+
+bool wxApp::sm_isEmbedded = false; // Normally we're not a plugin
+
+//----------------------------------------------------------------------
+// Core Apple Event Support
+//----------------------------------------------------------------------
+
+pascal OSErr AEHandleODoc( const AppleEvent *event , AppleEvent *reply , SRefCon refcon ) ;
+pascal OSErr AEHandleOApp( const AppleEvent *event , AppleEvent *reply , SRefCon refcon ) ;
+pascal OSErr AEHandlePDoc( const AppleEvent *event , AppleEvent *reply , SRefCon refcon ) ;
+pascal OSErr AEHandleQuit( const AppleEvent *event , AppleEvent *reply , SRefCon refcon ) ;
+pascal OSErr AEHandleRApp( const AppleEvent *event , AppleEvent *reply , SRefCon refcon ) ;
+
+pascal OSErr AEHandleODoc( const AppleEvent *event , AppleEvent *reply , SRefCon WXUNUSED(refcon) )
+{
+ return wxTheApp->MacHandleAEODoc( (AppleEvent*) event , reply) ;
+}
+
+pascal OSErr AEHandleOApp( const AppleEvent *event , AppleEvent *reply , SRefCon WXUNUSED(refcon) )
+{
+ return wxTheApp->MacHandleAEOApp( (AppleEvent*) event , reply ) ;
+}
+
+pascal OSErr AEHandlePDoc( const AppleEvent *event , AppleEvent *reply , SRefCon WXUNUSED(refcon) )
+{
+ return wxTheApp->MacHandleAEPDoc( (AppleEvent*) event , reply ) ;
+}
+
+pascal OSErr AEHandleQuit( const AppleEvent *event , AppleEvent *reply , SRefCon WXUNUSED(refcon) )
+{
+ return wxTheApp->MacHandleAEQuit( (AppleEvent*) event , reply) ;
+}
+
+pascal OSErr AEHandleRApp( const AppleEvent *event , AppleEvent *reply , SRefCon WXUNUSED(refcon) )
+{
+ return wxTheApp->MacHandleAERApp( (AppleEvent*) event , reply) ;
+}
+
+pascal OSErr AEHandleGURL( const AppleEvent *event , AppleEvent *reply , SRefCon WXUNUSED(refcon) )
+{
+ return wxTheApp->MacHandleAEGURL((WXEVENTREF *)event , reply) ;
+}
+
+
+// AEODoc Calls MacOpenFile on each of the files passed
+
+short wxApp::MacHandleAEODoc(const WXEVENTREF event, WXEVENTREF WXUNUSED(reply))
+{
+ AEDescList docList;
+ AEKeyword keywd;
+ DescType returnedType;
+ Size actualSize;
+ long itemsInList;
+ OSErr err;
+ short i;
+
+ err = AEGetParamDesc((AppleEvent *)event, keyDirectObject, typeAEList,&docList);
+ if (err != noErr)
+ return err;
+
+ err = AECountItems(&docList, &itemsInList);
+ if (err != noErr)
+ return err;
+
+ ProcessSerialNumber PSN ;
+ PSN.highLongOfPSN = 0 ;
+ PSN.lowLongOfPSN = kCurrentProcess ;
+ SetFrontProcess( &PSN ) ;
+
+ wxString fName ;
+ FSRef theRef ;
+
+ for (i = 1; i <= itemsInList; i++)
+ {
+ AEGetNthPtr(
+ &docList, i, typeFSRef, &keywd, &returnedType,
+ (Ptr)&theRef, sizeof(theRef), &actualSize);
+ fName = wxMacFSRefToPath( &theRef ) ;
+
+ MacOpenFile(fName);
+ }
+
+ return noErr;
+}
+
+// AEODoc Calls MacOpenURL on the url passed
+
+short wxApp::MacHandleAEGURL(const WXEVENTREF event, WXEVENTREF WXUNUSED(reply))
+{
+ DescType returnedType;
+ Size actualSize;
+ char url[255];
+ OSErr err = AEGetParamPtr((AppleEvent *)event, keyDirectObject, typeChar,
+ &returnedType, url, sizeof(url)-1,
+ &actualSize);
+ if (err != noErr)
+ return err;
+
+ url[actualSize] = '\0'; // Terminate the C string
+
+ ProcessSerialNumber PSN ;
+ PSN.highLongOfPSN = 0 ;
+ PSN.lowLongOfPSN = kCurrentProcess ;
+ SetFrontProcess( &PSN ) ;
+
+ MacOpenURL(wxString(url, wxConvUTF8));
+
+ return noErr;
+}
+
+// AEPDoc Calls MacPrintFile on each of the files passed
+
+short wxApp::MacHandleAEPDoc(const WXEVENTREF event , WXEVENTREF WXUNUSED(reply))
+{
+ AEDescList docList;
+ AEKeyword keywd;
+ DescType returnedType;
+ Size actualSize;
+ long itemsInList;
+ OSErr err;
+ short i;
+
+ err = AEGetParamDesc((AppleEvent *)event, keyDirectObject, typeAEList,&docList);
+ if (err != noErr)
+ return err;
+
+ err = AECountItems(&docList, &itemsInList);
+ if (err != noErr)
+ return err;
+
+ ProcessSerialNumber PSN ;
+ PSN.highLongOfPSN = 0 ;
+ PSN.lowLongOfPSN = kCurrentProcess ;
+ SetFrontProcess( &PSN ) ;
+
+ wxString fName ;
+ FSRef theRef ;
+
+ for (i = 1; i <= itemsInList; i++)
+ {
+ AEGetNthPtr(
+ &docList, i, typeFSRef, &keywd, &returnedType,
+ (Ptr)&theRef, sizeof(theRef), &actualSize);
+ fName = wxMacFSRefToPath( &theRef ) ;
+
+ MacPrintFile(fName);
+ }
+
+ return noErr;
+}
+
+// AEOApp calls MacNewFile
+
+short wxApp::MacHandleAEOApp(const WXEVENTREF WXUNUSED(event) , WXEVENTREF WXUNUSED(reply))
+{
+ MacNewFile() ;
+ return noErr ;
+}
+
+// AEQuit attempts to quit the application
+
+short wxApp::MacHandleAEQuit(const WXEVENTREF WXUNUSED(event) , WXEVENTREF WXUNUSED(reply))
+{
+ wxWindow* win = GetTopWindow() ;
+ if ( win )
+ {
+ wxCommandEvent exitEvent(wxEVT_COMMAND_MENU_SELECTED, s_macExitMenuItemId);
+ if (!win->ProcessEvent(exitEvent))
+ win->Close(true) ;
+ }
+ else
+ {
+ ExitMainLoop() ;
+ }
+
+ return noErr ;
+}
+
+// AEROApp calls MacReopenApp
+
+short wxApp::MacHandleAERApp(const WXEVENTREF WXUNUSED(event) , WXEVENTREF WXUNUSED(reply))
+{
+ MacReopenApp() ;
+
+ return noErr ;
+}
+
+//----------------------------------------------------------------------
+// Support Routines linking the Mac...File Calls to the Document Manager
+//----------------------------------------------------------------------
+
+void wxApp::MacOpenFile(const wxString & fileName )
+{
+#if wxUSE_DOC_VIEW_ARCHITECTURE
+ wxDocManager* dm = wxDocManager::GetDocumentManager() ;
+ if ( dm )
+ dm->CreateDocument(fileName , wxDOC_SILENT ) ;
+#endif
+}
+
+void wxApp::MacOpenURL(const wxString & WXUNUSED(url) )
+{
+}
+
+void wxApp::MacPrintFile(const wxString & fileName )
+{
+#if wxUSE_DOC_VIEW_ARCHITECTURE
+
+#if wxUSE_PRINTING_ARCHITECTURE
+ wxDocManager* dm = wxDocManager::GetDocumentManager() ;
+ if ( dm )
+ {
+ wxDocument *doc = dm->CreateDocument(fileName , wxDOC_SILENT ) ;
+ if ( doc )
+ {
+ wxView* view = doc->GetFirstView() ;
+ if ( view )
+ {
+ wxPrintout *printout = view->OnCreatePrintout();
+ if (printout)
+ {
+ wxPrinter printer;
+ printer.Print(view->GetFrame(), printout, true);
+ delete printout;
+ }
+ }
+
+ if (doc->Close())
+ {
+ doc->DeleteAllViews();
+ dm->RemoveDocument(doc) ;
+ }
+ }
+ }
+#endif //print
+
+#endif //docview
+}
+
+
+
+void wxApp::MacNewFile()
+{
+}
+
+void wxApp::MacReopenApp()
+{
+ // HIG says :
+ // if there is no open window -> create a new one
+ // if all windows are hidden -> show the first
+ // if some windows are not hidden -> do nothing
+
+ wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst();
+ if ( node == NULL )
+ {
+ MacNewFile() ;
+ }
+ else
+ {
+ wxTopLevelWindow* firstIconized = NULL ;
+ wxTopLevelWindow* firstHidden = NULL ;
+ while (node)
+ {
+ wxTopLevelWindow* win = (wxTopLevelWindow*) node->GetData();
+ if ( !win->IsShown() )
+ {
+ // make sure we don't show 'virtual toplevel windows' like wxTaskBarIconWindow
+ if ( firstHidden == NULL && ( wxDynamicCast( win, wxFrame ) || wxDynamicCast( win, wxDialog ) ) )
+ firstHidden = win ;
+ }
+ else if ( win->IsIconized() )
+ {
+ if ( firstIconized == NULL )
+ firstIconized = win ;
+ }
+ else
+ {
+ // we do have a visible, non-iconized toplevelwindow -> do nothing
+ return;
+ }
+
+ node = node->GetNext();
+ }
+
+ if ( firstIconized )
+ firstIconized->Iconize( false ) ;
+ else if ( firstHidden )
+ firstHidden->Show( true );
+ }
+}
+
+//----------------------------------------------------------------------
+// Macintosh CommandID support - converting between native and wx IDs
+//----------------------------------------------------------------------
+
+// if no native match they just return the passed-in id
+
+struct IdPair
+{
+ UInt32 macId ;
+ int wxId ;
+} ;
+
+IdPair gCommandIds [] =
+{
+ { kHICommandCut , wxID_CUT } ,
+ { kHICommandCopy , wxID_COPY } ,
+ { kHICommandPaste , wxID_PASTE } ,
+ { kHICommandSelectAll , wxID_SELECTALL } ,
+ { kHICommandClear , wxID_CLEAR } ,
+ { kHICommandUndo , wxID_UNDO } ,
+ { kHICommandRedo , wxID_REDO } ,
+} ;
+
+int wxMacCommandToId( UInt32 macCommandId )
+{
+ int wxid = 0 ;
+
+ switch ( macCommandId )
+ {
+ case kHICommandPreferences :
+ wxid = wxApp::s_macPreferencesMenuItemId ;
+ break ;
+
+ case kHICommandQuit :
+ wxid = wxApp::s_macExitMenuItemId ;
+ break ;
+
+ case kHICommandAbout :
+ wxid = wxApp::s_macAboutMenuItemId ;
+ break ;
+
+ default :
+ {
+ for ( size_t i = 0 ; i < WXSIZEOF(gCommandIds) ; ++i )
+ {
+ if ( gCommandIds[i].macId == macCommandId )
+ {
+ wxid = gCommandIds[i].wxId ;
+ break ;
+ }
+ }
+ }
+ break ;
+ }
+
+ if ( wxid == 0 )
+ wxid = (int) macCommandId ;
+
+ return wxid ;
+}
+
+UInt32 wxIdToMacCommand( int wxId )
+{
+ UInt32 macId = 0 ;
+
+ if ( wxId == wxApp::s_macPreferencesMenuItemId )
+ macId = kHICommandPreferences ;
+ else if (wxId == wxApp::s_macExitMenuItemId)
+ macId = kHICommandQuit ;
+ else if (wxId == wxApp::s_macAboutMenuItemId)
+ macId = kHICommandAbout ;
+ else
+ {
+ for ( size_t i = 0 ; i < WXSIZEOF(gCommandIds) ; ++i )
+ {
+ if ( gCommandIds[i].wxId == wxId )
+ {
+ macId = gCommandIds[i].macId ;
+ break ;
+ }
+ }
+ }
+
+ if ( macId == 0 )
+ macId = (int) wxId ;
+
+ return macId ;
+}
+
+wxMenu* wxFindMenuFromMacCommand( const HICommand &command , wxMenuItem* &item )
+{
+ wxMenu* itemMenu = NULL ;
+#ifndef __WXUNIVERSAL__
+ int id = 0 ;
+
+ // for 'standard' commands which don't have a wx-menu
+ if ( command.commandID == kHICommandPreferences || command.commandID == kHICommandQuit || command.commandID == kHICommandAbout )
+ {
+ id = wxMacCommandToId( command.commandID ) ;
+
+ wxMenuBar* mbar = wxMenuBar::MacGetInstalledMenuBar() ;
+ if ( mbar )
+ item = mbar->FindItem( id , &itemMenu ) ;
+ }
+ else if ( command.commandID != 0 && command.menu.menuRef != 0 && command.menu.menuItemIndex != 0 )
+ {
+ id = wxMacCommandToId( command.commandID ) ;
+ // make sure it is one of our own menus, or of the 'synthetic' apple and help menus , otherwise don't touch
+ MenuItemIndex firstUserHelpMenuItem ;
+ static MenuHandle helpMenuHandle = NULL ;
+ if ( helpMenuHandle == NULL )
+ {
+ if ( UMAGetHelpMenuDontCreate( &helpMenuHandle , &firstUserHelpMenuItem) != noErr )
+ helpMenuHandle = NULL ;
+ }
+
+ // is it part of the application or the Help menu, then look for the id directly
+ if ( ( GetMenuHandle( kwxMacAppleMenuId ) != NULL && command.menu.menuRef == GetMenuHandle( kwxMacAppleMenuId ) ) ||
+ ( helpMenuHandle != NULL && command.menu.menuRef == helpMenuHandle ) ||
+ wxMenuBar::MacGetWindowMenuHMenu() != NULL && command.menu.menuRef == wxMenuBar::MacGetWindowMenuHMenu() )
+ {
+ wxMenuBar* mbar = wxMenuBar::MacGetInstalledMenuBar() ;
+ if ( mbar )
+ item = mbar->FindItem( id , &itemMenu ) ;
+ }
+ else
+ {
+ URefCon refCon ;
+
+ GetMenuItemRefCon( command.menu.menuRef , command.menu.menuItemIndex , &refCon ) ;
+ itemMenu = wxFindMenuFromMacMenu( command.menu.menuRef ) ;
+ if ( itemMenu != NULL )
+ item = (wxMenuItem*) refCon ;
+ }
+ }
+#endif
+ return itemMenu ;
+}
+
+//----------------------------------------------------------------------
+// Carbon Event Handler
+//----------------------------------------------------------------------
+
+static const EventTypeSpec eventList[] =
+{
+ { kEventClassCommand, kEventProcessCommand } ,
+ { kEventClassCommand, kEventCommandUpdateStatus } ,
+
+ { kEventClassMenu, kEventMenuOpening },
+ { kEventClassMenu, kEventMenuClosed },
+ { kEventClassMenu, kEventMenuTargetItem },
+
+ { kEventClassApplication , kEventAppActivated } ,
+ { kEventClassApplication , kEventAppDeactivated } ,
+ // handling the quit event is not recommended by apple
+ // rather using the quit apple event - which we do
+
+ { kEventClassAppleEvent , kEventAppleEvent } ,
+
+ { kEventClassMouse , kEventMouseDown } ,
+ { kEventClassMouse , kEventMouseMoved } ,
+ { kEventClassMouse , kEventMouseUp } ,
+ { kEventClassMouse , kEventMouseDragged } ,
+ { 'WXMC' , 'WXMC' }
+} ;
+
+static pascal OSStatus
+wxMacAppMenuEventHandler( EventHandlerCallRef WXUNUSED(handler),
+ EventRef event,
+ void *WXUNUSED(data) )
+{
+ wxMacCarbonEvent cEvent( event ) ;
+ MenuRef menuRef = cEvent.GetParameter(kEventParamDirectObject) ;
+#ifndef __WXUNIVERSAL__
+ wxMenu* menu = wxFindMenuFromMacMenu( menuRef ) ;
+
+ if ( menu )
+ {
+ wxEventType type=0;
+ MenuCommand cmd=0;
+ switch (GetEventKind(event))
+ {
+ case kEventMenuOpening:
+ type = wxEVT_MENU_OPEN;
+ break;
+
+ case kEventMenuClosed:
+ type = wxEVT_MENU_CLOSE;
+ break;
+
+ case kEventMenuTargetItem:
+ cmd = cEvent.GetParameter(kEventParamMenuCommand,typeMenuCommand) ;
+ if (cmd != 0)
+ type = wxEVT_MENU_HIGHLIGHT;
+ break;
+
+ default:
+ wxFAIL_MSG(wxT("Unexpected menu event kind"));
+ break;
+ }
+
+ if ( type )
+ {
+ wxMenuEvent wxevent(type, cmd, menu);
+ wxevent.SetEventObject(menu);
+
+ wxEvtHandler* handler = menu->GetEventHandler();
+ if (handler && handler->ProcessEvent(wxevent))
+ {
+ // handled
+ }
+ else
+ {
+ wxWindow *win = menu->GetInvokingWindow();
+ if (win)
+ win->HandleWindowEvent(wxevent);
+ }
+ }
+ }
+#endif
+ return eventNotHandledErr;
+}
+
+#ifndef __LP64__
+static pascal OSStatus
+wxMacAppCommandEventHandler( EventHandlerCallRef WXUNUSED(handler) ,
+ EventRef event ,
+ void *WXUNUSED(data) )
+{
+ OSStatus result = eventNotHandledErr ;
+
+ HICommand command ;
+
+ wxMacCarbonEvent cEvent( event ) ;
+ cEvent.GetParameter(kEventParamDirectObject,typeHICommand,&command) ;
+
+ wxMenuItem* item = NULL ;
+ wxMenu* itemMenu = wxFindMenuFromMacCommand( command , item ) ;
+ int id = wxMacCommandToId( command.commandID ) ;
+
+ if ( item )
+ {
+ wxASSERT( itemMenu != NULL ) ;
+
+ switch ( cEvent.GetKind() )
+ {
+ case kEventProcessCommand :
+ result = itemMenu->MacHandleCommandProcess( item, id );
+ break ;
+
+ case kEventCommandUpdateStatus:
+ result = itemMenu->MacHandleCommandUpdateStatus( item, id );
+ break ;
+
+ default :
+ break ;
+ }
+ }
+ return result ;
+}
+#endif
+
+static pascal OSStatus
+wxMacAppApplicationEventHandler( EventHandlerCallRef WXUNUSED(handler) ,
+ EventRef event ,
+ void *WXUNUSED(data) )
+{
+ OSStatus result = eventNotHandledErr ;
+ switch ( GetEventKind( event ) )
+ {
+ case kEventAppActivated :
+ if ( wxTheApp )
+ wxTheApp->SetActive( true , NULL ) ;
+ result = noErr ;
+ break ;
+
+ case kEventAppDeactivated :
+ if ( wxTheApp )
+ wxTheApp->SetActive( false , NULL ) ;
+ result = noErr ;
+ break ;
+
+ default :
+ break ;
+ }
+
+ return result ;
+}
+
+pascal OSStatus wxMacAppEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
+{
+ EventRef formerEvent = (EventRef) wxTheApp->MacGetCurrentEvent() ;
+ EventHandlerCallRef formerEventHandlerCallRef = (EventHandlerCallRef) wxTheApp->MacGetCurrentEventHandlerCallRef() ;
+ wxTheApp->MacSetCurrentEvent( event , handler ) ;
+
+ OSStatus result = eventNotHandledErr ;
+ switch ( GetEventClass( event ) )
+ {
+#ifndef __LP64__
+ case kEventClassCommand :
+ result = wxMacAppCommandEventHandler( handler , event , data ) ;
+ break ;
+#endif
+ case kEventClassApplication :
+ result = wxMacAppApplicationEventHandler( handler , event , data ) ;
+ break ;
+#ifndef __LP64__
+ case kEventClassMenu :
+ result = wxMacAppMenuEventHandler( handler , event , data ) ;
+ break ;
+
+ case kEventClassMouse :
+ {
+ wxMacCarbonEvent cEvent( event ) ;
+
+ WindowRef window ;
+ Point screenMouseLocation = cEvent.GetParameter(kEventParamMouseLocation) ;
+ ::FindWindow(screenMouseLocation, &window);
+ // only send this event in case it had not already been sent to a tlw, as we get
+ // double events otherwise (in case event.skip) was called
+ if ( window == NULL )
+ result = wxMacTopLevelMouseEventHandler( handler , event , NULL ) ;
+ }
+ break ;
+#endif
+ case kEventClassAppleEvent :
+ {
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+ if ( AEProcessEvent != NULL )
+ {
+ result = AEProcessEvent(event);
+ }
+#endif
+#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
+ {
+ EventRecord rec ;
+
+ wxMacConvertEventToRecord( event , &rec ) ;
+ result = AEProcessAppleEvent( &rec ) ;
+ }
+#endif
+ }
+ break ;
+
+ default :
+ break ;
+ }
+
+ wxTheApp->MacSetCurrentEvent( formerEvent, formerEventHandlerCallRef ) ;
+
+ return result ;
+}
+
+DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacAppEventHandler )
+
+#ifdef __WXDEBUG__
+
+pascal static void
+wxMacAssertOutputHandler(OSType WXUNUSED(componentSignature),
+ UInt32 WXUNUSED(options),
+ const char *assertionString,
+ const char *exceptionLabelString,
+ const char *errorString,
+ const char *fileName,
+ long lineNumber,
+ void *value,
+ ConstStr255Param WXUNUSED(outputMsg))
+{
+ // flow into assert handling
+ wxString fileNameStr ;
+ wxString assertionStr ;
+ wxString exceptionStr ;
+ wxString errorStr ;
+
+#if wxUSE_UNICODE
+ fileNameStr = wxString(fileName, wxConvLocal);
+ assertionStr = wxString(assertionString, wxConvLocal);
+ exceptionStr = wxString((exceptionLabelString!=0) ? exceptionLabelString : "", wxConvLocal) ;
+ errorStr = wxString((errorString!=0) ? errorString : "", wxConvLocal) ;
+#else
+ fileNameStr = fileName;
+ assertionStr = assertionString;
+ exceptionStr = (exceptionLabelString!=0) ? exceptionLabelString : "" ;
+ errorStr = (errorString!=0) ? errorString : "" ;
+#endif
+
+#if 1
+ // flow into log
+ wxLogDebug( wxT("AssertMacros: %s %s %s file: %s, line: %ld (value %p)\n"),
+ assertionStr.c_str() ,
+ exceptionStr.c_str() ,
+ errorStr.c_str(),
+ fileNameStr.c_str(), lineNumber ,
+ value ) ;
+#else
+
+ wxOnAssert(fileNameStr, lineNumber , assertionStr ,
+ wxString::Format( wxT("%s %s value (%p)") , exceptionStr, errorStr , value ) ) ;
+#endif
+}
+
+#endif //__WXDEBUG__
+
+extern "C" void macPostedEventCallback(void *WXUNUSED(unused))
+{
+ wxTheApp->ProcessPendingEvents();
+}
+
+bool wxApp::Initialize(int& argc, wxChar **argv)
+{
+ // Mac-specific
+
+#ifdef __WXDEBUG__
+ InstallDebugAssertOutputHandler( NewDebugAssertOutputHandlerUPP( wxMacAssertOutputHandler ) );
+#endif
+
+ UMAInitToolbox( 4, sm_isEmbedded ) ;
+// TODO CHECK Can Be Removed SetEventMask( everyEvent ) ;
+
+ // Mac OS X passes a process serial number command line argument when
+ // the application is launched from the Finder. This argument must be
+ // removed from the command line arguments before being handled by the
+ // application (otherwise applications would need to handle it)
+ if ( argc > 1 )
+ {
+ static const wxChar *ARG_PSN = _T("-psn_");
+ if ( wxStrncmp(argv[1], ARG_PSN, wxStrlen(ARG_PSN)) == 0 )
+ {
+ // remove this argument
+ --argc;
+ memmove(argv + 1, argv + 2, argc * sizeof(char *));
+ }
+ }
+
+ if ( !wxAppBase::Initialize(argc, argv) )
+ return false;
+
+#if wxUSE_INTL
+ wxFont::SetDefaultEncoding(wxLocale::GetSystemEncoding());
+#endif
+
+ // these might be the startup dirs, set them to the 'usual' dir containing the app bundle
+ wxString startupCwd = wxGetCwd() ;
+ if ( startupCwd == wxT("/") || startupCwd.Right(15) == wxT("/Contents/MacOS") )
+ {
+ CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle() ) ;
+ CFURLRef urlParent = CFURLCreateCopyDeletingLastPathComponent( kCFAllocatorDefault , url ) ;
+ CFRelease( url ) ;
+ CFStringRef path = CFURLCopyFileSystemPath ( urlParent , kCFURLPOSIXPathStyle ) ;
+ CFRelease( urlParent ) ;
+ wxString cwd = wxCFStringRef(path).AsString(wxLocale::GetSystemEncoding());
+ wxSetWorkingDirectory( cwd ) ;
+ }
+
+ /* connect posted events to common-mode run loop so that wxPostEvent events
+ are handled even while we're in the menu or on a scrollbar */
+ CFRunLoopSourceContext event_posted_context = {0};
+ event_posted_context.perform = macPostedEventCallback;
+ m_macEventPosted = CFRunLoopSourceCreate(NULL,0,&event_posted_context);
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), m_macEventPosted, kCFRunLoopCommonModes);
+ // run loop takes ownership
+ CFRelease(m_macEventPosted);
+
+ return true;
+}
+
+AEEventHandlerUPP sODocHandler = NULL ;
+AEEventHandlerUPP sGURLHandler = NULL ;
+AEEventHandlerUPP sOAppHandler = NULL ;
+AEEventHandlerUPP sPDocHandler = NULL ;
+AEEventHandlerUPP sRAppHandler = NULL ;
+AEEventHandlerUPP sQuitHandler = NULL ;
+
+bool wxApp::OnInitGui()
+{
+ if ( !wxAppBase::OnInitGui() )
+ return false ;
+#ifndef __LP64__
+ InstallStandardEventHandler( GetApplicationEventTarget() ) ;
+ if (!sm_isEmbedded)
+ {
+ InstallApplicationEventHandler(
+ GetwxMacAppEventHandlerUPP(),
+ GetEventTypeCount(eventList), eventList, wxTheApp, (EventHandlerRef *)&(wxTheApp->m_macEventHandler));
+ }
+#endif
+
+ if (!sm_isEmbedded)
+ {
+ sODocHandler = NewAEEventHandlerUPP(AEHandleODoc) ;
+ sGURLHandler = NewAEEventHandlerUPP(AEHandleGURL) ;
+ sOAppHandler = NewAEEventHandlerUPP(AEHandleOApp) ;
+ sPDocHandler = NewAEEventHandlerUPP(AEHandlePDoc) ;
+ sRAppHandler = NewAEEventHandlerUPP(AEHandleRApp) ;
+ sQuitHandler = NewAEEventHandlerUPP(AEHandleQuit) ;
+
+ AEInstallEventHandler( kCoreEventClass , kAEOpenDocuments ,
+ sODocHandler , 0 , FALSE ) ;
+ AEInstallEventHandler( kInternetEventClass, kAEGetURL,
+ sGURLHandler , 0 , FALSE ) ;
+ AEInstallEventHandler( kCoreEventClass , kAEOpenApplication ,
+ sOAppHandler , 0 , FALSE ) ;
+ AEInstallEventHandler( kCoreEventClass , kAEPrintDocuments ,
+ sPDocHandler , 0 , FALSE ) ;
+ AEInstallEventHandler( kCoreEventClass , kAEReopenApplication ,
+ sRAppHandler , 0 , FALSE ) ;
+ AEInstallEventHandler( kCoreEventClass , kAEQuitApplication ,
+ sQuitHandler , 0 , FALSE ) ;
+ }
+
+ if ( !wxMacInitCocoa() )
+ return false;
+
+ return true ;
+}
+
+void wxApp::CleanUp()
+{
+#if wxUSE_TOOLTIPS
+ wxToolTip::RemoveToolTips() ;
+#endif
+
+ if (m_macEventPosted)
+ {
+ CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m_macEventPosted, kCFRunLoopCommonModes);
+ m_macEventPosted = NULL;
+ }
+
+ // One last chance for pending objects to be cleaned up
+ wxTheApp->DeletePendingObjects();
+
+ if (!sm_isEmbedded)
+ RemoveEventHandler( (EventHandlerRef)(wxTheApp->m_macEventHandler) );
+
+ if (!sm_isEmbedded)
+ {
+ AERemoveEventHandler( kCoreEventClass , kAEOpenDocuments ,
+ sODocHandler , FALSE ) ;
+ AERemoveEventHandler( kInternetEventClass, kAEGetURL,
+ sGURLHandler , FALSE ) ;
+ AERemoveEventHandler( kCoreEventClass , kAEOpenApplication ,
+ sOAppHandler , FALSE ) ;
+ AERemoveEventHandler( kCoreEventClass , kAEPrintDocuments ,
+ sPDocHandler , FALSE ) ;
+ AERemoveEventHandler( kCoreEventClass , kAEReopenApplication ,
+ sRAppHandler , FALSE ) ;
+ AERemoveEventHandler( kCoreEventClass , kAEQuitApplication ,
+ sQuitHandler , FALSE ) ;
+
+ DisposeAEEventHandlerUPP( sODocHandler ) ;
+ DisposeAEEventHandlerUPP( sGURLHandler ) ;
+ DisposeAEEventHandlerUPP( sOAppHandler ) ;
+ DisposeAEEventHandlerUPP( sPDocHandler ) ;
+ DisposeAEEventHandlerUPP( sRAppHandler ) ;
+ DisposeAEEventHandlerUPP( sQuitHandler ) ;
+ }
+
+ wxAppBase::CleanUp();
+}
+
+//----------------------------------------------------------------------
+// misc initialization stuff
+//----------------------------------------------------------------------
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
+bool wxMacConvertEventToRecord( EventRef event , EventRecord *rec)
+{
+ OSStatus err = noErr ;
+ bool converted = ConvertEventRefToEventRecord( event, rec) ;
+
+ if ( !converted )
+ {
+ switch ( GetEventClass( event ) )
+ {
+ case kEventClassKeyboard :
+ {
+ converted = true ;
+ switch ( GetEventKind(event) )
+ {
+ case kEventRawKeyDown :
+ rec->what = keyDown ;
+ break ;
+
+ case kEventRawKeyRepeat :
+ rec->what = autoKey ;
+ break ;
+
+ case kEventRawKeyUp :
+ rec->what = keyUp ;
+ break ;
+
+ case kEventRawKeyModifiersChanged :
+ rec->what = nullEvent ;
+ break ;
+
+ default :
+ converted = false ;
+ break ;
+ }
+
+ if ( converted )
+ {
+ UInt32 keyCode ;
+ unsigned char charCode ;
+ UInt32 modifiers ;
+ GetMouse( &rec->where) ;
+ err = GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL, 4, NULL, &modifiers);
+ err = GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL, 4, NULL, &keyCode);
+ err = GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar, NULL, 1, NULL, &charCode);
+ rec->modifiers = modifiers ;
+ rec->message = (keyCode << 8 ) + charCode ;
+ }
+ }
+ break ;
+
+ case kEventClassTextInput :
+ {
+ switch ( GetEventKind( event ) )
+ {
+ case kEventTextInputUnicodeForKeyEvent :
+ {
+ EventRef rawEvent ;
+ err = GetEventParameter(
+ event, kEventParamTextInputSendKeyboardEvent, typeEventRef, NULL,
+ sizeof(rawEvent), NULL, &rawEvent ) ;
+ converted = true ;
+
+ {
+ UInt32 keyCode, modifiers;
+ unsigned char charCode ;
+ GetMouse( &rec->where) ;
+ rec->what = keyDown ;
+ err = GetEventParameter(rawEvent, kEventParamKeyModifiers, typeUInt32, NULL, 4, NULL, &modifiers);
+ err = GetEventParameter(rawEvent, kEventParamKeyCode, typeUInt32, NULL, 4, NULL, &keyCode);
+ err = GetEventParameter(rawEvent, kEventParamKeyMacCharCodes, typeChar, NULL, 1, NULL, &charCode);
+ rec->modifiers = modifiers ;
+ rec->message = (keyCode << 8 ) + charCode ;
+ }
+ }
+ break ;
+
+ default :
+ break ;
+ }
+ }
+ break ;
+
+ default :
+ break ;
+ }
+ }
+
+ return converted ;
+}
+#endif
+
+wxApp::wxApp()
+{
+ m_printMode = wxPRINT_WINDOWS;
+
+ m_macCurrentEvent = NULL ;
+ m_macCurrentEventHandlerCallRef = NULL ;
+ m_macEventPosted = NULL ;
+}
+
+void wxApp::OnIdle(wxIdleEvent& WXUNUSED(event))
+{
+ // If they are pending events, we must process them: pending events are
+ // either events to the threads other than main or events posted with
+ // wxPostEvent() functions
+#ifndef __WXUNIVERSAL__
+ if (!wxMenuBar::MacGetInstalledMenuBar() && wxMenuBar::MacGetCommonMenuBar())
+ wxMenuBar::MacGetCommonMenuBar()->MacInstallMenuBar();
+#endif
+}
+
+void wxApp::WakeUpIdle()
+{
+ if (m_macEventPosted)
+ {
+ CFRunLoopSourceSignal(m_macEventPosted);
+ }
+
+ wxMacWakeUp() ;
+}
+
+void wxApp::OnEndSession(wxCloseEvent& WXUNUSED(event))
+{
+ if (GetTopWindow())
+ GetTopWindow()->Close(true);
+}
+
+// Default behaviour: close the application with prompts. The
+// user can veto the close, and therefore the end session.
+void wxApp::OnQueryEndSession(wxCloseEvent& event)
+{
+ if (GetTopWindow())
+ {
+ if (!GetTopWindow()->Close(!event.CanVeto()))
+ event.Veto(true);
+ }
+}
+
+extern "C" void wxCYield() ;
+void wxCYield()
+{
+ wxYield() ;
+}
+
+// Yield to other processes
+
+bool wxApp::Yield(bool onlyIfNeeded)
+{
+ if (s_inYield)
+ {
+ if ( !onlyIfNeeded )
+ {
+ wxFAIL_MSG( wxT("wxYield called recursively" ) );
+ }
+
+ return false;
+ }
+
+#if wxUSE_THREADS
+ // Yielding from a non-gui thread needs to bail out, otherwise we end up
+ // possibly sending events in the thread too.
+ if ( !wxThread::IsMain() )
+ {
+ return true;
+ }
+#endif // wxUSE_THREADS
+
+ s_inYield = true;
+
+ // by definition yield should handle all non-processed events
+
+ EventRef theEvent;
+
+ OSStatus status = noErr ;
+
+ while ( status == noErr )
+ {
+ s_inReceiveEvent = true ;
+ status = ReceiveNextEvent(0, NULL,kEventDurationNoWait,true,&theEvent) ;
+ s_inReceiveEvent = false ;
+
+ if ( status == eventLoopTimedOutErr )
+ {
+ // make sure next time the event loop will trigger idle events
+ sleepTime = kEventDurationNoWait ;
+ }
+ else if ( status == eventLoopQuitErr )
+ {
+ // according to QA1061 this may also occur when a WakeUp Process
+ // is executed
+ }
+ else
+ {
+ MacHandleOneEvent( theEvent ) ;
+ ReleaseEvent(theEvent);
+ }
+ }
+
+ s_inYield = false;
+
+ return true;
+}
+
+void wxApp::MacDoOneEvent()
+{
+ wxMacAutoreleasePool autoreleasepool;
+ EventRef theEvent;
+
+ s_inReceiveEvent = true ;
+ OSStatus status = ReceiveNextEvent(0, NULL, sleepTime, true, &theEvent) ;
+ s_inReceiveEvent = false ;
+
+ switch (status)
+ {
+ case eventLoopTimedOutErr :
+ if ( wxTheApp->ProcessIdle() )
+ sleepTime = kEventDurationNoWait ;
+ else
+ sleepTime = kEventDurationSecond;
+ break;
+
+ case eventLoopQuitErr :
+ // according to QA1061 this may also occur
+ // when a WakeUp Process is executed
+ break;
+
+ default:
+ MacHandleOneEvent( theEvent ) ;
+ ReleaseEvent( theEvent );
+ sleepTime = kEventDurationNoWait ;
+ break;
+ }
+ // repeaters
+
+ DeletePendingObjects() ;
+}
+
+// virtual
+void wxApp::MacHandleUnhandledEvent( WXEVENTREF WXUNUSED(evr) )
+{
+ // Override to process unhandled events as you please
+}
+
+CFMutableArrayRef GetAutoReleaseArray()
+{
+ static CFMutableArrayRef array = 0;
+ if ( array == 0)
+ array= CFArrayCreateMutable(kCFAllocatorDefault,0,&kCFTypeArrayCallBacks);
+ return array;
+}
+
+void wxApp::MacHandleOneEvent( WXEVENTREF evr )
+{
+ EventTargetRef theTarget;
+ theTarget = GetEventDispatcherTarget();
+ m_macCurrentEvent = evr ;
+
+ OSStatus status = SendEventToEventTarget((EventRef) evr , theTarget);
+ if (status == eventNotHandledErr)
+ MacHandleUnhandledEvent(evr);
+
+#if wxUSE_THREADS
+ wxMutexGuiLeaveOrEnter();
+#endif // wxUSE_THREADS
+
+ CFArrayRemoveAllValues( GetAutoReleaseArray() );
+}
+
+void wxApp::MacAddToAutorelease( void* cfrefobj )
+{
+ CFArrayAppendValue( GetAutoReleaseArray(), cfrefobj );
+}
+
+long wxMacTranslateKey(unsigned char key, unsigned char code)
+{
+ long retval = key ;
+ switch (key)
+ {
+ case kHomeCharCode :
+ retval = WXK_HOME;
+ break;
+
+ case kEnterCharCode :
+ retval = WXK_RETURN;
+ break;
+ case kEndCharCode :
+ retval = WXK_END;
+ break;
+
+ case kHelpCharCode :
+ retval = WXK_HELP;
+ break;
+
+ case kBackspaceCharCode :
+ retval = WXK_BACK;
+ break;
+
+ case kTabCharCode :
+ retval = WXK_TAB;
+ break;
+
+ case kPageUpCharCode :
+ retval = WXK_PAGEUP;
+ break;
+
+ case kPageDownCharCode :
+ retval = WXK_PAGEDOWN;
+ break;
+
+ case kReturnCharCode :
+ retval = WXK_RETURN;
+ break;
+
+ case kFunctionKeyCharCode :
+ {
+ switch ( code )
+ {
+ case 0x7a :
+ retval = WXK_F1 ;
+ break;
+
+ case 0x78 :
+ retval = WXK_F2 ;
+ break;
+
+ case 0x63 :
+ retval = WXK_F3 ;
+ break;
+
+ case 0x76 :
+ retval = WXK_F4 ;
+ break;
+
+ case 0x60 :
+ retval = WXK_F5 ;
+ break;
+
+ case 0x61 :
+ retval = WXK_F6 ;
+ break;
+
+ case 0x62:
+ retval = WXK_F7 ;
+ break;
+
+ case 0x64 :
+ retval = WXK_F8 ;
+ break;
+
+ case 0x65 :
+ retval = WXK_F9 ;
+ break;
+
+ case 0x6D :
+ retval = WXK_F10 ;
+ break;
+
+ case 0x67 :
+ retval = WXK_F11 ;
+ break;
+
+ case 0x6F :
+ retval = WXK_F12 ;
+ break;
+
+ case 0x69 :
+ retval = WXK_F13 ;
+ break;
+
+ case 0x6B :
+ retval = WXK_F14 ;
+ break;
+
+ case 0x71 :
+ retval = WXK_F15 ;
+ break;
+
+ default:
+ break;
+ }
+ }
+ break ;
+
+ case kEscapeCharCode :
+ retval = WXK_ESCAPE ;
+ break ;
+
+ case kLeftArrowCharCode :
+ retval = WXK_LEFT ;
+ break ;
+
+ case kRightArrowCharCode :
+ retval = WXK_RIGHT ;
+ break ;
+
+ case kUpArrowCharCode :
+ retval = WXK_UP ;
+ break ;
+
+ case kDownArrowCharCode :
+ retval = WXK_DOWN ;
+ break ;
+
+ case kDeleteCharCode :
+ retval = WXK_DELETE ;
+ break ;
+
+ default:
+ break ;
+ } // end switch
+
+ return retval;
+}
+
+int wxMacKeyCodeToModifier(wxKeyCode key)
+{
+ switch (key)
+ {
+ case WXK_START:
+ case WXK_MENU:
+ return cmdKey;
+
+ case WXK_SHIFT:
+ return shiftKey;
+
+ case WXK_CAPITAL:
+ return alphaLock;
+
+ case WXK_ALT:
+ return optionKey;
+
+ case WXK_CONTROL:
+ return controlKey;
+
+ default:
+ return 0;
+ }
+}
+
+wxMouseState wxGetMouseState()
+{
+ wxMouseState ms;
+
+ wxPoint pt = wxGetMousePosition();
+ ms.SetX(pt.x);
+ ms.SetY(pt.y);
+
+ UInt32 buttons = GetCurrentButtonState();
+ ms.SetLeftDown( (buttons & 0x01) != 0 );
+ ms.SetMiddleDown( (buttons & 0x04) != 0 );
+ ms.SetRightDown( (buttons & 0x02) != 0 );
+
+ UInt32 modifiers = GetCurrentKeyModifiers();
+ ms.SetControlDown(modifiers & controlKey);
+ ms.SetShiftDown(modifiers & shiftKey);
+ ms.SetAltDown(modifiers & optionKey);
+ ms.SetMetaDown(modifiers & cmdKey);
+
+ return ms;
+}
+
+// TODO : once the new key/char handling is tested, move all the code to wxWindow
+
+bool wxApp::MacSendKeyDownEvent( wxWindow* focus , long keymessage , long modifiers , long when , short wherex , short wherey , wxChar uniChar )
+{
+ if ( !focus )
+ return false ;
+
+ bool handled;
+ wxKeyEvent event(wxEVT_KEY_DOWN) ;
+ MacCreateKeyEvent( event, focus , keymessage , modifiers , when , wherex , wherey , uniChar ) ;
+
+ handled = focus->HandleWindowEvent( event ) ;
+ if ( handled && event.GetSkipped() )
+ handled = false ;
+
+#if wxUSE_ACCEL
+ if ( !handled )
+ {
+ wxWindow *ancestor = focus;
+ while (ancestor)
+ {
+ int command = ancestor->GetAcceleratorTable()->GetCommand( event );
+ if (command != -1)
+ {
+ wxEvtHandler * const handler = ancestor->GetEventHandler();
+
+ wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command );
+ handled = handler->ProcessEvent( command_event );
+
+ if ( !handled )
+ {
+ // accelerators can also be used with buttons, try them too
+ command_event.SetEventType(wxEVT_COMMAND_BUTTON_CLICKED);
+ handled = handler->ProcessEvent( command_event );
+ }
+
+ break;
+ }
+
+ if (ancestor->IsTopLevel())
+ break;
+
+ ancestor = ancestor->GetParent();
+ }
+ }
+#endif // wxUSE_ACCEL
+
+ return handled ;
+}
+
+bool wxApp::MacSendKeyUpEvent( wxWindow* focus , long keymessage , long modifiers , long when , short wherex , short wherey , wxChar uniChar )
+{
+ if ( !focus )
+ return false ;
+
+ bool handled;
+ wxKeyEvent event( wxEVT_KEY_UP ) ;
+ MacCreateKeyEvent( event, focus , keymessage , modifiers , when , wherex , wherey , uniChar ) ;
+ handled = focus->HandleWindowEvent( event ) ;
+
+ return handled ;
+}
+
+bool wxApp::MacSendCharEvent( wxWindow* focus , long keymessage , long modifiers , long when , short wherex , short wherey , wxChar uniChar )
+{
+ if ( !focus )
+ return false ;
+
+ wxKeyEvent event(wxEVT_CHAR) ;
+ MacCreateKeyEvent( event, focus , keymessage , modifiers , when , wherex , wherey , uniChar ) ;
+ long keyval = event.m_keyCode ;
+
+ bool handled = false ;
+
+ wxNonOwnedWindow *tlw = focus->MacGetTopLevelWindow() ;
+
+ if (tlw)
+ {
+ event.SetEventType( wxEVT_CHAR_HOOK );
+ handled = tlw->HandleWindowEvent( event );
+ if ( handled && event.GetSkipped() )
+ handled = false ;
+ }
+
+ if ( !handled )
+ {
+ event.SetEventType( wxEVT_CHAR );
+ event.Skip( false ) ;
+ handled = focus->HandleWindowEvent( event ) ;
+ }
+
+ if ( !handled && (keyval == WXK_TAB) )
+ {
+ wxWindow* iter = focus->GetParent() ;
+ while ( iter && !handled )
+ {
+ if ( iter->HasFlag( wxTAB_TRAVERSAL ) )
+ {
+ wxNavigationKeyEvent new_event;
+ new_event.SetEventObject( focus );
+ new_event.SetDirection( !event.ShiftDown() );
+ /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
+ new_event.SetWindowChange( event.ControlDown() );
+ new_event.SetCurrentFocus( focus );
+ handled = focus->GetParent()->HandleWindowEvent( new_event );
+ if ( handled && new_event.GetSkipped() )
+ handled = false ;
+ }
+
+ iter = iter->GetParent() ;
+ }
+ }
+
+ // backdoor handler for default return and command escape
+ if ( !handled && (!focus->IsKindOf(CLASSINFO(wxControl) ) || !focus->MacCanFocus() ) )
+ {
+ // if window is not having a focus still testing for default enter or cancel
+ // TODO: add the UMA version for ActiveNonFloatingWindow
+#ifndef __LP64__
+ wxWindow* focus = wxFindWinFromMacWindow( FrontWindow() ) ;
+ if ( focus )
+ {
+ if ( keyval == WXK_RETURN || keyval == WXK_NUMPAD_ENTER )
+ {
+ wxTopLevelWindow *tlw = wxDynamicCast(wxGetTopLevelParent(focus), wxTopLevelWindow);
+ if ( tlw && tlw->GetDefaultItem() )
+ {
+ wxButton *def = wxDynamicCast(tlw->GetDefaultItem(), wxButton);
+ if ( def && def->IsEnabled() )
+ {
+ wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, def->GetId() );
+ event.SetEventObject(def);
+ def->Command(event);
+
+ return true ;
+ }
+ }
+ }
+ else if (keyval == WXK_ESCAPE || (keyval == '.' && modifiers & cmdKey ) )
+ {
+ // generate wxID_CANCEL if command-. or has been pressed (typically in dialogs)
+ wxCommandEvent new_event(wxEVT_COMMAND_BUTTON_CLICKED,wxID_CANCEL);
+ new_event.SetEventObject( focus );
+ handled = focus->HandleWindowEvent( new_event );
+ }
+ }
+#endif
+ }
+ return handled ;
+}
+
+// This method handles common code for SendKeyDown, SendKeyUp, and SendChar events.
+void wxApp::MacCreateKeyEvent( wxKeyEvent& event, wxWindow* focus , long keymessage , long modifiers , long when , short wherex , short wherey , wxChar uniChar )
+{
+ short keycode, keychar ;
+
+ keychar = short(keymessage & charCodeMask);
+ keycode = short(keymessage & keyCodeMask) >> 8 ;
+ if ( !(event.GetEventType() == wxEVT_CHAR) && (modifiers & (controlKey | shiftKey | optionKey) ) )
+ {
+ // control interferes with some built-in keys like pgdown, return etc. therefore we remove the controlKey modifier
+ // and look at the character after
+#ifdef __LP64__
+ // TODO new implementation using TextInputSources
+#else
+ UInt32 state = 0;
+ UInt32 keyInfo = KeyTranslate((Ptr)GetScriptManagerVariable(smKCHRCache), ( modifiers & (~(controlKey | shiftKey | optionKey))) | keycode, &state);
+ keychar = short(keyInfo & charCodeMask);
+#endif
+ }
+
+ long keyval = wxMacTranslateKey(keychar, keycode) ;
+ if ( keyval == keychar && ( event.GetEventType() == wxEVT_KEY_UP || event.GetEventType() == wxEVT_KEY_DOWN ) )
+ keyval = wxToupper( keyval ) ;
+
+ // Check for NUMPAD keys. For KEY_UP/DOWN events we need to use the
+ // WXK_NUMPAD constants, but for the CHAR event we want to use the
+ // standard ascii values
+ if ( event.GetEventType() != wxEVT_CHAR )
+ {
+ if (keyval >= '0' && keyval <= '9' && keycode >= 82 && keycode <= 92)
+ {
+ keyval = (keyval - '0') + WXK_NUMPAD0;
+ }
+ else if (keycode >= 65 && keycode <= 81)
+ {
+ switch (keycode)
+ {
+ case 76 :
+ keyval = WXK_NUMPAD_ENTER;
+ break;
+
+ case 81:
+ keyval = WXK_NUMPAD_EQUAL;
+ break;
+
+ case 67:
+ keyval = WXK_NUMPAD_MULTIPLY;
+ break;
+
+ case 75:
+ keyval = WXK_NUMPAD_DIVIDE;
+ break;
+
+ case 78:
+ keyval = WXK_NUMPAD_SUBTRACT;
+ break;
+
+ case 69:
+ keyval = WXK_NUMPAD_ADD;
+ break;
+
+ case 65:
+ keyval = WXK_NUMPAD_DECIMAL;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ event.m_shiftDown = modifiers & shiftKey;
+ event.m_controlDown = modifiers & controlKey;
+ event.m_altDown = modifiers & optionKey;
+ event.m_metaDown = modifiers & cmdKey;
+ event.m_keyCode = keyval ;
+#if wxUSE_UNICODE
+ event.m_uniChar = uniChar ;
+#endif
+
+ event.m_rawCode = keymessage;
+ event.m_rawFlags = modifiers;
+ event.m_x = wherex;
+ event.m_y = wherey;
+ event.SetTimestamp(when);
+ event.SetEventObject(focus);
+}
+
+
+void wxApp::MacHideApp()
+{
+ wxMacCarbonEvent event( kEventClassCommand , kEventCommandProcess );
+ HICommand command;
+ memset( &command, 0 , sizeof(command) );
+ command.commandID = kHICommandHide ;
+ event.SetParameter(kEventParamDirectObject, command );
+ SendEventToApplication( event );
+}
diff --git a/src/osx/carbon/apprsrc.h b/src/osx/carbon/apprsrc.h
new file mode 100644
index 0000000000..55d7f307ad
--- /dev/null
+++ b/src/osx/carbon/apprsrc.h
@@ -0,0 +1 @@
+// TODO REMOVE
diff --git a/src/osx/carbon/apprsrc.r b/src/osx/carbon/apprsrc.r
new file mode 100644
index 0000000000..4113a172a0
--- /dev/null
+++ b/src/osx/carbon/apprsrc.r
@@ -0,0 +1 @@
+/* not needed anymore */
diff --git a/src/osx/carbon/artmac.cpp b/src/osx/carbon/artmac.cpp
new file mode 100644
index 0000000000..466ba9be56
--- /dev/null
+++ b/src/osx/carbon/artmac.cpp
@@ -0,0 +1,108 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/artmac.cpp
+// Purpose: wxArtProvider instance with native Mac stock icons
+// Author: Alan Shouls
+// Created: 2006-10-30
+// RCS-ID: $Id$
+// Copyright: (c) wxWindows team
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+// ---------------------------------------------------------------------------
+// headers
+// ---------------------------------------------------------------------------
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#if defined(__BORLANDC__)
+ #pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+ #include "wx/image.h"
+#endif
+
+#include "wx/artprov.h"
+#include "wx/image.h"
+
+// ----------------------------------------------------------------------------
+// wxMacArtProvider
+// ----------------------------------------------------------------------------
+
+class wxMacArtProvider : public wxArtProvider
+{
+protected:
+ virtual wxBitmap CreateBitmap(const wxArtID& id, const wxArtClient& client,
+ const wxSize& size);
+ virtual wxIconBundle CreateIconBundle(const wxArtID& id,
+ const wxArtClient& client);
+};
+
+/* static */ void wxArtProvider::InitNativeProvider()
+{
+ wxArtProvider::Push(new wxMacArtProvider);
+}
+
+// ----------------------------------------------------------------------------
+// helper macros
+// ----------------------------------------------------------------------------
+
+#define CREATE_STD_ICON(iconId, xpmRc) \
+ { \
+ wxIconBundle icon(_T(iconId), wxBITMAP_TYPE_ICON_RESOURCE); \
+ return icon; \
+ }
+
+// Macro used in CreateBitmap to get wxICON_FOO icons:
+#define ART_MSGBOX(artId, iconId, xpmRc) \
+ if ( id == artId ) \
+ { \
+ CREATE_STD_ICON(#iconId, xpmRc) \
+ }
+
+static wxIconBundle wxMacArtProvider_CreateIconBundle(const wxArtID& id)
+{
+ ART_MSGBOX(wxART_ERROR, wxICON_ERROR, error)
+ ART_MSGBOX(wxART_INFORMATION, wxICON_INFORMATION, info)
+ ART_MSGBOX(wxART_WARNING, wxICON_WARNING, warning)
+ ART_MSGBOX(wxART_QUESTION, wxICON_QUESTION, question)
+
+ ART_MSGBOX(wxART_FOLDER, wxICON_FOLDER, folder)
+ ART_MSGBOX(wxART_FOLDER_OPEN, wxICON_FOLDER_OPEN, folder_open)
+ ART_MSGBOX(wxART_NORMAL_FILE, wxICON_NORMAL_FILE, deffile)
+
+ return wxNullIconBundle;
+}
+
+// ----------------------------------------------------------------------------
+// CreateIconBundle
+// ----------------------------------------------------------------------------
+
+wxIconBundle wxMacArtProvider::CreateIconBundle(const wxArtID& id, const wxArtClient& client)
+{
+ // On the Mac folders in lists are always drawn closed, so if an open
+ // folder icon is asked for we will ask for a closed one in its place
+ if ( client == wxART_LIST && id == wxART_FOLDER_OPEN )
+ return wxMacArtProvider_CreateIconBundle(wxART_FOLDER);
+
+ return wxMacArtProvider_CreateIconBundle(id);
+}
+
+// ----------------------------------------------------------------------------
+// CreateBitmap
+// ----------------------------------------------------------------------------
+
+wxBitmap wxMacArtProvider::CreateBitmap(const wxArtID& id,
+ const wxArtClient& client,
+ const wxSize& reqSize)
+{
+ wxIconBundle ic(CreateIconBundle(id, client));
+ if (ic.IsOk())
+ {
+ wxIcon theIcon(ic.GetIcon(reqSize));
+ return wxBitmap(theIcon);
+ }
+
+ return wxNullBitmap;
+}
diff --git a/src/osx/carbon/bitmap.cpp b/src/osx/carbon/bitmap.cpp
new file mode 100644
index 0000000000..1183eb0fbb
--- /dev/null
+++ b/src/osx/carbon/bitmap.cpp
@@ -0,0 +1,1721 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/bitmap.cpp
+// Purpose: wxBitmap
+// Author: Stefan Csomor
+// Modified by:
+// Created: 1998-01-01
+// RCS-ID: $Id$
+// Copyright: (c) Stefan Csomor
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/wxprec.h"
+
+#include "wx/bitmap.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/log.h"
+ #include "wx/dcmemory.h"
+ #include "wx/icon.h"
+ #include "wx/image.h"
+#endif
+
+#include "wx/metafile.h"
+#include "wx/xpmdecod.h"
+
+#include "wx/rawbmp.h"
+
+IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject)
+IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject)
+
+#include "wx/mac/private.h"
+#ifndef __WXOSX_IPHONE__
+#include
+#endif
+
+CGColorSpaceRef wxMacGetGenericRGBColorSpace();
+CGDataProviderRef wxMacCGDataProviderCreateWithMemoryBuffer( const wxMemoryBuffer& buf );
+
+// Implementation Notes
+// --------------------
+//
+// we are always working with a 32 bit deep pixel buffer
+// under QuickDraw its alpha parts are going to be ignored in the GWorld,
+// therefore we have a separate GWorld there for blitting the mask in
+
+// under Quartz then content is transformed into a CGImageRef representing the same data
+// which can be transferred to the GPU by the OS for fast rendering
+
+class WXDLLEXPORT wxBitmapRefData: public wxGDIRefData
+{
+ friend class WXDLLIMPEXP_FWD_CORE wxIcon;
+ friend class WXDLLIMPEXP_FWD_CORE wxCursor;
+public:
+ wxBitmapRefData(int width , int height , int depth);
+ wxBitmapRefData();
+ wxBitmapRefData(const wxBitmapRefData &tocopy);
+
+ virtual ~wxBitmapRefData();
+
+ virtual bool IsOk() const { return m_ok; }
+
+ void Free();
+ void SetOk( bool isOk) { m_ok = isOk; }
+
+ void SetWidth( int width ) { m_width = width; }
+ void SetHeight( int height ) { m_height = height; }
+ void SetDepth( int depth ) { m_depth = depth; }
+
+ int GetWidth() const { return m_width; }
+ int GetHeight() const { return m_height; }
+ int GetDepth() const { return m_depth; }
+
+ void *GetRawAccess() const;
+ void *BeginRawAccess();
+ void EndRawAccess();
+
+ bool HasAlpha() const { return m_hasAlpha; }
+ void UseAlpha( bool useAlpha );
+
+public:
+#if wxUSE_PALETTE
+ wxPalette m_bitmapPalette;
+#endif // wxUSE_PALETTE
+
+ wxMask * m_bitmapMask; // Optional mask
+ CGImageRef CreateCGImage() const;
+
+ // returns true if the bitmap has a size that
+ // can be natively transferred into a true icon
+ // if no is returned GetIconRef will still produce
+ // an icon but it will be generated via a PICT and
+ // rescaled to 16 x 16
+ bool HasNativeSize();
+
+ // caller should increase ref count if needed longer
+ // than the bitmap exists
+ IconRef GetIconRef();
+
+#ifndef __WXOSX_IPHONE__
+ // returns a Pict from the bitmap content
+ PicHandle GetPictHandle();
+#endif
+
+ CGContextRef GetBitmapContext() const;
+
+ int GetBytesPerRow() const { return m_bytesPerRow; }
+ private :
+ bool Create(int width , int height , int depth);
+ void Init();
+
+ int m_width;
+ int m_height;
+ int m_bytesPerRow;
+ int m_depth;
+ bool m_hasAlpha;
+ wxMemoryBuffer m_memBuf;
+ int m_rawAccessCount;
+ bool m_ok;
+ mutable CGImageRef m_cgImageRef;
+
+ IconRef m_iconRef;
+#ifndef __WXOSX_IPHONE__
+ PicHandle m_pictHandle;
+#endif
+ CGContextRef m_hBitmap;
+};
+
+
+#define wxMAC_USE_PREMULTIPLIED_ALPHA 1
+static const int kBestByteAlignement = 16;
+static const int kMaskBytesPerPixel = 1;
+
+static int GetBestBytesPerRow( int rawBytes )
+{
+ return (((rawBytes)+kBestByteAlignement-1) & ~(kBestByteAlignement-1) );
+}
+
+#if wxUSE_GUI && !defined(__WXOSX_IPHONE__)
+
+// this is used for more controls than just the wxBitmap button, also for notebooks etc
+
+void wxMacCreateBitmapButton( ControlButtonContentInfo*info , const wxBitmap& bitmap , int forceType )
+{
+ memset( info , 0 , sizeof(ControlButtonContentInfo) ) ;
+ if ( bitmap.Ok() )
+ {
+ wxBitmapRefData * bmap = bitmap.GetBitmapData() ;
+ if ( bmap == NULL )
+ return ;
+
+ if ( forceType == 0 )
+ {
+ forceType = kControlContentCGImageRef;
+ }
+
+ if ( forceType == kControlContentIconRef )
+ {
+ wxBitmap scaleBmp ;
+ wxBitmapRefData* bmp = bmap ;
+
+ if ( !bmap->HasNativeSize() )
+ {
+ // as PICT conversion will only result in a 16x16 icon, let's attempt
+ // a few scales for better results
+
+ int w = bitmap.GetWidth() ;
+ int h = bitmap.GetHeight() ;
+ int sz = wxMax( w , h ) ;
+ if ( sz == 24 || sz == 64 )
+ {
+ scaleBmp = wxBitmap( bitmap.ConvertToImage().Scale( w * 2 , h * 2 ) ) ;
+ bmp = scaleBmp.GetBitmapData() ;
+ }
+ }
+
+ info->contentType = kControlContentIconRef ;
+ info->u.iconRef = bmp->GetIconRef() ;
+ AcquireIconRef( info->u.iconRef ) ;
+ }
+ else if ( forceType == kControlContentCGImageRef )
+ {
+ info->contentType = kControlContentCGImageRef ;
+ info->u.imageRef = (CGImageRef) bmap->CreateCGImage() ;
+ }
+ else
+ {
+#ifndef __LP64__
+ info->contentType = kControlContentPictHandle ;
+ info->u.picture = bmap->GetPictHandle() ;
+#endif
+ }
+ }
+}
+
+CGImageRef wxMacCreateCGImageFromBitmap( const wxBitmap& bitmap )
+{
+ wxBitmapRefData * bmap = bitmap.GetBitmapData() ;
+ if ( bmap == NULL )
+ return NULL ;
+ return (CGImageRef) bmap->CreateCGImage();
+}
+
+void wxMacReleaseBitmapButton( ControlButtonContentInfo*info )
+{
+ if ( info->contentType == kControlContentIconRef )
+ {
+ ReleaseIconRef( info->u.iconRef ) ;
+ }
+ else if ( info->contentType == kControlNoContent )
+ {
+ // there's no bitmap at all, fall through silently
+ }
+ else if ( info->contentType == kControlContentPictHandle )
+ {
+ // owned by the bitmap, no release here
+ }
+ else if ( info->contentType == kControlContentCGImageRef )
+ {
+ CGImageRelease( info->u.imageRef ) ;
+ }
+ else
+ {
+ wxFAIL_MSG(wxT("Unexpected bitmap type") ) ;
+ }
+}
+
+#endif //wxUSE_BMPBUTTON
+
+#define M_BITMAPDATA ((wxBitmapRefData *)m_refData)
+
+void wxBitmapRefData::Init()
+{
+ m_width = 0 ;
+ m_height = 0 ;
+ m_depth = 0 ;
+ m_bytesPerRow = 0;
+ m_ok = false ;
+ m_bitmapMask = NULL ;
+ m_cgImageRef = NULL ;
+
+#ifndef __WXOSX_IPHONE__
+ m_iconRef = NULL ;
+ m_pictHandle = NULL ;
+#endif
+ m_hBitmap = NULL ;
+
+ m_rawAccessCount = 0 ;
+ m_hasAlpha = false;
+}
+
+wxBitmapRefData::wxBitmapRefData(const wxBitmapRefData &tocopy)
+{
+ Init();
+ Create(tocopy.m_width, tocopy.m_height, tocopy.m_depth);
+
+ if (tocopy.m_bitmapMask)
+ m_bitmapMask = new wxMask(*tocopy.m_bitmapMask);
+ else if (tocopy.m_hasAlpha)
+ UseAlpha(true);
+
+ unsigned char* dest = (unsigned char*)GetRawAccess();
+ unsigned char* source = (unsigned char*)tocopy.GetRawAccess();
+ size_t numbytes = m_bytesPerRow * m_height;
+ memcpy( dest, source, numbytes );
+}
+
+wxBitmapRefData::wxBitmapRefData()
+{
+ Init() ;
+}
+
+wxBitmapRefData::wxBitmapRefData( int w , int h , int d )
+{
+ Init() ;
+ Create( w , h , d ) ;
+}
+
+bool wxBitmapRefData::Create( int w , int h , int d )
+{
+ m_width = wxMax(1, w);
+ m_height = wxMax(1, h);
+ m_depth = d ;
+ m_hBitmap = NULL ;
+
+ m_bytesPerRow = GetBestBytesPerRow( w * 4 ) ;
+ size_t size = m_bytesPerRow * h ;
+ void* data = m_memBuf.GetWriteBuf( size ) ;
+ if ( data != NULL )
+ {
+ memset( data , 0 , size ) ;
+ m_memBuf.UngetWriteBuf( size ) ;
+
+ m_hBitmap = CGBitmapContextCreate((char*) data, m_width, m_height, 8, m_bytesPerRow, wxMacGetGenericRGBColorSpace(), kCGImageAlphaNoneSkipFirst );
+ wxASSERT_MSG( m_hBitmap , wxT("Unable to create CGBitmapContext context") ) ;
+ CGContextTranslateCTM( m_hBitmap, 0, m_height );
+ CGContextScaleCTM( m_hBitmap, 1, -1 );
+ } /* data != NULL */
+ m_ok = ( m_hBitmap != NULL ) ;
+
+ return m_ok ;
+}
+
+void wxBitmapRefData::UseAlpha( bool use )
+{
+ if ( m_hasAlpha == use )
+ return ;
+
+ m_hasAlpha = use ;
+
+ CGContextRelease( m_hBitmap );
+ m_hBitmap = CGBitmapContextCreate((char*) m_memBuf.GetData(), m_width, m_height, 8, m_bytesPerRow, wxMacGetGenericRGBColorSpace(), m_hasAlpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst );
+ wxASSERT_MSG( m_hBitmap , wxT("Unable to create CGBitmapContext context") ) ;
+ CGContextTranslateCTM( m_hBitmap, 0, m_height );
+ CGContextScaleCTM( m_hBitmap, 1, -1 );
+}
+
+void *wxBitmapRefData::GetRawAccess() const
+{
+ wxCHECK_MSG( IsOk(), NULL , wxT("invalid bitmap") ) ;
+ return m_memBuf.GetData() ;
+}
+
+void *wxBitmapRefData::BeginRawAccess()
+{
+ wxCHECK_MSG( IsOk(), NULL, wxT("invalid bitmap") ) ;
+ wxASSERT( m_rawAccessCount == 0 ) ;
+#ifndef __WXOSX_IPHONE__
+ wxASSERT_MSG( m_pictHandle == NULL && m_iconRef == NULL ,
+ wxT("Currently, modifing bitmaps that are used in controls already is not supported") ) ;
+#endif
+ ++m_rawAccessCount ;
+
+ // we must destroy an existing cached image, as
+ // the bitmap data may change now
+ if ( m_cgImageRef )
+ {
+ CGImageRelease( m_cgImageRef ) ;
+ m_cgImageRef = NULL ;
+ }
+
+ return m_memBuf.GetData() ;
+}
+
+void wxBitmapRefData::EndRawAccess()
+{
+ wxCHECK_RET( IsOk() , wxT("invalid bitmap") ) ;
+ wxASSERT( m_rawAccessCount == 1 ) ;
+
+ --m_rawAccessCount ;
+}
+
+bool wxBitmapRefData::HasNativeSize()
+{
+ int w = GetWidth() ;
+ int h = GetHeight() ;
+ int sz = wxMax( w , h ) ;
+
+ return ( sz == 128 || sz == 48 || sz == 32 || sz == 16 );
+}
+
+#ifndef __WXOSX_IPHONE__
+IconRef wxBitmapRefData::GetIconRef()
+{
+ if ( m_iconRef == NULL )
+ {
+ // Create Icon Family Handle
+
+ IconFamilyHandle iconFamily = (IconFamilyHandle) NewHandle( 0 );
+
+ int w = GetWidth() ;
+ int h = GetHeight() ;
+ int sz = wxMax( w , h ) ;
+
+ OSType dataType = 0 ;
+ OSType maskType = 0 ;
+
+ switch (sz)
+ {
+ case 128:
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+ if ( UMAGetSystemVersion() >= 0x1050 )
+ {
+ dataType = kIconServices128PixelDataARGB ;
+ }
+ else
+#endif
+ {
+ dataType = kThumbnail32BitData ;
+ maskType = kThumbnail8BitMask ;
+ }
+ break;
+
+ case 48:
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+ if ( UMAGetSystemVersion() >= 0x1050 )
+ {
+ dataType = kIconServices48PixelDataARGB ;
+ }
+ else
+#endif
+ {
+ dataType = kHuge32BitData ;
+ maskType = kHuge8BitMask ;
+ }
+ break;
+
+ case 32:
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+ if ( UMAGetSystemVersion() >= 0x1050 )
+ {
+ dataType = kIconServices32PixelDataARGB ;
+ }
+ else
+#endif
+ {
+ dataType = kLarge32BitData ;
+ maskType = kLarge8BitMask ;
+ }
+ break;
+
+ case 16:
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+ if ( UMAGetSystemVersion() >= 0x1050 )
+ {
+ dataType = kIconServices16PixelDataARGB ;
+ }
+ else
+#endif
+ {
+ dataType = kSmall32BitData ;
+ maskType = kSmall8BitMask ;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if ( dataType != 0 )
+ {
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+ if ( maskType == 0 && UMAGetSystemVersion() >= 0x1050 )
+ {
+ size_t datasize = sz * sz * 4 ;
+ Handle data = NewHandle( datasize ) ;
+ HLock( data ) ;
+ unsigned char* ptr = (unsigned char*) *data ;
+ memset( ptr, 0, datasize );
+ bool hasAlpha = HasAlpha() ;
+ wxMask *mask = m_bitmapMask ;
+ unsigned char * sourcePtr = (unsigned char*) GetRawAccess() ;
+ unsigned char * masksourcePtr = mask ? (unsigned char*) mask->GetRawAccess() : NULL ;
+
+ for ( int y = 0 ; y < h ; ++y, sourcePtr += m_bytesPerRow , masksourcePtr += mask ? mask->GetBytesPerRow() : 0 )
+ {
+ unsigned char * source = sourcePtr;
+ unsigned char * masksource = masksourcePtr;
+ unsigned char * dest = ptr + y * sz * 4 ;
+ unsigned char a, r, g, b;
+
+ for ( int x = 0 ; x < w ; ++x )
+ {
+ a = *source ++ ;
+ r = *source ++ ;
+ g = *source ++ ;
+ b = *source ++ ;
+
+ if ( mask )
+ {
+ a = 0xFF - *masksource++ ;
+ }
+ else if ( !hasAlpha )
+ a = 0xFF ;
+ else
+ {
+#if wxMAC_USE_PREMULTIPLIED_ALPHA
+ // this must be non-premultiplied data
+ if ( a != 0xFF && a!= 0 )
+ {
+ r = r * 255 / a;
+ g = g * 255 / a;
+ b = b * 255 / a;
+ }
+#endif
+ }
+ *dest++ = a ;
+ *dest++ = r ;
+ *dest++ = g ;
+ *dest++ = b ;
+
+ }
+ }
+ HUnlock( data );
+ OSStatus err = SetIconFamilyData( iconFamily, dataType , data );
+ wxASSERT_MSG( err == noErr , wxT("Error when adding bitmap") );
+ DisposeHandle( data );
+ }
+ else
+#endif
+ {
+ // setup the header properly
+
+ Handle data = NULL ;
+ Handle maskdata = NULL ;
+ unsigned char * maskptr = NULL ;
+ unsigned char * ptr = NULL ;
+ size_t datasize, masksize ;
+
+ datasize = sz * sz * 4 ;
+ data = NewHandle( datasize ) ;
+ HLock( data ) ;
+ ptr = (unsigned char*) *data ;
+ memset( ptr , 0, datasize ) ;
+
+ masksize = sz * sz ;
+ maskdata = NewHandle( masksize ) ;
+ HLock( maskdata ) ;
+ maskptr = (unsigned char*) *maskdata ;
+ memset( maskptr , 0 , masksize ) ;
+
+ bool hasAlpha = HasAlpha() ;
+ wxMask *mask = m_bitmapMask ;
+ unsigned char * sourcePtr = (unsigned char*) GetRawAccess() ;
+ unsigned char * masksourcePtr = mask ? (unsigned char*) mask->GetRawAccess() : NULL ;
+
+ for ( int y = 0 ; y < h ; ++y, sourcePtr += m_bytesPerRow , masksourcePtr += mask ? mask->GetBytesPerRow() : 0 )
+ {
+ unsigned char * source = sourcePtr;
+ unsigned char * masksource = masksourcePtr;
+ unsigned char * dest = ptr + y * sz * 4 ;
+ unsigned char * maskdest = maskptr + y * sz ;
+ unsigned char a, r, g, b;
+
+ for ( int x = 0 ; x < w ; ++x )
+ {
+ a = *source ++ ;
+ r = *source ++ ;
+ g = *source ++ ;
+ b = *source ++ ;
+
+ *dest++ = 0 ;
+ *dest++ = r ;
+ *dest++ = g ;
+ *dest++ = b ;
+
+ if ( mask )
+ *maskdest++ = 0xFF - *masksource++ ;
+ else if ( hasAlpha )
+ *maskdest++ = a ;
+ else
+ *maskdest++ = 0xFF ;
+ }
+ }
+
+ OSStatus err = SetIconFamilyData( iconFamily, dataType , data ) ;
+ wxASSERT_MSG( err == noErr , wxT("Error when adding bitmap") ) ;
+
+ err = SetIconFamilyData( iconFamily, maskType , maskdata ) ;
+ wxASSERT_MSG( err == noErr , wxT("Error when adding mask") ) ;
+
+ HUnlock( data ) ;
+ HUnlock( maskdata ) ;
+ DisposeHandle( data ) ;
+ DisposeHandle( maskdata ) ;
+ }
+ }
+ else
+ {
+ PicHandle pic = GetPictHandle() ;
+ SetIconFamilyData( iconFamily, 'PICT' , (Handle) pic ) ;
+ }
+ // transform into IconRef
+
+ // cleaner version existing from 10.3 upwards
+ HLock((Handle) iconFamily);
+ OSStatus err = GetIconRefFromIconFamilyPtr( *iconFamily, GetHandleSize((Handle) iconFamily), &m_iconRef );
+ HUnlock((Handle) iconFamily);
+ DisposeHandle( (Handle) iconFamily ) ;
+
+ wxCHECK_MSG( err == noErr, NULL, wxT("Error when constructing icon ref") );
+ }
+
+ return m_iconRef ;
+}
+
+PicHandle wxBitmapRefData::GetPictHandle()
+{
+ if ( m_pictHandle == NULL )
+ {
+#ifndef __LP64__
+ GraphicsExportComponent exporter = 0;
+ OSStatus err = OpenADefaultComponent(GraphicsExporterComponentType, kQTFileTypePicture, &exporter);
+ if (noErr == err)
+ {
+ m_pictHandle = (PicHandle) NewHandle(0);
+ if ( m_pictHandle )
+ {
+ // QT does not correctly export the mask
+ // TODO if we get around to it create a synthetic PICT with the CopyBits and Mask commands
+ CGImageRef imageRef = CreateCGImage();
+ err = GraphicsExportSetInputCGImage( exporter, imageRef );
+ err = GraphicsExportSetOutputHandle(exporter, (Handle)m_pictHandle);
+ err = GraphicsExportDoExport(exporter, NULL);
+ CGImageRelease( imageRef );
+
+ size_t handleSize = GetHandleSize( (Handle) m_pictHandle );
+ // the 512 bytes header is only needed for pict files, but not in memory
+ if ( handleSize >= 512 )
+ {
+ memmove( *m_pictHandle , (char*)(*m_pictHandle)+512, handleSize - 512 );
+ SetHandleSize( (Handle) m_pictHandle, handleSize - 512 );
+ }
+ }
+ CloseComponent( exporter );
+ }
+#endif
+ }
+
+ return m_pictHandle ;
+}
+#endif
+
+CGImageRef wxBitmapRefData::CreateCGImage() const
+{
+ wxASSERT( m_ok ) ;
+ wxASSERT( m_rawAccessCount >= 0 ) ;
+ CGImageRef image ;
+ if ( m_rawAccessCount > 0 || m_cgImageRef == NULL )
+ {
+ if ( m_depth != 1 && m_bitmapMask == NULL )
+ {
+ if ( m_bitmapMask )
+ {
+ CGImageRef tempImage = CGBitmapContextCreateImage( m_hBitmap );
+ CGImageRef tempMask = CGBitmapContextCreateImage((CGContextRef) m_bitmapMask->GetHBITMAP() );
+ image = CGImageCreateWithMask( tempImage, tempMask );
+ CGImageRelease(tempMask);
+ CGImageRelease(tempImage);
+ }
+ else
+ image = CGBitmapContextCreateImage( m_hBitmap );
+ }
+ else
+ {
+ size_t imageSize = m_height * m_bytesPerRow ;
+ void * dataBuffer = m_memBuf.GetData() ;
+ int w = m_width ;
+ int h = m_height ;
+ CGImageAlphaInfo alphaInfo = kCGImageAlphaNoneSkipFirst ;
+ wxMemoryBuffer membuf;
+
+ if ( m_bitmapMask )
+ {
+ alphaInfo = kCGImageAlphaFirst ;
+ unsigned char *destalphastart = (unsigned char*) membuf.GetWriteBuf( imageSize ) ;
+ memcpy( destalphastart , dataBuffer , imageSize ) ;
+ unsigned char *sourcemaskstart = (unsigned char *) m_bitmapMask->GetRawAccess() ;
+ int maskrowbytes = m_bitmapMask->GetBytesPerRow() ;
+ for ( int y = 0 ; y < h ; ++y , destalphastart += m_bytesPerRow, sourcemaskstart += maskrowbytes)
+ {
+ unsigned char *sourcemask = sourcemaskstart ;
+ unsigned char *destalpha = destalphastart ;
+ for ( int x = 0 ; x < w ; ++x , sourcemask += kMaskBytesPerPixel , destalpha += 4 )
+ {
+ *destalpha = 0xFF - *sourcemask ;
+ }
+ }
+ membuf.UngetWriteBuf( imageSize );
+ }
+ else
+ {
+ if ( m_hasAlpha )
+ {
+#if wxMAC_USE_PREMULTIPLIED_ALPHA
+ alphaInfo = kCGImageAlphaPremultipliedFirst ;
+#else
+ alphaInfo = kCGImageAlphaFirst ;
+#endif
+ }
+
+ membuf = m_memBuf;
+ }
+
+ CGDataProviderRef dataProvider = NULL ;
+ if ( m_depth == 1 )
+ {
+ // TODO CHECK ALIGNMENT
+ wxMemoryBuffer maskBuf;
+ unsigned char * maskBufData = (unsigned char*) maskBuf.GetWriteBuf( m_width * m_height );
+ unsigned char * bufData = (unsigned char *) membuf.GetData() ;
+ // copy one color component
+ size_t i = 0;
+ for( int y = 0 ; y < m_height ; bufData+= m_bytesPerRow, ++y )
+ {
+ unsigned char *bufDataIter = bufData+3;
+ for ( int x = 0 ; x < m_width ; bufDataIter += 4, ++x, ++i )
+ {
+ maskBufData[i] = *bufDataIter;
+ }
+ }
+ maskBuf.UngetWriteBuf( m_width * m_height );
+
+ dataProvider =
+ wxMacCGDataProviderCreateWithMemoryBuffer( maskBuf );
+
+ image = ::CGImageMaskCreate( w, h, 8, 8, m_width , dataProvider, NULL, false );
+ }
+ else
+ {
+ CGColorSpaceRef colorSpace = wxMacGetGenericRGBColorSpace();
+ dataProvider = wxMacCGDataProviderCreateWithMemoryBuffer( membuf );
+ image =
+ ::CGImageCreate(
+ w, h, 8 , 32 , m_bytesPerRow , colorSpace, alphaInfo ,
+ dataProvider, NULL , false , kCGRenderingIntentDefault );
+ }
+ CGDataProviderRelease( dataProvider);
+ }
+ }
+ else
+ {
+ image = m_cgImageRef ;
+ CGImageRetain( image ) ;
+ }
+
+ if ( m_rawAccessCount == 0 && m_cgImageRef == NULL)
+ {
+ // we keep it for later use
+ m_cgImageRef = image ;
+ CGImageRetain( image ) ;
+ }
+
+ return image ;
+}
+
+CGContextRef wxBitmapRefData::GetBitmapContext() const
+{
+ return m_hBitmap;
+}
+
+void wxBitmapRefData::Free()
+{
+ wxASSERT_MSG( m_rawAccessCount == 0 , wxT("Bitmap still selected when destroyed") ) ;
+
+ if ( m_cgImageRef )
+ {
+ CGImageRelease( m_cgImageRef ) ;
+ m_cgImageRef = NULL ;
+ }
+#ifndef __WXOSX_IPHONE__
+ if ( m_iconRef )
+ {
+ ReleaseIconRef( m_iconRef ) ;
+ m_iconRef = NULL ;
+ }
+
+#ifndef __LP64__
+ if ( m_pictHandle )
+ {
+ KillPicture( m_pictHandle ) ;
+ m_pictHandle = NULL ;
+ }
+#endif
+#endif
+ if ( m_hBitmap )
+ {
+ CGContextRelease(m_hBitmap);
+ m_hBitmap = NULL ;
+ }
+
+ if (m_bitmapMask)
+ {
+ delete m_bitmapMask;
+ m_bitmapMask = NULL;
+ }
+}
+
+wxBitmapRefData::~wxBitmapRefData()
+{
+ Free() ;
+}
+
+bool wxBitmap::CopyFromIcon(const wxIcon& icon)
+{
+ bool created = false ;
+ int w = icon.GetWidth() ;
+ int h = icon.GetHeight() ;
+
+ Create( icon.GetWidth() , icon.GetHeight() ) ;
+#ifndef __WXOSX_IPHONE__
+ if ( w == h && ( w == 16 || w == 32 || w == 48 || w == 128 ) )
+ {
+ IconFamilyHandle iconFamily = NULL ;
+ Handle imagehandle = NewHandle( 0 ) ;
+ Handle maskhandle = NewHandle( 0 ) ;
+
+ OSType maskType = 0;
+ OSType dataType = 0;
+ IconSelectorValue selector = 0 ;
+
+ switch (w)
+ {
+ case 128:
+ dataType = kThumbnail32BitData ;
+ maskType = kThumbnail8BitMask ;
+ selector = kSelectorAllAvailableData ;
+ break;
+
+ case 48:
+ dataType = kHuge32BitData ;
+ maskType = kHuge8BitMask ;
+ selector = kSelectorHuge32Bit | kSelectorHuge8BitMask ;
+ break;
+
+ case 32:
+ dataType = kLarge32BitData ;
+ maskType = kLarge8BitMask ;
+ selector = kSelectorLarge32Bit | kSelectorLarge8BitMask ;
+ break;
+
+ case 16:
+ dataType = kSmall32BitData ;
+ maskType = kSmall8BitMask ;
+ selector = kSelectorSmall32Bit | kSelectorSmall8BitMask ;
+ break;
+
+ default:
+ break;
+ }
+
+ OSStatus err = IconRefToIconFamily( MAC_WXHICON(icon.GetHICON()) , selector , &iconFamily ) ;
+
+ err = GetIconFamilyData( iconFamily , dataType , imagehandle ) ;
+ err = GetIconFamilyData( iconFamily , maskType , maskhandle ) ;
+ size_t imagehandlesize = GetHandleSize( imagehandle ) ;
+ size_t maskhandlesize = GetHandleSize( maskhandle ) ;
+
+ if ( imagehandlesize != 0 && maskhandlesize != 0 )
+ {
+ wxASSERT( GetHandleSize( imagehandle ) == w * 4 * h ) ;
+ wxASSERT( GetHandleSize( maskhandle ) == w * h ) ;
+
+ UseAlpha() ;
+
+ unsigned char *source = (unsigned char *) *imagehandle ;
+ unsigned char *sourcemask = (unsigned char *) *maskhandle ;
+ unsigned char* destination = (unsigned char*) BeginRawAccess() ;
+
+ for ( int y = 0 ; y < h ; ++y )
+ {
+ for ( int x = 0 ; x < w ; ++x )
+ {
+ unsigned char a = *sourcemask++;
+ *destination++ = a;
+ source++ ;
+#if wxMAC_USE_PREMULTIPLIED_ALPHA
+ *destination++ = ( (*source++) * a + 127 ) / 255;
+ *destination++ = ( (*source++) * a + 127 ) / 255;
+ *destination++ = ( (*source++) * a + 127 ) / 255;
+#else
+ *destination++ = *source++ ;
+ *destination++ = *source++ ;
+ *destination++ = *source++ ;
+#endif
+ }
+ }
+
+ EndRawAccess() ;
+ DisposeHandle( imagehandle ) ;
+ DisposeHandle( maskhandle ) ;
+ created = true ;
+ }
+
+ DisposeHandle( (Handle) iconFamily ) ;
+ }
+#endif
+ if ( !created )
+ {
+ wxMemoryDC dc ;
+ dc.SelectObject( *this ) ;
+ dc.DrawIcon( icon , 0 , 0 ) ;
+ dc.SelectObject( wxNullBitmap ) ;
+ }
+
+ return true;
+}
+
+wxBitmap::wxBitmap()
+{
+}
+
+wxBitmap::~wxBitmap()
+{
+}
+
+wxBitmap::wxBitmap(const char bits[], int the_width, int the_height, int no_bits)
+{
+ wxBitmapRefData* bitmapRefData;
+
+ m_refData = bitmapRefData = new wxBitmapRefData( the_width , the_height , no_bits ) ;
+
+ if (bitmapRefData->IsOk())
+ {
+ if ( no_bits == 1 )
+ {
+ int linesize = ( the_width / (sizeof(unsigned char) * 8)) ;
+ if ( the_width % (sizeof(unsigned char) * 8) )
+ linesize += sizeof(unsigned char);
+
+ unsigned char* linestart = (unsigned char*) bits ;
+ unsigned char* destptr = (unsigned char*) BeginRawAccess() ;
+
+ for ( int y = 0 ; y < the_height ; ++y , linestart += linesize, destptr += M_BITMAPDATA->GetBytesPerRow() )
+ {
+ unsigned char* destination = destptr;
+ int index, bit, mask;
+
+ for ( int x = 0 ; x < the_width ; ++x )
+ {
+ index = x / 8 ;
+ bit = x % 8 ;
+ mask = 1 << bit ;
+
+ if ( linestart[index] & mask )
+ {
+ *destination++ = 0xFF ;
+ *destination++ = 0 ;
+ *destination++ = 0 ;
+ *destination++ = 0 ;
+ }
+ else
+ {
+ *destination++ = 0xFF ;
+ *destination++ = 0xFF ;
+ *destination++ = 0xFF ;
+ *destination++ = 0xFF ;
+ }
+ }
+ }
+
+ EndRawAccess() ;
+ }
+ else
+ {
+ wxFAIL_MSG(wxT("multicolor BITMAPs not yet implemented"));
+ }
+ } /* bitmapRefData->IsOk() */
+}
+
+wxBitmap::wxBitmap(int w, int h, int d)
+{
+ (void)Create(w, h, d);
+}
+
+wxBitmap::wxBitmap(const void* data, wxBitmapType type, int width, int height, int depth)
+{
+ (void) Create(data, type, width, height, depth);
+}
+
+wxBitmap::wxBitmap(const wxString& filename, wxBitmapType type)
+{
+ LoadFile(filename, type);
+}
+
+wxGDIRefData* wxBitmap::CreateGDIRefData() const
+{
+ return new wxBitmapRefData;
+}
+
+wxGDIRefData* wxBitmap::CloneGDIRefData(const wxGDIRefData* data) const
+{
+ return new wxBitmapRefData(*wx_static_cast(const wxBitmapRefData *, data));
+}
+
+void * wxBitmap::GetRawAccess() const
+{
+ wxCHECK_MSG( Ok() , NULL , wxT("invalid bitmap") ) ;
+
+ return M_BITMAPDATA->GetRawAccess() ;
+}
+
+void * wxBitmap::BeginRawAccess()
+{
+ wxCHECK_MSG( Ok() , NULL , wxT("invalid bitmap") ) ;
+
+ return M_BITMAPDATA->BeginRawAccess() ;
+}
+
+void wxBitmap::EndRawAccess()
+{
+ wxCHECK_RET( Ok() , wxT("invalid bitmap") ) ;
+
+ M_BITMAPDATA->EndRawAccess() ;
+}
+
+CGImageRef wxBitmap::CreateCGImage() const
+{
+ wxCHECK_MSG( Ok(), NULL , wxT("invalid bitmap") ) ;
+
+ return M_BITMAPDATA->CreateCGImage() ;
+}
+
+#ifndef __WXOSX_IPHONE__
+IconRef wxBitmap::GetIconRef() const
+{
+ wxCHECK_MSG( Ok(), NULL , wxT("invalid bitmap") ) ;
+
+ return M_BITMAPDATA->GetIconRef() ;
+}
+
+IconRef wxBitmap::CreateIconRef() const
+{
+ IconRef icon = GetIconRef();
+ verify_noerr( AcquireIconRef(icon) );
+ return icon;
+}
+#endif
+
+wxBitmap wxBitmap::GetSubBitmap(const wxRect &rect) const
+{
+ wxCHECK_MSG( Ok() &&
+ (rect.x >= 0) && (rect.y >= 0) &&
+ (rect.x+rect.width <= GetWidth()) &&
+ (rect.y+rect.height <= GetHeight()),
+ wxNullBitmap, wxT("invalid bitmap or bitmap region") );
+
+ wxBitmap ret( rect.width, rect.height, GetDepth() );
+ wxASSERT_MSG( ret.Ok(), wxT("GetSubBitmap error") );
+
+ int destwidth = rect.width ;
+ int destheight = rect.height ;
+
+ {
+ unsigned char *sourcedata = (unsigned char*) GetRawAccess() ;
+ unsigned char *destdata = (unsigned char*) ret.BeginRawAccess() ;
+ wxASSERT( (sourcedata != NULL) && (destdata != NULL) ) ;
+
+ int sourcelinesize = GetBitmapData()->GetBytesPerRow() ;
+ int destlinesize = ret.GetBitmapData()->GetBytesPerRow() ;
+ unsigned char *source = sourcedata + rect.x * 4 + rect.y * sourcelinesize ;
+ unsigned char *dest = destdata ;
+
+ for (int yy = 0; yy < destheight; ++yy, source += sourcelinesize , dest += destlinesize)
+ {
+ memcpy( dest , source , destlinesize ) ;
+ }
+ }
+
+ ret.EndRawAccess() ;
+
+ if ( M_BITMAPDATA->m_bitmapMask )
+ {
+ wxMemoryBuffer maskbuf ;
+ int rowBytes = GetBestBytesPerRow( destwidth * kMaskBytesPerPixel );
+ size_t maskbufsize = rowBytes * destheight ;
+
+ int sourcelinesize = M_BITMAPDATA->m_bitmapMask->GetBytesPerRow() ;
+ int destlinesize = rowBytes ;
+
+ unsigned char *source = (unsigned char *) M_BITMAPDATA->m_bitmapMask->GetRawAccess() ;
+ unsigned char *destdata = (unsigned char * ) maskbuf.GetWriteBuf( maskbufsize ) ;
+ wxASSERT( (source != NULL) && (destdata != NULL) ) ;
+
+ source += rect.x * kMaskBytesPerPixel + rect.y * sourcelinesize ;
+ unsigned char *dest = destdata ;
+
+ for (int yy = 0; yy < destheight; ++yy, source += sourcelinesize , dest += destlinesize)
+ {
+ memcpy( dest , source , destlinesize ) ;
+ }
+
+ maskbuf.UngetWriteBuf( maskbufsize ) ;
+ ret.SetMask( new wxMask( maskbuf , destwidth , destheight , rowBytes ) ) ;
+ }
+ else if ( HasAlpha() )
+ ret.UseAlpha() ;
+
+ return ret;
+}
+
+bool wxBitmap::Create(int w, int h, int d)
+{
+ UnRef();
+
+ if ( d < 0 )
+ d = wxDisplayDepth() ;
+
+ m_refData = new wxBitmapRefData( w , h , d );
+
+ return M_BITMAPDATA->IsOk() ;
+}
+
+bool wxBitmap::LoadFile(const wxString& filename, wxBitmapType type)
+{
+ UnRef();
+
+ wxBitmapHandler *handler = FindHandler(type);
+
+ if ( handler )
+ {
+ m_refData = new wxBitmapRefData;
+
+ return handler->LoadFile(this, filename, type, -1, -1);
+ }
+ else
+ {
+#if wxUSE_IMAGE
+ wxImage loadimage(filename, type);
+ if (loadimage.Ok())
+ {
+ *this = loadimage;
+
+ return true;
+ }
+#endif
+ }
+
+ wxLogWarning(wxT("no bitmap handler for type %d defined."), type);
+
+ return false;
+}
+
+bool wxBitmap::Create(const void* data, wxBitmapType type, int width, int height, int depth)
+{
+ UnRef();
+
+ m_refData = new wxBitmapRefData;
+
+ wxBitmapHandler *handler = FindHandler(type);
+
+ if ( handler == NULL )
+ {
+ wxLogWarning(wxT("no bitmap handler for type %d defined."), type);
+
+ return false;
+ }
+
+ return handler->Create(this, data, type, width, height, depth);
+}
+
+#if wxUSE_IMAGE
+
+wxBitmap::wxBitmap(const wxImage& image, int depth)
+{
+ wxCHECK_RET( image.Ok(), wxT("invalid image") );
+
+ // width and height of the device-dependent bitmap
+ int width = image.GetWidth();
+ int height = image.GetHeight();
+
+ wxBitmapRefData* bitmapRefData;
+
+ m_refData = bitmapRefData = new wxBitmapRefData( width , height , depth ) ;
+
+ if ( bitmapRefData->IsOk())
+ {
+ // Create picture
+
+ bool hasAlpha = false ;
+
+ if ( image.HasMask() )
+ {
+ // takes precedence, don't mix with alpha info
+ }
+ else
+ {
+ hasAlpha = image.HasAlpha() ;
+ }
+
+ if ( hasAlpha )
+ UseAlpha() ;
+
+ unsigned char* destinationstart = (unsigned char*) BeginRawAccess() ;
+ register unsigned char* data = image.GetData();
+ if ( destinationstart != NULL && data != NULL )
+ {
+ const unsigned char *alpha = hasAlpha ? image.GetAlpha() : NULL ;
+ for (int y = 0; y < height; destinationstart += M_BITMAPDATA->GetBytesPerRow(), y++)
+ {
+ unsigned char * destination = destinationstart;
+ for (int x = 0; x < width; x++)
+ {
+ if ( hasAlpha )
+ {
+ const unsigned char a = *alpha++;
+ *destination++ = a ;
+
+ #if wxMAC_USE_PREMULTIPLIED_ALPHA
+ *destination++ = ((*data++) * a + 127) / 255 ;
+ *destination++ = ((*data++) * a + 127) / 255 ;
+ *destination++ = ((*data++) * a + 127) / 255 ;
+ #else
+ *destination++ = *data++ ;
+ *destination++ = *data++ ;
+ *destination++ = *data++ ;
+ #endif
+ }
+ else
+ {
+ *destination++ = 0xFF ;
+ *destination++ = *data++ ;
+ *destination++ = *data++ ;
+ *destination++ = *data++ ;
+ }
+ }
+ }
+
+ EndRawAccess() ;
+ }
+ if ( image.HasMask() )
+ SetMask( new wxMask( *this , wxColour( image.GetMaskRed() , image.GetMaskGreen() , image.GetMaskBlue() ) ) ) ;
+ } /* bitmapRefData->IsOk() */
+}
+
+wxImage wxBitmap::ConvertToImage() const
+{
+ wxImage image;
+
+ wxCHECK_MSG( Ok(), wxNullImage, wxT("invalid bitmap") );
+
+ // create an wxImage object
+ int width = GetWidth();
+ int height = GetHeight();
+ image.Create( width, height );
+
+ unsigned char *data = image.GetData();
+ wxCHECK_MSG( data, wxNullImage, wxT("Could not allocate data for image") );
+
+ unsigned char* sourcestart = (unsigned char*) GetRawAccess() ;
+
+ bool hasAlpha = false ;
+ bool hasMask = false ;
+ int maskBytesPerRow = 0 ;
+ unsigned char *alpha = NULL ;
+ unsigned char *mask = NULL ;
+
+ if ( HasAlpha() )
+ hasAlpha = true ;
+
+ if ( GetMask() )
+ {
+ hasMask = true ;
+ mask = (unsigned char*) GetMask()->GetRawAccess() ;
+ maskBytesPerRow = GetMask()->GetBytesPerRow() ;
+ }
+
+ if ( hasAlpha )
+ {
+ image.SetAlpha() ;
+ alpha = image.GetAlpha() ;
+ }
+
+ int index = 0;
+
+ // The following masking algorithm is the same as well in msw/gtk:
+ // the colour used as transparent one in wxImage and the one it is
+ // replaced with when it actually occurs in the bitmap
+ static const int MASK_RED = 1;
+ static const int MASK_GREEN = 2;
+ static const int MASK_BLUE = 3;
+ static const int MASK_BLUE_REPLACEMENT = 2;
+
+ for (int yy = 0; yy < height; yy++ , sourcestart += M_BITMAPDATA->GetBytesPerRow() , mask += maskBytesPerRow )
+ {
+ unsigned char * maskp = mask ;
+ unsigned char * source = sourcestart;
+ unsigned char a, r, g, b;
+ long color;
+
+ for (int xx = 0; xx < width; xx++)
+ {
+ color = *((long*) source) ;
+#ifdef WORDS_BIGENDIAN
+ a = ((color&0xFF000000) >> 24) ;
+ r = ((color&0x00FF0000) >> 16) ;
+ g = ((color&0x0000FF00) >> 8) ;
+ b = (color&0x000000FF);
+#else
+ b = ((color&0xFF000000) >> 24) ;
+ g = ((color&0x00FF0000) >> 16) ;
+ r = ((color&0x0000FF00) >> 8) ;
+ a = (color&0x000000FF);
+#endif
+ if ( hasMask )
+ {
+ if ( *maskp++ == 0xFF )
+ {
+ r = MASK_RED ;
+ g = MASK_GREEN ;
+ b = MASK_BLUE ;
+ }
+ else if ( r == MASK_RED && g == MASK_GREEN && b == MASK_BLUE )
+ b = MASK_BLUE_REPLACEMENT ;
+ }
+ else if ( hasAlpha )
+ {
+ *alpha++ = a ;
+#if wxMAC_USE_PREMULTIPLIED_ALPHA
+ // this must be non-premultiplied data
+ if ( a != 0xFF && a!= 0 )
+ {
+ r = r * 255 / a;
+ g = g * 255 / a;
+ b = b * 255 / a;
+ }
+#endif
+ }
+
+ data[index ] = r ;
+ data[index + 1] = g ;
+ data[index + 2] = b ;
+
+ index += 3;
+ source += 4 ;
+ }
+ }
+
+ if ( hasMask )
+ image.SetMaskColour( MASK_RED, MASK_GREEN, MASK_BLUE );
+
+ return image;
+}
+
+#endif //wxUSE_IMAGE
+
+bool wxBitmap::SaveFile( const wxString& filename,
+ wxBitmapType type, const wxPalette *palette ) const
+{
+ bool success = false;
+ wxBitmapHandler *handler = FindHandler(type);
+
+ if ( handler )
+ {
+ success = handler->SaveFile(this, filename, type, palette);
+ }
+ else
+ {
+#if wxUSE_IMAGE
+ wxImage image = ConvertToImage();
+ success = image.SaveFile(filename, type);
+#else
+ wxLogWarning(wxT("no bitmap handler for type %d defined."), type);
+#endif
+ }
+
+ return success;
+}
+
+int wxBitmap::GetHeight() const
+{
+ wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
+
+ return M_BITMAPDATA->GetHeight();
+}
+
+int wxBitmap::GetWidth() const
+{
+ wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
+
+ return M_BITMAPDATA->GetWidth() ;
+}
+
+int wxBitmap::GetDepth() const
+{
+ wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
+
+ return M_BITMAPDATA->GetDepth();
+}
+
+wxMask *wxBitmap::GetMask() const
+{
+ wxCHECK_MSG( Ok(), (wxMask *) NULL, wxT("invalid bitmap") );
+
+ return M_BITMAPDATA->m_bitmapMask;
+}
+
+bool wxBitmap::HasAlpha() const
+{
+ wxCHECK_MSG( Ok(), false , wxT("invalid bitmap") );
+
+ return M_BITMAPDATA->HasAlpha() ;
+}
+
+void wxBitmap::SetWidth(int w)
+{
+ AllocExclusive();
+ M_BITMAPDATA->SetWidth(w);
+}
+
+void wxBitmap::SetHeight(int h)
+{
+ AllocExclusive();
+ M_BITMAPDATA->SetHeight(h);
+}
+
+void wxBitmap::SetDepth(int d)
+{
+ AllocExclusive();
+ M_BITMAPDATA->SetDepth(d);
+}
+
+void wxBitmap::SetOk(bool isOk)
+{
+ AllocExclusive();
+ M_BITMAPDATA->SetOk(isOk);
+}
+
+#if wxUSE_PALETTE
+wxPalette *wxBitmap::GetPalette() const
+{
+ wxCHECK_MSG( Ok(), NULL, wxT("Invalid bitmap GetPalette()") );
+
+ return &M_BITMAPDATA->m_bitmapPalette;
+}
+
+void wxBitmap::SetPalette(const wxPalette& palette)
+{
+ AllocExclusive();
+ M_BITMAPDATA->m_bitmapPalette = palette ;
+}
+#endif // wxUSE_PALETTE
+
+void wxBitmap::SetMask(wxMask *mask)
+{
+ AllocExclusive();
+ // Remove existing mask if there is one.
+ delete M_BITMAPDATA->m_bitmapMask;
+
+ M_BITMAPDATA->m_bitmapMask = mask ;
+}
+
+WXHBITMAP wxBitmap::GetHBITMAP(WXHBITMAP* mask) const
+{
+ wxUnusedVar(mask);
+
+ return WXHBITMAP(M_BITMAPDATA->GetBitmapContext());
+}
+
+// ----------------------------------------------------------------------------
+// wxMask
+// ----------------------------------------------------------------------------
+
+wxMask::wxMask()
+{
+ Init() ;
+}
+
+wxMask::wxMask(const wxMask &tocopy)
+{
+ Init();
+
+ m_bytesPerRow = tocopy.m_bytesPerRow;
+ m_width = tocopy.m_width;
+ m_height = tocopy.m_height;
+
+ size_t size = m_bytesPerRow * m_height;
+ unsigned char* dest = (unsigned char*)m_memBuf.GetWriteBuf( size );
+ unsigned char* source = (unsigned char*)tocopy.m_memBuf.GetData();
+ memcpy( dest, source, size );
+ m_memBuf.UngetWriteBuf( size ) ;
+ RealizeNative() ;
+}
+
+// Construct a mask from a bitmap and a colour indicating
+// the transparent area
+wxMask::wxMask( const wxBitmap& bitmap, const wxColour& colour )
+{
+ Init() ;
+ Create( bitmap, colour );
+}
+
+// Construct a mask from a mono bitmap (copies the bitmap).
+wxMask::wxMask( const wxBitmap& bitmap )
+{
+ Init() ;
+ Create( bitmap );
+}
+
+// Construct a mask from a mono bitmap (copies the bitmap).
+
+wxMask::wxMask( const wxMemoryBuffer& data, int width , int height , int bytesPerRow )
+{
+ Init() ;
+ Create( data, width , height , bytesPerRow );
+}
+
+wxMask::~wxMask()
+{
+ if ( m_maskBitmap )
+ {
+ CGContextRelease( (CGContextRef) m_maskBitmap );
+ m_maskBitmap = NULL ;
+ }
+}
+
+void wxMask::Init()
+{
+ m_width = m_height = m_bytesPerRow = 0 ;
+ m_maskBitmap = NULL ;
+}
+
+void *wxMask::GetRawAccess() const
+{
+ return m_memBuf.GetData() ;
+}
+
+// The default ColorTable for k8IndexedGrayPixelFormat in Intel appears to be broken, so we'll use an non-indexed
+// bitmap mask instead; in order to keep the code simple, the change applies to PowerPC implementations as well
+
+void wxMask::RealizeNative()
+{
+ if ( m_maskBitmap )
+ {
+ CGContextRelease( (CGContextRef) m_maskBitmap );
+ m_maskBitmap = NULL ;
+ }
+
+ CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceGray();
+ // from MouseTracking sample :
+ // Ironically, due to a bug in CGImageCreateWithMask, you cannot use
+ // CGColorSpaceCreateWithName(kCGColorSpaceGenericGray) at this point!
+
+ m_maskBitmap = CGBitmapContextCreate((char*) m_memBuf.GetData(), m_width, m_height, 8, m_bytesPerRow, colorspace,
+ kCGImageAlphaNone );
+ CGColorSpaceRelease( colorspace );
+ wxASSERT_MSG( m_maskBitmap , wxT("Unable to create CGBitmapContext context") ) ;
+}
+
+// Create a mask from a mono bitmap (copies the bitmap).
+
+bool wxMask::Create(const wxMemoryBuffer& data,int width , int height , int bytesPerRow)
+{
+ m_memBuf = data ;
+ m_width = width ;
+ m_height = height ;
+ m_bytesPerRow = bytesPerRow ;
+
+ wxASSERT( data.GetDataLen() == (size_t)(height * bytesPerRow) ) ;
+
+ RealizeNative() ;
+
+ return true ;
+}
+
+// Create a mask from a mono bitmap (copies the bitmap).
+bool wxMask::Create(const wxBitmap& bitmap)
+{
+ m_width = bitmap.GetWidth() ;
+ m_height = bitmap.GetHeight() ;
+ m_bytesPerRow = GetBestBytesPerRow( m_width * kMaskBytesPerPixel ) ;
+
+ size_t size = m_bytesPerRow * m_height ;
+ unsigned char * destdatabase = (unsigned char*) m_memBuf.GetWriteBuf( size ) ;
+ wxASSERT( destdatabase != NULL ) ;
+
+ memset( destdatabase , 0 , size ) ;
+ unsigned char * srcdata = (unsigned char*) bitmap.GetRawAccess() ;
+
+ for ( int y = 0 ; y < m_height ; ++y , destdatabase += m_bytesPerRow )
+ {
+ unsigned char *destdata = destdatabase ;
+ unsigned char r, g, b;
+
+ for ( int x = 0 ; x < m_width ; ++x )
+ {
+ srcdata++ ;
+ r = *srcdata++ ;
+ g = *srcdata++ ;
+ b = *srcdata++ ;
+
+ if ( ( r + g + b ) > 0x10 )
+ *destdata++ = 0xFF ;
+ else
+ *destdata++ = 0x00 ;
+ }
+ }
+
+ m_memBuf.UngetWriteBuf( size ) ;
+ RealizeNative() ;
+
+ return true;
+}
+
+// Create a mask from a bitmap and a colour indicating
+// the transparent area
+bool wxMask::Create(const wxBitmap& bitmap, const wxColour& colour)
+{
+ m_width = bitmap.GetWidth() ;
+ m_height = bitmap.GetHeight() ;
+ m_bytesPerRow = GetBestBytesPerRow( m_width * kMaskBytesPerPixel ) ;
+
+ size_t size = m_bytesPerRow * m_height ;
+ unsigned char * destdatabase = (unsigned char*) m_memBuf.GetWriteBuf( size ) ;
+ wxASSERT( destdatabase != NULL ) ;
+
+ memset( destdatabase , 0 , size ) ;
+ unsigned char * srcdatabase = (unsigned char*) bitmap.GetRawAccess() ;
+ size_t sourceBytesRow = bitmap.GetBitmapData()->GetBytesPerRow();
+
+ for ( int y = 0 ; y < m_height ; ++y , srcdatabase+= sourceBytesRow, destdatabase += m_bytesPerRow)
+ {
+ unsigned char *srcdata = srcdatabase ;
+ unsigned char *destdata = destdatabase ;
+ unsigned char r, g, b;
+
+ for ( int x = 0 ; x < m_width ; ++x )
+ {
+ srcdata++ ;
+ r = *srcdata++ ;
+ g = *srcdata++ ;
+ b = *srcdata++ ;
+
+ if ( colour == wxColour( r , g , b ) )
+ *destdata++ = 0xFF ;
+ else
+ *destdata++ = 0x00 ;
+ }
+ }
+
+ m_memBuf.UngetWriteBuf( size ) ;
+ RealizeNative() ;
+
+ return true;
+}
+
+WXHBITMAP wxMask::GetHBITMAP() const
+{
+ return m_maskBitmap ;
+}
+
+// ----------------------------------------------------------------------------
+// Standard Handlers
+// ----------------------------------------------------------------------------
+
+#if !defined( __LP64__ ) && !defined(__WXOSX_IPHONE__)
+
+class WXDLLEXPORT wxPICTResourceHandler: public wxBitmapHandler
+{
+ DECLARE_DYNAMIC_CLASS(wxPICTResourceHandler)
+
+public:
+ inline wxPICTResourceHandler()
+ {
+ SetName(wxT("Macintosh Pict resource"));
+ SetExtension(wxEmptyString);
+ SetType(wxBITMAP_TYPE_PICT_RESOURCE);
+ };
+
+ virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
+ int desiredWidth, int desiredHeight);
+};
+
+IMPLEMENT_DYNAMIC_CLASS(wxPICTResourceHandler, wxBitmapHandler)
+
+
+bool wxPICTResourceHandler::LoadFile(wxBitmap *bitmap,
+ const wxString& name,
+ long WXUNUSED(flags),
+ int WXUNUSED(desiredWidth),
+ int WXUNUSED(desiredHeight))
+{
+#if wxUSE_METAFILE
+ Str255 theName ;
+ wxMacStringToPascal( name , theName ) ;
+
+ PicHandle thePict = (PicHandle ) GetNamedResource( 'PICT' , theName ) ;
+ if ( thePict )
+ {
+ wxMetafile mf ;
+
+ mf.SetPICT( thePict ) ;
+ bitmap->Create( mf.GetWidth() , mf.GetHeight() ) ;
+ wxMemoryDC dc ;
+ dc.SelectObject( *bitmap ) ;
+ mf.Play( &dc ) ;
+ dc.SelectObject( wxNullBitmap ) ;
+
+ return true ;
+ }
+#endif
+
+ return false ;
+}
+#endif
+
+void wxBitmap::InitStandardHandlers()
+{
+#if !defined( __LP64__ ) && !defined(__WXOSX_IPHONE__)
+ AddHandler( new wxPICTResourceHandler ) ;
+#endif
+ AddHandler( new wxICONResourceHandler ) ;
+}
+
+// ----------------------------------------------------------------------------
+// raw bitmap access support
+// ----------------------------------------------------------------------------
+
+void *wxBitmap::GetRawData(wxPixelDataBase& data, int WXUNUSED(bpp))
+{
+ if ( !Ok() )
+ // no bitmap, no data (raw or otherwise)
+ return NULL;
+
+ data.m_width = GetWidth() ;
+ data.m_height = GetHeight() ;
+ data.m_stride = GetBitmapData()->GetBytesPerRow() ;
+
+ return BeginRawAccess() ;
+}
+
+void wxBitmap::UngetRawData(wxPixelDataBase& WXUNUSED(dataBase))
+{
+ EndRawAccess() ;
+}
+
+void wxBitmap::UseAlpha()
+{
+ // remember that we are using alpha channel:
+ // we'll need to create a proper mask in UngetRawData()
+ M_BITMAPDATA->UseAlpha( true );
+}
diff --git a/src/osx/carbon/bmpbuttn.cpp b/src/osx/carbon/bmpbuttn.cpp
new file mode 100644
index 0000000000..5757f50b84
--- /dev/null
+++ b/src/osx/carbon/bmpbuttn.cpp
@@ -0,0 +1,189 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/bmpbuttn.cpp
+// Purpose: wxBitmapButton
+// Author: Stefan Csomor
+// Modified by:
+// Created: 1998-01-01
+// RCS-ID: $Id$
+// Copyright: (c) Stefan Csomor
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/wxprec.h"
+
+#if wxUSE_BMPBUTTON
+
+#include "wx/bmpbuttn.h"
+#include "wx/image.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/dcmemory.h"
+#endif
+
+IMPLEMENT_DYNAMIC_CLASS(wxBitmapButton, wxButton)
+
+#include "wx/mac/uma.h"
+
+//---------------------------------------------------------------------------
+// Helper functions
+
+static wxBitmap wxMakeStdSizeBitmap(const wxBitmap& bitmap)
+{
+ // in Mac OS X the icon controls (which are used for borderless bitmap
+ // buttons) can have only one of the few standard sizes and if they
+ // don't, the OS rescales them automatically resulting in really ugly
+ // images, so centre the image in a square of standard size instead
+
+ // the supported sizes, sorted in decreasng order
+ static const int stdSizes[] = { 128, 48, 32, 16, 0 };
+
+ const int width = bitmap.GetWidth();
+ const int height = bitmap.GetHeight();
+
+ wxBitmap newBmp(bitmap);
+
+ int n;
+ for ( n = 0; n < (int)WXSIZEOF(stdSizes); n++ )
+ {
+ const int sizeStd = stdSizes[n];
+ if ( width > sizeStd || height > sizeStd )
+ {
+ // it will become -1 if the bitmap is larger than the biggest
+ // supported size, this is intentional
+ n--;
+
+ break;
+ }
+ }
+
+ if ( n != -1 )
+ {
+ const int sizeStd = stdSizes[n];
+ if ( width != sizeStd || height != sizeStd )
+ {
+ wxASSERT_MSG( width <= sizeStd && height <= sizeStd,
+ _T("bitmap shouldn't be cropped") );
+
+ wxImage square_image = bitmap.ConvertToImage();
+ newBmp = square_image.Size
+ (
+ wxSize(sizeStd, sizeStd),
+ wxPoint((sizeStd - width)/2, (sizeStd-height)/2)
+ );
+ }
+ }
+ //else: let the system rescale the bitmap
+
+ return newBmp;
+}
+
+//---------------------------------------------------------------------------
+
+bool wxBitmapButton::Create( wxWindow *parent,
+ wxWindowID id, const wxBitmap& bitmap,
+ const wxPoint& pos,
+ const wxSize& size,
+ long style,
+ const wxValidator& validator,
+ const wxString& name )
+{
+ m_macIsUserPane = false;
+
+ // since bitmapbuttonbase is subclass of button calling wxBitmapButtonBase::Create
+ // essentially creates an additional button
+ if ( !wxControl::Create( parent, id, pos, size, style, validator, name ) )
+ return false;
+
+ if ( style & wxBU_AUTODRAW )
+ {
+ m_marginX =
+ m_marginY = wxDEFAULT_BUTTON_MARGIN;
+ }
+ else
+ {
+ m_marginX =
+ m_marginY = 0;
+ }
+
+ OSStatus err = noErr;
+ ControlButtonContentInfo info;
+
+ Rect bounds = wxMacGetBoundsForControl( this, pos, size );
+ m_peer = new wxMacControl( this );
+
+ if ( bitmap.Ok() && HasFlag(wxBORDER_NONE) )
+ m_bmpNormal = wxMakeStdSizeBitmap(bitmap);
+ else
+ m_bmpNormal = bitmap;
+
+
+ if ( HasFlag( wxBORDER_NONE ) )
+ {
+ // contrary to the docs this control only works with iconrefs
+ wxMacCreateBitmapButton( &info, m_bmpNormal, kControlContentIconRef );
+ err = CreateIconControl(
+ MAC_WXHWND(parent->MacGetTopLevelWindowRef()),
+ &bounds, &info, false, m_peer->GetControlRefAddr() );
+ }
+ else
+ {
+ wxMacCreateBitmapButton( &info, m_bmpNormal );
+ err = CreateBevelButtonControl(
+ MAC_WXHWND(parent->MacGetTopLevelWindowRef()), &bounds, CFSTR(""),
+ ((style & wxBU_AUTODRAW) ? kControlBevelButtonSmallBevel : kControlBevelButtonNormalBevel ),
+ kControlBehaviorOffsetContents, &info, 0, 0, 0, m_peer->GetControlRefAddr() );
+ }
+
+ verify_noerr( err );
+
+ wxMacReleaseBitmapButton( &info );
+ wxASSERT_MSG( m_peer != NULL && m_peer->Ok(), wxT("No valid native Mac control") );
+
+ MacPostControlCreate( pos, size );
+
+ return true;
+}
+
+void wxBitmapButton::SetBitmapLabel( const wxBitmap& bitmap )
+{
+ if ( HasFlag( wxBORDER_NONE ) )
+ m_bmpNormal = wxMakeStdSizeBitmap(bitmap);
+ else
+ m_bmpNormal = bitmap;
+
+ InvalidateBestSize();
+
+ ControlButtonContentInfo info;
+
+ if ( HasFlag( wxBORDER_NONE ) )
+ {
+ wxMacCreateBitmapButton( &info, m_bmpNormal, kControlContentIconRef );
+ if ( info.contentType != kControlNoContent )
+ m_peer->SetData( kControlIconPart, kControlIconContentTag, info );
+ }
+ else
+ {
+ wxMacCreateBitmapButton( &info, m_bmpNormal );
+ if ( info.contentType != kControlNoContent )
+ m_peer->SetData( kControlButtonPart, kControlBevelButtonContentTag, info );
+ }
+
+ wxMacReleaseBitmapButton( &info );
+}
+
+wxSize wxBitmapButton::DoGetBestSize() const
+{
+ wxSize best;
+
+ best.x = 2 * m_marginX;
+ best.y = 2 * m_marginY;
+ if ( m_bmpNormal.Ok() )
+ {
+ best.x += m_bmpNormal.GetWidth();
+ best.y += m_bmpNormal.GetHeight();
+ }
+
+ return best;
+}
+
+#endif
diff --git a/src/osx/carbon/brush.cpp b/src/osx/carbon/brush.cpp
new file mode 100644
index 0000000000..84dd60d6e9
--- /dev/null
+++ b/src/osx/carbon/brush.cpp
@@ -0,0 +1,192 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/brush.cpp
+// Purpose: wxBrush
+// Author: Stefan Csomor
+// Modified by:
+// Created: 1998-01-01
+// RCS-ID: $Id$
+// Copyright: (c) Stefan Csomor
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/wxprec.h"
+
+#include "wx/brush.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/utils.h"
+#endif
+
+#include "wx/mac/private.h"
+
+IMPLEMENT_DYNAMIC_CLASS(wxBrush, wxGDIObject)
+
+class WXDLLEXPORT wxBrushRefData: public wxGDIRefData
+{
+public:
+ wxBrushRefData(const wxColour& colour = wxNullColour, wxBrushStyle style = wxBRUSHSTYLE_SOLID);
+ wxBrushRefData(const wxBitmap& stipple);
+ wxBrushRefData(const wxBrushRefData& data);
+ virtual ~wxBrushRefData();
+
+ bool operator==(const wxBrushRefData& data) const;
+
+ const wxColour& GetColour() const { return m_colour; }
+ wxBrushStyle GetStyle() const { return m_style; }
+ wxBitmap *GetStipple() { return &m_stipple; }
+
+ void SetColour(const wxColour& colour) { m_colour = colour; }
+ void SetStyle(wxBrushStyle style) { m_style = style; }
+ void SetStipple(const wxBitmap& stipple) { DoSetStipple(stipple); }
+
+protected:
+ void DoSetStipple(const wxBitmap& stipple);
+
+ wxBitmap m_stipple;
+ wxColour m_colour;
+ wxBrushStyle m_style;
+};
+
+#define M_BRUSHDATA ((wxBrushRefData *)m_refData)
+
+wxBrushRefData::wxBrushRefData(const wxColour& colour, wxBrushStyle style)
+ : m_colour(colour), m_style( style )
+{
+}
+
+wxBrushRefData::wxBrushRefData(const wxBitmap& stipple)
+{
+ DoSetStipple( stipple );
+}
+
+wxBrushRefData::wxBrushRefData(const wxBrushRefData& data)
+ : wxGDIRefData() ,
+ m_stipple(data.m_stipple),
+ m_colour(data.m_colour),
+ m_style(data.m_style)
+{
+}
+
+wxBrushRefData::~wxBrushRefData()
+{
+}
+
+bool wxBrushRefData::operator==(const wxBrushRefData& data) const
+{
+ return m_style == data.m_style &&
+ m_colour == data.m_colour &&
+ m_stipple.IsSameAs(data.m_stipple);
+}
+
+void wxBrushRefData::DoSetStipple(const wxBitmap& stipple)
+{
+ m_stipple = stipple;
+ m_style = stipple.GetMask() ? wxBRUSHSTYLE_STIPPLE_MASK_OPAQUE : wxBRUSHSTYLE_STIPPLE;
+}
+//
+//
+//
+
+wxBrush::wxBrush()
+{
+}
+
+wxBrush::~wxBrush()
+{
+}
+
+wxBrush::wxBrush(const wxColour& col, wxBrushStyle style)
+{
+ m_refData = new wxBrushRefData( col, style );
+}
+
+#if FUTURE_WXWIN_COMPATIBILITY_3_0
+wxBrush::wxBrush(const wxColour& col, int style)
+{
+ m_refData = new wxBrushRefData(col, (wxBrushStyle)style);
+}
+#endif
+
+wxBrush::wxBrush(const wxBitmap& stipple)
+{
+ m_refData = new wxBrushRefData( stipple );
+}
+
+// ----------------------------------------------------------------------------
+// wxBrush house keeping stuff
+// ----------------------------------------------------------------------------
+
+bool wxBrush::operator==(const wxBrush& brush) const
+{
+ const wxBrushRefData *brushData = (wxBrushRefData *)brush.m_refData;
+
+ // an invalid brush is considered to be only equal to another invalid brush
+ return m_refData ? (brushData && *M_BRUSHDATA == *brushData) : !brushData;
+}
+
+wxGDIRefData *wxBrush::CreateGDIRefData() const
+{
+ return new wxBrushRefData;
+}
+
+wxGDIRefData *wxBrush::CloneGDIRefData(const wxGDIRefData *data) const
+{
+ return new wxBrushRefData(*(const wxBrushRefData *)data);
+}
+
+// ----------------------------------------------------------------------------
+// wxBrush accessors
+// ----------------------------------------------------------------------------
+
+wxColour wxBrush::GetColour() const
+{
+ wxCHECK_MSG( Ok(), wxNullColour, _T("invalid brush") );
+
+ return M_BRUSHDATA->GetColour();
+}
+
+wxBrushStyle wxBrush::GetStyle() const
+{
+ wxCHECK_MSG( Ok(), wxBRUSHSTYLE_INVALID, _T("invalid brush") );
+
+ return M_BRUSHDATA->GetStyle();
+}
+
+wxBitmap *wxBrush::GetStipple() const
+{
+ wxCHECK_MSG( Ok(), NULL, _T("invalid brush") );
+
+ return M_BRUSHDATA->GetStipple();
+}
+
+// ----------------------------------------------------------------------------
+// wxBrush setters
+// ----------------------------------------------------------------------------
+
+void wxBrush::SetColour(const wxColour& col)
+{
+ AllocExclusive();
+
+ M_BRUSHDATA->SetColour(col);
+}
+
+void wxBrush::SetColour(unsigned char r, unsigned char g, unsigned char b)
+{
+ AllocExclusive();
+
+ M_BRUSHDATA->SetColour(wxColour(r, g, b));
+}
+
+void wxBrush::SetStyle(wxBrushStyle style)
+{
+ AllocExclusive();
+
+ M_BRUSHDATA->SetStyle(style);
+}
+
+void wxBrush::SetStipple(const wxBitmap& stipple)
+{
+ AllocExclusive();
+
+ M_BRUSHDATA->SetStipple(stipple);
+}
diff --git a/src/osx/carbon/button.cpp b/src/osx/carbon/button.cpp
new file mode 100644
index 0000000000..87fa56c82b
--- /dev/null
+++ b/src/osx/carbon/button.cpp
@@ -0,0 +1,273 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/button.cpp
+// Purpose: wxButton
+// Author: Stefan Csomor
+// Modified by:
+// Created: 1998-01-01
+// RCS-ID: $Id$
+// Copyright: (c) Stefan Csomor
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/wxprec.h"
+
+#include "wx/button.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/panel.h"
+ #include "wx/toplevel.h"
+ #include "wx/dcclient.h"
+#endif
+
+#include "wx/stockitem.h"
+
+#include "wx/mac/uma.h"
+
+IMPLEMENT_DYNAMIC_CLASS(wxButton, wxControl)
+
+
+bool wxButton::Create(wxWindow *parent,
+ wxWindowID id,
+ const wxString& lbl,
+ const wxPoint& pos,
+ const wxSize& size,
+ long style,
+ const wxValidator& validator,
+ const wxString& name)
+{
+ wxString label(lbl);
+ if (label.empty() && wxIsStockID(id))
+ label = wxGetStockLabel(id);
+
+ m_macIsUserPane = false ;
+
+ if ( !wxButtonBase::Create(parent, id, pos, size, style, validator, name) )
+ return false;
+
+ m_labelOrig = m_label = label ;
+
+ OSStatus err;
+ Rect bounds = wxMacGetBoundsForControl( this , pos , size ) ;
+ m_peer = new wxMacControl(this) ;
+ if ( id == wxID_HELP )
+ {
+ ControlButtonContentInfo info ;
+ info.contentType = kControlContentIconRef ;
+ GetIconRef(kOnSystemDisk, kSystemIconsCreator, kHelpIcon, &info.u.iconRef);
+ err = CreateRoundButtonControl(
+ MAC_WXHWND(parent->MacGetTopLevelWindowRef()),
+ &bounds, kControlRoundButtonNormalSize,
+ &info, m_peer->GetControlRefAddr() );
+ }
+ else if ( label.Find('\n' ) == wxNOT_FOUND && label.Find('\r' ) == wxNOT_FOUND)
+ {
+ // Button height is static in Mac, can't be changed, so we need to force it here
+ if ( GetWindowVariant() == wxWINDOW_VARIANT_NORMAL || GetWindowVariant() == wxWINDOW_VARIANT_LARGE )
+ {
+ bounds.bottom = bounds.top + 20 ;
+ m_maxHeight = 20 ;
+ }
+ else if ( GetWindowVariant() == wxWINDOW_VARIANT_SMALL )
+ {
+ bounds.bottom = bounds.top + 17 ;
+ m_maxHeight = 17 ;
+ }
+ else if ( GetWindowVariant() == wxWINDOW_VARIANT_MINI )
+ {
+ bounds.bottom = bounds.top + 15 ;
+ m_maxHeight = 15 ;
+ }
+ err = CreatePushButtonControl(
+ MAC_WXHWND(parent->MacGetTopLevelWindowRef()),
+ &bounds, CFSTR(""), m_peer->GetControlRefAddr() );
+ }
+ else
+ {
+ ControlButtonContentInfo info ;
+ info.contentType = kControlNoContent ;
+ err = CreateBevelButtonControl(
+ MAC_WXHWND(parent->MacGetTopLevelWindowRef()) , &bounds, CFSTR(""),
+ kControlBevelButtonLargeBevel, kControlBehaviorPushbutton,
+ &info, 0, 0, 0, m_peer->GetControlRefAddr() );
+ }
+
+ verify_noerr( err );
+ wxASSERT_MSG( m_peer != NULL && m_peer->Ok() , wxT("No valid Mac control") ) ;
+
+ MacPostControlCreate( pos, size );
+
+ return true;
+}
+
+wxWindow *wxButton::SetDefault()
+{
+ wxWindow *btnOldDefault = wxButtonBase::SetDefault();
+
+ if ( btnOldDefault )
+ {
+ // cast needed to access the protected member
+ btnOldDefault->GetPeer()->SetData(kControlButtonPart , kControlPushButtonDefaultTag , (Boolean) 0 ) ;
+ }
+
+ m_peer->SetData(kControlButtonPart , kControlPushButtonDefaultTag , (Boolean) 1 ) ;
+
+ return btnOldDefault;
+}
+
+wxSize wxButton::DoGetBestSize() const
+{
+ if ( GetId() == wxID_HELP )
+ return wxSize( 20 , 20 ) ;
+
+ wxSize sz = GetDefaultSize() ;
+
+ switch (GetWindowVariant())
+ {
+ case wxWINDOW_VARIANT_NORMAL:
+ case wxWINDOW_VARIANT_LARGE:
+ sz.y = 20 ;
+ break;
+
+ case wxWINDOW_VARIANT_SMALL:
+ sz.y = 17 ;
+ break;
+
+ case wxWINDOW_VARIANT_MINI:
+ sz.y = 15 ;
+ break;
+
+ default:
+ break;
+ }
+
+ Rect bestsize = { 0 , 0 , 0 , 0 } ;
+ m_peer->GetBestRect( &bestsize ) ;
+
+ int wBtn;
+ if ( EmptyRect( &bestsize ) || ( GetWindowStyle() & wxBU_EXACTFIT) )
+ {
+ Point bounds;
+
+ ControlFontStyleRec controlFont;
+ OSStatus err = m_peer->GetData( kControlEntireControl, kControlFontStyleTag, &controlFont );
+ verify_noerr( err );
+
+ wxCFStringRef str( m_label, GetFont().GetEncoding() );
+
+#if wxMAC_USE_ATSU_TEXT
+ SInt16 baseline;
+ if ( m_font.MacGetThemeFontID() != kThemeCurrentPortFont )
+ {
+ err = GetThemeTextDimensions(
+ (!m_label.empty() ? (CFStringRef)str : CFSTR(" ")),
+ m_font.MacGetThemeFontID(), kThemeStateActive, false, &bounds, &baseline );
+ verify_noerr( err );
+ }
+ else
+#endif
+ {
+ wxClientDC dc(const_cast(this));
+ wxCoord width, height ;
+ dc.GetTextExtent( m_label , &width, &height);
+ bounds.h = width;
+ bounds.v = height;
+ }
+
+ wBtn = bounds.h + sz.y;
+ }
+ else
+ {
+ wBtn = bestsize.right - bestsize.left ;
+ // non 'normal' window variants don't return the correct height
+ // sz.y = bestsize.bottom - bestsize.top ;
+ }
+
+ if ((wBtn > sz.x) || ( GetWindowStyle() & wxBU_EXACTFIT))
+ sz.x = wBtn;
+
+ return sz ;
+}
+
+wxSize wxButton::GetDefaultSize()
+{
+ int wBtn = 70 ;
+ int hBtn = 20 ;
+
+ return wxSize(wBtn, hBtn);
+}
+
+void wxButton::Command (wxCommandEvent & event)
+{
+ m_peer->Flash(kControlButtonPart) ;
+ ProcessCommand(event);
+}
+
+wxInt32 wxButton::MacControlHit(WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) )
+{
+ wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, m_windowId);
+ event.SetEventObject(this);
+ ProcessCommand(event);
+
+ return noErr;
+}
+
+//-------------------------------------------------------
+// wxDisclosureTriangle
+//-------------------------------------------------------
+
+bool wxDisclosureTriangle::Create(wxWindow *parent, wxWindowID id, const wxString& label,
+ const wxPoint& pos, const wxSize& size, long style,const wxValidator& validator, const wxString& name )
+{
+ m_macIsUserPane = false ;
+
+ if ( !wxControl::Create(parent, id, pos, size, style, validator, name) )
+ return false;
+
+ Rect bounds = wxMacGetBoundsForControl( this , pos , size ) ;
+ m_peer = new wxMacControl(this) ;
+
+ OSStatus err = CreateDisclosureTriangleControl(
+ MAC_WXHWND(parent->MacGetTopLevelWindowRef()) , &bounds,
+ kControlDisclosureTrianglePointDefault,
+ wxCFStringRef( label ),
+ 0, // closed
+ TRUE, // draw title
+ TRUE, // auto toggle back and forth
+ m_peer->GetControlRefAddr() );
+
+ verify_noerr( err );
+ wxASSERT_MSG( m_peer != NULL && m_peer->Ok() , wxT("No valid Mac control") ) ;
+
+ MacPostControlCreate( pos, size );
+ // passing the text in the param doesn't seem to work, so lets do if again
+ SetLabel( label );
+
+ return true;
+}
+
+void wxDisclosureTriangle::SetOpen( bool open )
+{
+ m_peer->SetValue( open ? 1 : 0 );
+}
+
+bool wxDisclosureTriangle::IsOpen() const
+{
+ return m_peer->GetValue() == 1;
+}
+
+wxInt32 wxDisclosureTriangle::MacControlHit( WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) )
+{
+ // Just emit button event for now
+ wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, m_windowId);
+ event.SetEventObject(this);
+ ProcessCommand(event);
+
+ return noErr;
+}
+
+wxSize wxDisclosureTriangle::DoGetBestSize() const
+{
+ return wxSize(16,16);
+}
+
+
diff --git a/src/osx/carbon/carbrsrc.r b/src/osx/carbon/carbrsrc.r
new file mode 100644
index 0000000000..9326cc3b56
--- /dev/null
+++ b/src/osx/carbon/carbrsrc.r
@@ -0,0 +1,7 @@
+// carbon for 9
+data 'carb' (0) {
+ $"0000" /* .. */
+};
+
+// the plist resource should only be included in the application
+// since it contains the bundle information and should not be duplicated
diff --git a/src/osx/carbon/cfsocket.cpp b/src/osx/carbon/cfsocket.cpp
new file mode 100644
index 0000000000..8a2383c7f5
--- /dev/null
+++ b/src/osx/carbon/cfsocket.cpp
@@ -0,0 +1,2311 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/cfsocket.cpp
+// Purpose: Socket handler classes
+// Authors: Guilhem Lavaux, Guillermo Rodriguez Garcia
+// Created: April 1997
+// Copyright: (C) 1999-1997, Guilhem Lavaux
+// (C) 2000-1999, Guillermo Rodriguez Garcia
+// RCS_ID: $Id$
+// License: see wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+
+#if wxUSE_SOCKETS
+
+#include "wx/socket.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/object.h"
+ #include "wx/string.h"
+ #include "wx/intl.h"
+ #include "wx/log.h"
+ #include "wx/event.h"
+ #include "wx/app.h"
+ #include "wx/utils.h"
+ #include "wx/timer.h"
+ #include "wx/module.h"
+#endif
+
+#include "wx/apptrait.h"
+
+#include "wx/sckaddr.h"
+#include "wx/mac/carbon/private.h"
+
+#include
+#include
+#include
+#include
+
+#define HAVE_INET_ATON
+
+// DLL options compatibility check:
+#include "wx/build.h"
+
+WX_CHECK_BUILD_OPTIONS("wxNet")
+
+
+// discard buffer
+#define MAX_DISCARD_SIZE (10 * 1024)
+
+#ifndef INVALID_SOCKET
+#define INVALID_SOCKET -1
+#endif
+
+// what to do within waits: we have 2 cases: from the main thread itself we
+// have to call wxYield() to let the events (including the GUI events and the
+// low-level (not wxWidgets) events from GSocket) be processed. From another
+// thread it is enough to just call wxThread::Yield() which will give away the
+// rest of our time slice: the explanation is that the events will be processed
+// by the main thread anyhow, without calling wxYield(), but we don't want to
+// eat the CPU time uselessly while sitting in the loop waiting for the data
+#if wxUSE_THREADS
+ #define PROCESS_EVENTS() \
+ { \
+ if ( wxThread::IsMain() ) \
+ wxYield(); \
+ else \
+ wxThread::Yield(); \
+ }
+#else // !wxUSE_THREADS
+ #define PROCESS_EVENTS() wxYield()
+#endif // wxUSE_THREADS/!wxUSE_THREADS
+
+#define wxTRACE_Socket _T("wxSocket")
+
+
+IMPLEMENT_CLASS(wxSocketBase, wxObject)
+IMPLEMENT_CLASS(wxSocketServer, wxSocketBase)
+IMPLEMENT_CLASS(wxSocketClient, wxSocketBase)
+IMPLEMENT_CLASS(wxDatagramSocket, wxSocketBase)
+IMPLEMENT_DYNAMIC_CLASS(wxSocketEvent, wxEvent)
+
+// --------------------------------------------------------------------------
+// private classes
+// --------------------------------------------------------------------------
+
+class wxSocketState : public wxObject
+{
+public:
+ wxSocketFlags m_flags;
+ wxSocketEventFlags m_eventmask;
+ bool m_notify;
+ void *m_clientData;
+
+public:
+ wxSocketState() : wxObject() {}
+
+ DECLARE_NO_COPY_CLASS(wxSocketState)
+};
+
+struct _GSocket
+{
+ CFSocketNativeHandle m_fd;
+ GAddress *m_local;
+ GAddress *m_peer;
+ GSocketError m_error;
+
+ int m_non_blocking;
+ int m_server;
+ int m_stream;
+ int m_oriented;
+ int m_establishing;
+ unsigned long m_timeout;
+
+ // Callbacks
+ GSocketEventFlags m_detected;
+ GSocketCallback m_cbacks[GSOCK_MAX_EVENT];
+ char *m_data[GSOCK_MAX_EVENT];
+
+ CFSocketRef m_cfSocket;
+ CFRunLoopSourceRef m_runLoopSource;
+ CFReadStreamRef m_readStream ;
+ CFWriteStreamRef m_writeStream ;
+};
+
+struct _GAddress
+{
+ struct sockaddr *m_addr;
+ size_t m_len;
+
+ GAddressType m_family;
+ int m_realfamily;
+
+ GSocketError m_error;
+ int somethingElse ;
+};
+
+void wxMacCFSocketCallback(CFSocketRef s, CFSocketCallBackType callbackType,
+ CFDataRef address, const void* data, void* info) ;
+void _GSocket_Enable(GSocket *socket, GSocketEvent event) ;
+void _GSocket_Disable(GSocket *socket, GSocketEvent event) ;
+
+// ==========================================================================
+// wxSocketBase
+// ==========================================================================
+
+// --------------------------------------------------------------------------
+// Initialization and shutdown
+// --------------------------------------------------------------------------
+
+// FIXME-MT: all this is MT-unsafe, of course, we should protect all accesses
+// to m_countInit with a crit section
+size_t wxSocketBase::m_countInit = 0;
+
+bool wxSocketBase::IsInitialized()
+{
+ return m_countInit > 0;
+}
+
+bool wxSocketBase::Initialize()
+{
+ if ( !m_countInit++ )
+ {
+#if 0
+ wxAppTraits *traits = wxAppConsole::GetInstance() ?
+ wxAppConsole::GetInstance()->GetTraits() : NULL;
+ GSocketGUIFunctionsTable *functions =
+ traits ? traits->GetSocketGUIFunctionsTable() : NULL;
+ GSocket_SetGUIFunctions(functions);
+
+ if ( !GSocket_Init() )
+ {
+ m_countInit--;
+
+ return false;
+ }
+#endif
+ }
+
+ return true;
+}
+
+void wxSocketBase::Shutdown()
+{
+ // we should be initialized
+ wxASSERT_MSG( m_countInit, wxT("extra call to Shutdown()") );
+ if ( !--m_countInit )
+ {
+#if 0
+ GSocket_Cleanup();
+#endif
+ }
+}
+
+// --------------------------------------------------------------------------
+// Ctor and dtor
+// --------------------------------------------------------------------------
+
+void wxSocketBase::Init()
+{
+ m_socket = NULL;
+ m_type = wxSOCKET_UNINIT;
+
+ // state
+ m_flags = 0;
+ m_connected =
+ m_establishing =
+ m_reading =
+ m_writing =
+ m_error = false;
+ m_lcount = 0;
+ m_timeout = 600;
+ m_beingDeleted = false;
+
+ // pushback buffer
+ m_unread = NULL;
+ m_unrd_size = 0;
+ m_unrd_cur = 0;
+
+ // events
+ m_id = -1;
+ m_handler = NULL;
+ m_clientData = NULL;
+ m_notify = false;
+ m_eventmask = 0;
+
+ if ( !IsInitialized() )
+ {
+ // this Initialize() will be undone by wxSocketModule::OnExit(), all the
+ // other calls to it should be matched by a call to Shutdown()
+ Initialize();
+ }
+}
+
+wxSocketBase::wxSocketBase()
+{
+ Init();
+}
+
+wxSocketBase::wxSocketBase( wxSocketFlags flags, wxSocketType type)
+{
+ Init();
+
+ m_flags = flags;
+ m_type = type;
+}
+
+wxSocketBase::~wxSocketBase()
+{
+ // Just in case the app called Destroy() *and* then deleted
+ // the socket immediately: don't leave dangling pointers.
+ wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL;
+ if ( traits )
+ traits->RemoveFromPendingDelete(this);
+
+ // Shutdown and close the socket
+ if (!m_beingDeleted)
+ Close();
+
+ // Destroy the GSocket object
+ if (m_socket)
+ {
+ GSocket_destroy(m_socket);
+ }
+
+ // Free the pushback buffer
+ if (m_unread)
+ free(m_unread);
+}
+
+bool wxSocketBase::Destroy()
+{
+ // Delayed destruction: the socket will be deleted during the next
+ // idle loop iteration. This ensures that all pending events have
+ // been processed.
+ m_beingDeleted = true;
+
+ // Shutdown and close the socket
+ Close();
+
+ // Supress events from now on
+ Notify(false);
+
+ // schedule this object for deletion
+ wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL;
+ if ( traits )
+ {
+ // let the traits object decide what to do with us
+ traits->ScheduleForDestroy(this);
+ }
+ else // no app or no traits
+ {
+ // in wxBase we might have no app object at all, don't leak memory
+ delete this;
+ }
+
+ return true;
+}
+
+// --------------------------------------------------------------------------
+// Basic IO calls
+// --------------------------------------------------------------------------
+
+// The following IO operations update m_error and m_lcount:
+// {Read, Write, ReadMsg, WriteMsg, Peek, Unread, Discard}
+//
+// TODO: Should Connect, Accept and AcceptWith update m_error?
+
+bool wxSocketBase::Close()
+{
+ // Interrupt pending waits
+ InterruptWait();
+
+ if (m_socket)
+ GSocket_Shutdown(m_socket);
+
+ m_connected = false;
+ m_establishing = false;
+
+ return true;
+}
+
+wxSocketBase& wxSocketBase::Read(void* buffer, wxUint32 nbytes)
+{
+ // Mask read events
+ m_reading = true;
+
+ m_lcount = _Read(buffer, nbytes);
+
+ // If in wxSOCKET_WAITALL mode, all bytes should have been read.
+ if (m_flags & wxSOCKET_WAITALL)
+ m_error = (m_lcount != nbytes);
+ else
+ m_error = (m_lcount == 0);
+
+ // Allow read events from now on
+ m_reading = false;
+
+ return *this;
+}
+
+wxUint32 wxSocketBase::_Read(void* buffer, wxUint32 nbytes)
+{
+ int total = 0;
+
+ // Try the pushback buffer first
+ total = GetPushback(buffer, nbytes, false);
+ nbytes -= total;
+ buffer = (char *)buffer + total;
+
+ // Return now in one of the following cases:
+ // - the socket is invalid,
+ // - we got all the data,
+ // - we got *some* data and we are not using wxSOCKET_WAITALL.
+ if ( !m_socket ||
+ !nbytes ||
+ ((total != 0) && !(m_flags & wxSOCKET_WAITALL)) )
+ return total;
+
+ // Possible combinations (they are checked in this order)
+ // wxSOCKET_NOWAIT
+ // wxSOCKET_WAITALL (with or without wxSOCKET_BLOCK)
+ // wxSOCKET_BLOCK
+ // wxSOCKET_NONE
+ //
+
+ int ret;
+ if (m_flags & wxSOCKET_NOWAIT)
+ {
+ GSocket_SetNonBlocking(m_socket, 1);
+ ret = GSocket_Read(m_socket, (char *)buffer, nbytes);
+ GSocket_SetNonBlocking(m_socket, 0);
+
+ if (ret > 0)
+ total += ret;
+ }
+ else
+ {
+ bool more = true;
+
+ while (more)
+ {
+ if ( !(m_flags & wxSOCKET_BLOCK) && !WaitForRead() )
+ break;
+
+ ret = GSocket_Read(m_socket, (char *)buffer, nbytes);
+
+ if (ret > 0)
+ {
+ total += ret;
+ nbytes -= ret;
+ buffer = (char *)buffer + ret;
+ }
+
+ // If we got here and wxSOCKET_WAITALL is not set, we can leave
+ // now. Otherwise, wait until we recv all the data or until there
+ // is an error.
+ //
+ more = (ret > 0 && nbytes > 0 && (m_flags & wxSOCKET_WAITALL));
+ }
+ }
+
+ return total;
+}
+
+wxSocketBase& wxSocketBase::ReadMsg(void* buffer, wxUint32 nbytes)
+{
+ wxUint32 len, len2, sig, total;
+ bool error;
+ int old_flags;
+ struct
+ {
+ unsigned char sig[4];
+ unsigned char len[4];
+ }
+ msg;
+
+ // Mask read events
+ m_reading = true;
+
+ total = 0;
+ error = true;
+ old_flags = m_flags;
+ SetFlags((m_flags & wxSOCKET_BLOCK) | wxSOCKET_WAITALL);
+
+ if (_Read(&msg, sizeof(msg)) != sizeof(msg))
+ goto exit;
+
+ sig = (wxUint32)msg.sig[0];
+ sig |= (wxUint32)(msg.sig[1] << 8);
+ sig |= (wxUint32)(msg.sig[2] << 16);
+ sig |= (wxUint32)(msg.sig[3] << 24);
+
+ if (sig != 0xfeeddead)
+ {
+ wxLogWarning( wxT("wxSocket: invalid signature in ReadMsg.") );
+ goto exit;
+ }
+
+ len = (wxUint32)msg.len[0];
+ len |= (wxUint32)(msg.len[1] << 8);
+ len |= (wxUint32)(msg.len[2] << 16);
+ len |= (wxUint32)(msg.len[3] << 24);
+
+ if (len > nbytes)
+ {
+ len2 = len - nbytes;
+ len = nbytes;
+ }
+ else
+ len2 = 0;
+
+ // Don't attemp to read if the msg was zero bytes long.
+ if (len)
+ {
+ total = _Read(buffer, len);
+
+ if (total != len)
+ goto exit;
+ }
+ if (len2)
+ {
+ char *discard_buffer = new char[MAX_DISCARD_SIZE];
+ long discard_len;
+
+ // NOTE: discarded bytes don't add to m_lcount.
+ do
+ {
+ discard_len = ((len2 > MAX_DISCARD_SIZE)? MAX_DISCARD_SIZE : len2);
+ discard_len = _Read(discard_buffer, (wxUint32)discard_len);
+ len2 -= (wxUint32)discard_len;
+ }
+ while ((discard_len > 0) && len2);
+
+ delete [] discard_buffer;
+
+ if (len2 != 0)
+ goto exit;
+ }
+ if (_Read(&msg, sizeof(msg)) != sizeof(msg))
+ goto exit;
+
+ sig = (wxUint32)msg.sig[0];
+ sig |= (wxUint32)(msg.sig[1] << 8);
+ sig |= (wxUint32)(msg.sig[2] << 16);
+ sig |= (wxUint32)(msg.sig[3] << 24);
+
+ if (sig != 0xdeadfeed)
+ {
+ wxLogWarning( wxT("wxSocket: invalid signature in ReadMsg.") );
+ goto exit;
+ }
+
+ // everything was OK
+ error = false;
+
+exit:
+ m_error = error;
+ m_lcount = total;
+ m_reading = false;
+ SetFlags(old_flags);
+
+ return *this;
+}
+
+wxSocketBase& wxSocketBase::Peek(void* buffer, wxUint32 nbytes)
+{
+ // Mask read events
+ m_reading = true;
+
+ m_lcount = _Read(buffer, nbytes);
+ Pushback(buffer, m_lcount);
+
+ // If in wxSOCKET_WAITALL mode, all bytes should have been read.
+ if (m_flags & wxSOCKET_WAITALL)
+ m_error = (m_lcount != nbytes);
+ else
+ m_error = (m_lcount == 0);
+
+ // Allow read events again
+ m_reading = false;
+
+ return *this;
+}
+
+wxSocketBase& wxSocketBase::Write(const void *buffer, wxUint32 nbytes)
+{
+ // Mask write events
+ m_writing = true;
+
+ m_lcount = _Write(buffer, nbytes);
+
+ // If in wxSOCKET_WAITALL mode, all bytes should have been written.
+ if (m_flags & wxSOCKET_WAITALL)
+ m_error = (m_lcount != nbytes);
+ else
+ m_error = (m_lcount == 0);
+
+ // Allow write events again
+ m_writing = false;
+
+ return *this;
+}
+
+wxUint32 wxSocketBase::_Write(const void *buffer, wxUint32 nbytes)
+{
+ wxUint32 total = 0;
+
+ // If the socket is invalid or parameters are ill, return immediately
+ if (!m_socket || !buffer || !nbytes)
+ return 0;
+
+ // Possible combinations (they are checked in this order)
+ // wxSOCKET_NOWAIT
+ // wxSOCKET_WAITALL (with or without wxSOCKET_BLOCK)
+ // wxSOCKET_BLOCK
+ // wxSOCKET_NONE
+ //
+ int ret;
+ if (m_flags & wxSOCKET_NOWAIT)
+ {
+ GSocket_SetNonBlocking(m_socket, 1);
+ ret = GSocket_Write(m_socket, (const char *)buffer, nbytes);
+ GSocket_SetNonBlocking(m_socket, 0);
+
+ if (ret > 0)
+ total = ret;
+ }
+ else
+ {
+ bool more = true;
+
+ while (more)
+ {
+ if ( !(m_flags & wxSOCKET_BLOCK) && !WaitForWrite() )
+ break;
+
+ ret = GSocket_Write(m_socket, (const char *)buffer, nbytes);
+
+ if (ret > 0)
+ {
+ total += ret;
+ nbytes -= ret;
+ buffer = (const char *)buffer + ret;
+ }
+
+ // If we got here and wxSOCKET_WAITALL is not set, we can leave
+ // now. Otherwise, wait until we send all the data or until there
+ // is an error.
+ //
+ more = (ret > 0 && nbytes > 0 && (m_flags & wxSOCKET_WAITALL));
+ }
+ }
+
+ return total;
+}
+
+wxSocketBase& wxSocketBase::WriteMsg(const void *buffer, wxUint32 nbytes)
+{
+ wxUint32 total;
+ bool error;
+ struct
+ {
+ unsigned char sig[4];
+ unsigned char len[4];
+ }
+ msg;
+
+ // Mask write events
+ m_writing = true;
+
+ error = true;
+ total = 0;
+ SetFlags((m_flags & wxSOCKET_BLOCK) | wxSOCKET_WAITALL);
+
+ msg.sig[0] = (unsigned char) 0xad;
+ msg.sig[1] = (unsigned char) 0xde;
+ msg.sig[2] = (unsigned char) 0xed;
+ msg.sig[3] = (unsigned char) 0xfe;
+
+ msg.len[0] = (unsigned char) (nbytes & 0xff);
+ msg.len[1] = (unsigned char) ((nbytes >> 8) & 0xff);
+ msg.len[2] = (unsigned char) ((nbytes >> 16) & 0xff);
+ msg.len[3] = (unsigned char) ((nbytes >> 24) & 0xff);
+
+ if (_Write(&msg, sizeof(msg)) < sizeof(msg))
+ goto exit;
+
+ total = _Write(buffer, nbytes);
+
+ if (total < nbytes)
+ goto exit;
+
+ msg.sig[0] = (unsigned char) 0xed;
+ msg.sig[1] = (unsigned char) 0xfe;
+ msg.sig[2] = (unsigned char) 0xad;
+ msg.sig[3] = (unsigned char) 0xde;
+ msg.len[0] = msg.len[1] = msg.len[2] = msg.len[3] = (char) 0;
+
+ if ((_Write(&msg, sizeof(msg))) < sizeof(msg))
+ goto exit;
+
+ // everything was OK
+ error = false;
+
+exit:
+ m_error = error;
+ m_lcount = total;
+ m_writing = false;
+
+ return *this;
+}
+
+wxSocketBase& wxSocketBase::Unread(const void *buffer, wxUint32 nbytes)
+{
+ if (nbytes != 0)
+ Pushback(buffer, nbytes);
+
+ m_error = false;
+ m_lcount = nbytes;
+
+ return *this;
+}
+
+wxSocketBase& wxSocketBase::Discard()
+{
+ char *buffer = new char[MAX_DISCARD_SIZE];
+ wxUint32 ret;
+ wxUint32 total = 0;
+
+ // Mask read events
+ m_reading = true;
+
+ SetFlags(wxSOCKET_NOWAIT);
+
+ do
+ {
+ ret = _Read(buffer, MAX_DISCARD_SIZE);
+ total += ret;
+ }
+ while (ret == MAX_DISCARD_SIZE);
+
+ delete[] buffer;
+ m_lcount = total;
+ m_error = false;
+
+ // Allow read events again
+ m_reading = false;
+
+ return *this;
+}
+
+// --------------------------------------------------------------------------
+// Wait functions
+// --------------------------------------------------------------------------
+
+// All Wait functions poll the socket using GSocket_Select() to
+// check for the specified combination of conditions, until one
+// of these conditions become true, an error occurs, or the
+// timeout elapses. The polling loop calls PROCESS_EVENTS(), so
+// this won't block the GUI.
+
+bool wxSocketBase::_Wait(long seconds,
+ long milliseconds,
+ wxSocketEventFlags flags)
+{
+ GSocketEventFlags result;
+ long timeout;
+
+ // Set this to true to interrupt ongoing waits
+ m_interrupt = false;
+
+ // Check for valid socket
+ if (!m_socket)
+ return false;
+
+ // Check for valid timeout value.
+ if (seconds != -1)
+ timeout = seconds * 1000 + milliseconds;
+ else
+ timeout = m_timeout * 1000;
+
+#if !defined(wxUSE_GUI) || !wxUSE_GUI
+ GSocket_SetTimeout(m_socket, timeout);
+#endif
+
+ // Wait in an active polling loop.
+ //
+ // NOTE: We duplicate some of the code in OnRequest, but this doesn't
+ // hurt. It has to be here because the (GSocket) event might arrive
+ // a bit delayed, and it has to be in OnRequest as well because we
+ // don't know whether the Wait functions are being used.
+ //
+ // Do this at least once (important if timeout == 0, when
+ // we are just polling). Also, if just polling, do not yield.
+
+ wxStopWatch chrono;
+ bool done = false;
+
+ while (!done)
+ {
+ result = GSocket_Select(m_socket, flags | GSOCK_LOST_FLAG);
+
+ // Incoming connection (server) or connection established (client)
+ if (result & GSOCK_CONNECTION_FLAG)
+ {
+ m_connected = true;
+ m_establishing = false;
+
+ return true;
+ }
+
+ // Data available or output buffer ready
+ if ((result & GSOCK_INPUT_FLAG) || (result & GSOCK_OUTPUT_FLAG))
+ {
+ return true;
+ }
+
+ // Connection lost
+ if (result & GSOCK_LOST_FLAG)
+ {
+ m_connected = false;
+ m_establishing = false;
+
+ return (flags & GSOCK_LOST_FLAG) != 0;
+ }
+
+ // Wait more?
+ if ((!timeout) || (chrono.Time() > timeout) || (m_interrupt))
+ done = true;
+ else
+ PROCESS_EVENTS();
+ }
+
+ return false;
+}
+
+bool wxSocketBase::Wait(long seconds, long milliseconds)
+{
+ return _Wait(seconds, milliseconds, GSOCK_INPUT_FLAG |
+ GSOCK_OUTPUT_FLAG |
+ GSOCK_CONNECTION_FLAG |
+ GSOCK_LOST_FLAG);
+}
+
+bool wxSocketBase::WaitForRead(long seconds, long milliseconds)
+{
+ // Check pushback buffer before entering _Wait
+ if (m_unread)
+ return true;
+
+ // Note that GSOCK_INPUT_LOST has to be explicitly passed to
+ // _Wait becuase of the semantics of WaitForRead: a return
+ // value of true means that a GSocket_Read call will return
+ // immediately, not that there is actually data to read.
+
+ return _Wait(seconds, milliseconds, GSOCK_INPUT_FLAG | GSOCK_LOST_FLAG);
+}
+
+bool wxSocketBase::WaitForWrite(long seconds, long milliseconds)
+{
+ return _Wait(seconds, milliseconds, GSOCK_OUTPUT_FLAG);
+}
+
+bool wxSocketBase::WaitForLost(long seconds, long milliseconds)
+{
+ return _Wait(seconds, milliseconds, GSOCK_LOST_FLAG);
+}
+
+// --------------------------------------------------------------------------
+// Miscellaneous
+// --------------------------------------------------------------------------
+
+//
+// Get local or peer address
+//
+
+bool wxSocketBase::GetPeer(wxSockAddress& addr_man) const
+{
+ GAddress *peer;
+
+ if (!m_socket)
+ return false;
+
+ peer = GSocket_GetPeer(m_socket);
+
+ // copying a null address would just trigger an assert anyway
+
+ if (!peer)
+ return false;
+
+ addr_man.SetAddress(peer);
+ GAddress_destroy(peer);
+
+ return true;
+}
+
+bool wxSocketBase::GetLocal(wxSockAddress& addr_man) const
+{
+#if 0
+ GAddress *local;
+
+ if (!m_socket)
+ return false;
+
+ local = GSocket_GetLocal(m_socket);
+ addr_man.SetAddress(local);
+ GAddress_destroy(local);
+#endif
+
+ return true;
+}
+
+//
+// Save and restore socket state
+//
+
+void wxSocketBase::SaveState()
+{
+ wxSocketState *state;
+
+ state = new wxSocketState();
+
+ state->m_flags = m_flags;
+ state->m_notify = m_notify;
+ state->m_eventmask = m_eventmask;
+ state->m_clientData = m_clientData;
+
+ m_states.Append(state);
+}
+
+void wxSocketBase::RestoreState()
+{
+ wxList::compatibility_iterator node;
+ wxSocketState *state;
+
+ node = m_states.GetLast();
+ if (!node)
+ return;
+
+ state = (wxSocketState *)node->GetData();
+
+ m_flags = state->m_flags;
+ m_notify = state->m_notify;
+ m_eventmask = state->m_eventmask;
+ m_clientData = state->m_clientData;
+
+ m_states.Erase(node);
+ delete state;
+}
+
+//
+// Timeout and flags
+//
+
+void wxSocketBase::SetTimeout(long seconds)
+{
+ m_timeout = seconds;
+
+#if 0
+ if (m_socket)
+ GSocket_SetTimeout(m_socket, m_timeout * 1000);
+#endif
+}
+
+void wxSocketBase::SetFlags(wxSocketFlags flags)
+{
+ m_flags = flags;
+}
+
+
+// --------------------------------------------------------------------------
+// Event handling
+// --------------------------------------------------------------------------
+
+// A note on how events are processed, which is probably the most
+// difficult thing to get working right while keeping the same API
+// and functionality for all platforms.
+//
+// When GSocket detects an event, it calls wx_socket_callback, which in
+// turn just calls wxSocketBase::OnRequest in the corresponding wxSocket
+// object. OnRequest does some housekeeping, and if the event is to be
+// propagated to the user, it creates a new wxSocketEvent object and
+// posts it. The event is not processed immediately, but delayed with
+// AddPendingEvent instead. This is necessary in order to decouple the
+// event processing from wx_socket_callback; otherwise, subsequent IO
+// calls made from the user event handler would fail, as gtk callbacks
+// are not reentrant.
+//
+// Note that, unlike events, user callbacks (now deprecated) are _not_
+// decoupled from wx_socket_callback and thus they suffer from a variety
+// of problems. Avoid them where possible and use events instead.
+
+extern "C"
+void LINKAGEMODE wx_socket_callback(GSocket * WXUNUSED(socket),
+ GSocketEvent notification,
+ char *cdata)
+{
+ wxSocketBase *sckobj = (wxSocketBase *)cdata;
+
+ sckobj->OnRequest((wxSocketNotify) notification);
+}
+
+void wxSocketBase::OnRequest(wxSocketNotify notification)
+{
+ // NOTE: We duplicate some of the code in _Wait, but this doesn't
+ // hurt. It has to be here because the (GSocket) event might arrive
+ // a bit delayed, and it has to be in _Wait as well because we don't
+ // know whether the Wait functions are being used.
+
+ switch (notification)
+ {
+ case wxSOCKET_CONNECTION:
+ m_establishing = false;
+ m_connected = true;
+ break;
+
+ // If we are in the middle of a R/W operation, do not
+ // propagate events to users. Also, filter 'late' events
+ // which are no longer valid.
+
+ case wxSOCKET_INPUT:
+ if (m_reading || !GSocket_Select(m_socket, GSOCK_INPUT_FLAG))
+ return;
+ break;
+
+ case wxSOCKET_OUTPUT:
+ if (m_writing || !GSocket_Select(m_socket, GSOCK_OUTPUT_FLAG))
+ return;
+ break;
+
+ case wxSOCKET_LOST:
+ m_connected = false;
+ m_establishing = false;
+ break;
+
+ default:
+ break;
+ }
+
+ // Schedule the event
+
+ wxSocketEventFlags flag = 0;
+ wxUnusedVar(flag);
+ switch (notification)
+ {
+ case GSOCK_INPUT:
+ flag = GSOCK_INPUT_FLAG;
+ break;
+
+ case GSOCK_OUTPUT:
+ flag = GSOCK_OUTPUT_FLAG;
+ break;
+
+ case GSOCK_CONNECTION:
+ flag = GSOCK_CONNECTION_FLAG;
+ break;
+
+ case GSOCK_LOST:
+ flag = GSOCK_LOST_FLAG;
+ break;
+
+ default:
+ wxLogWarning( wxT("wxSocket: unknown event!") );
+ return;
+ }
+
+ if (((m_eventmask & flag) == flag) && m_notify)
+ {
+ if (m_handler)
+ {
+ wxSocketEvent event(m_id);
+ event.m_event = notification;
+ event.m_clientData = m_clientData;
+ event.SetEventObject(this);
+
+ m_handler->AddPendingEvent(event);
+ }
+ }
+}
+
+void wxSocketBase::Notify(bool notify)
+{
+ m_notify = notify;
+}
+
+void wxSocketBase::SetNotify(wxSocketEventFlags flags)
+{
+ m_eventmask = flags;
+}
+
+void wxSocketBase::SetEventHandler(wxEvtHandler& handler, int id)
+{
+ m_handler = &handler;
+ m_id = id;
+}
+
+// --------------------------------------------------------------------------
+// Pushback buffer
+// --------------------------------------------------------------------------
+
+void wxSocketBase::Pushback(const void *buffer, wxUint32 size)
+{
+ if (!size)
+ return;
+
+ if (m_unread == NULL)
+ m_unread = malloc(size);
+ else
+ {
+ void *tmp;
+
+ tmp = malloc(m_unrd_size + size);
+ memcpy((char *)tmp + size, m_unread, m_unrd_size);
+ free(m_unread);
+
+ m_unread = tmp;
+ }
+
+ m_unrd_size += size;
+
+ memcpy(m_unread, buffer, size);
+}
+
+wxUint32 wxSocketBase::GetPushback(void *buffer, wxUint32 size, bool peek)
+{
+ if (!m_unrd_size)
+ return 0;
+
+ if (size > (m_unrd_size-m_unrd_cur))
+ size = m_unrd_size-m_unrd_cur;
+
+ memcpy(buffer, (char *)m_unread + m_unrd_cur, size);
+
+ if (!peek)
+ {
+ m_unrd_cur += size;
+ if (m_unrd_size == m_unrd_cur)
+ {
+ free(m_unread);
+ m_unread = NULL;
+ m_unrd_size = 0;
+ m_unrd_cur = 0;
+ }
+ }
+
+ return size;
+}
+
+
+// ==========================================================================
+// wxSocketServer
+// ==========================================================================
+
+// --------------------------------------------------------------------------
+// Ctor
+// --------------------------------------------------------------------------
+
+wxSocketServer::wxSocketServer(wxSockAddress& addr_man,
+ wxSocketFlags flags)
+ : wxSocketBase(flags, wxSOCKET_SERVER)
+{
+ wxLogTrace( wxTRACE_Socket, wxT("Opening wxSocketServer") );
+
+ m_socket = GSocket_new();
+
+ if (!m_socket)
+ {
+ wxLogTrace( wxTRACE_Socket, wxT("*** GSocket_new failed") );
+ return;
+ }
+
+ // Setup the socket as server
+
+#if 0
+ GSocket_SetLocal(m_socket, addr_man.GetAddress());
+ if (GSocket_SetServer(m_socket) != GSOCK_NOERROR)
+ {
+ GSocket_destroy(m_socket);
+ m_socket = NULL;
+
+ wxLogTrace( wxTRACE_Socket, wxT("*** GSocket_SetServer failed") );
+ return;
+ }
+
+ GSocket_SetTimeout(m_socket, m_timeout * 1000);
+ GSocket_SetCallback(m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
+ GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
+ wx_socket_callback, (char *)this);
+#endif
+}
+
+// --------------------------------------------------------------------------
+// Accept
+// --------------------------------------------------------------------------
+
+bool wxSocketServer::AcceptWith(wxSocketBase& sock, bool wait)
+{
+ GSocket *child_socket;
+
+ if (!m_socket)
+ return false;
+
+ // If wait == false, then the call should be nonblocking.
+ // When we are finished, we put the socket to blocking mode
+ // again.
+
+#if 0
+ if (!wait)
+ GSocket_SetNonBlocking(m_socket, 1);
+
+ child_socket = GSocket_WaitConnection(m_socket);
+
+ if (!wait)
+ GSocket_SetNonBlocking(m_socket, 0);
+
+ if (!child_socket)
+ return false;
+
+ sock.m_type = wxSOCKET_BASE;
+ sock.m_socket = child_socket;
+ sock.m_connected = true;
+
+ GSocket_SetTimeout(sock.m_socket, sock.m_timeout * 1000);
+ GSocket_SetCallback(sock.m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
+ GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
+ wx_socket_callback, (char *)&sock);
+#endif
+
+ return true;
+}
+
+wxSocketBase *wxSocketServer::Accept(bool wait)
+{
+ wxSocketBase* sock = new wxSocketBase();
+
+ sock->SetFlags(m_flags);
+
+ if (!AcceptWith(*sock, wait))
+ {
+ sock->Destroy();
+ sock = NULL;
+ }
+
+ return sock;
+}
+
+bool wxSocketServer::WaitForAccept(long seconds, long milliseconds)
+{
+ return _Wait(seconds, milliseconds, GSOCK_CONNECTION_FLAG);
+}
+
+// ==========================================================================
+// wxSocketClient
+// ==========================================================================
+
+// --------------------------------------------------------------------------
+// Ctor and dtor
+// --------------------------------------------------------------------------
+
+wxSocketClient::wxSocketClient(wxSocketFlags flags)
+ : wxSocketBase(flags, wxSOCKET_CLIENT)
+{
+}
+
+wxSocketClient::~wxSocketClient()
+{
+}
+
+// --------------------------------------------------------------------------
+// Connect
+// --------------------------------------------------------------------------
+
+bool wxSocketClient::Connect(wxSockAddress& addr_man, bool wait)
+{
+ GSocketError err;
+
+ if (m_socket)
+ {
+ // Shutdown and destroy the socket
+ Close();
+ GSocket_destroy(m_socket);
+ }
+
+ m_socket = GSocket_new();
+ m_connected = false;
+ m_establishing = false;
+
+ if (!m_socket)
+ return false;
+
+ GSocket_SetTimeout(m_socket, m_timeout * 1000);
+ GSocket_SetCallback(m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
+ GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
+ wx_socket_callback, (char *)this);
+
+ // If wait == false, then the call should be nonblocking.
+ // When we are finished, we put the socket to blocking mode
+ // again.
+
+ if (!wait)
+ GSocket_SetNonBlocking(m_socket, 1);
+
+ GSocket_SetPeer(m_socket, addr_man.GetAddress());
+ err = GSocket_Connect(m_socket, GSOCK_STREAMED);
+
+ if (!wait)
+ GSocket_SetNonBlocking(m_socket, 0);
+
+ if (err != GSOCK_NOERROR)
+ {
+ if (err == GSOCK_WOULDBLOCK)
+ m_establishing = true;
+
+ return false;
+ }
+
+ m_connected = true;
+ return true;
+}
+
+bool wxSocketClient::WaitOnConnect(long seconds, long milliseconds)
+{
+ if (m_connected) // Already connected
+ return true;
+
+ if (!m_establishing || !m_socket) // No connection in progress
+ return false;
+
+ return _Wait(seconds, milliseconds, GSOCK_CONNECTION_FLAG | GSOCK_LOST_FLAG);
+}
+
+// ==========================================================================
+// wxDatagramSocket
+// ==========================================================================
+
+/* NOTE: experimental stuff - might change */
+
+wxDatagramSocket::wxDatagramSocket( wxSockAddress& addr,
+ wxSocketFlags flags )
+ : wxSocketBase( flags, wxSOCKET_DATAGRAM )
+{
+#if 0
+ // Create the socket
+ m_socket = GSocket_new();
+
+ if (!m_socket)
+ return;
+
+ // Setup the socket as non connection oriented
+ GSocket_SetLocal(m_socket, addr.GetAddress());
+ if( GSocket_SetNonOriented(m_socket) != GSOCK_NOERROR )
+ {
+ GSocket_destroy(m_socket);
+ m_socket = NULL;
+ return;
+ }
+
+ // Initialize all stuff
+ m_connected = false;
+ m_establishing = false;
+ GSocket_SetTimeout( m_socket, m_timeout );
+ GSocket_SetCallback( m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
+ GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
+ wx_socket_callback, (char*)this );
+#endif
+}
+
+wxDatagramSocket& wxDatagramSocket::RecvFrom( wxSockAddress& addr,
+ void* buf,
+ wxUint32 nBytes )
+{
+ Read(buf, nBytes);
+ GetPeer(addr);
+ return (*this);
+}
+
+wxDatagramSocket& wxDatagramSocket::SendTo( wxSockAddress& addr,
+ const void* buf,
+ wxUint32 nBytes )
+{
+ GSocket_SetPeer(m_socket, addr.GetAddress());
+ Write(buf, nBytes);
+ return (*this);
+}
+
+/*
+ * -------------------------------------------------------------------------
+ * GAddress
+ * -------------------------------------------------------------------------
+ */
+
+/* CHECK_ADDRESS verifies that the current address family is either
+ * GSOCK_NOFAMILY or GSOCK_*family*, and if it is GSOCK_NOFAMILY, it
+ * initalizes it to be a GSOCK_*family*. In other cases, it returns
+ * an appropiate error code.
+ *
+ * CHECK_ADDRESS_RETVAL does the same but returning 'retval' on error.
+ */
+#define CHECK_ADDRESS(address, family) \
+{ \
+ if (address->m_family == GSOCK_NOFAMILY) \
+ if (_GAddress_Init_##family(address) != GSOCK_NOERROR) \
+ return address->m_error; \
+ if (address->m_family != GSOCK_##family) \
+ { \
+ address->m_error = GSOCK_INVADDR; \
+ return GSOCK_INVADDR; \
+ } \
+}
+
+#define CHECK_ADDRESS_RETVAL(address, family, retval) \
+{ \
+ if (address->m_family == GSOCK_NOFAMILY) \
+ if (_GAddress_Init_##family(address) != GSOCK_NOERROR) \
+ return retval; \
+ if (address->m_family != GSOCK_##family) \
+ { \
+ address->m_error = GSOCK_INVADDR; \
+ return retval; \
+ } \
+}
+
+
+GAddress *GAddress_new(void)
+{
+ GAddress *address;
+
+ if ((address = (GAddress *) malloc(sizeof(GAddress))) == NULL)
+ return NULL;
+
+ address->m_family = GSOCK_NOFAMILY;
+ address->m_addr = NULL;
+ address->m_len = 0;
+
+ return address;
+}
+
+GAddress *GAddress_copy(GAddress *address)
+{
+ GAddress *addr2;
+
+ assert(address != NULL);
+
+ if ((addr2 = (GAddress *) malloc(sizeof(GAddress))) == NULL)
+ return NULL;
+
+ memcpy(addr2, address, sizeof(GAddress));
+
+ if (address->m_addr && address->m_len > 0)
+ {
+ addr2->m_addr = (struct sockaddr *)malloc(addr2->m_len);
+ if (addr2->m_addr == NULL)
+ {
+ free(addr2);
+ return NULL;
+ }
+
+ memcpy(addr2->m_addr, address->m_addr, addr2->m_len);
+ }
+
+ return addr2;
+}
+
+void GAddress_destroy(GAddress *address)
+{
+ assert( address != NULL );
+
+ if (address->m_addr)
+ free(address->m_addr);
+
+ free(address);
+}
+
+void GAddress_SetFamily(GAddress *address, GAddressType type)
+{
+ assert(address != NULL);
+
+ address->m_family = type;
+}
+
+GAddressType GAddress_GetFamily(GAddress *address)
+{
+ assert( address != NULL );
+
+ return address->m_family;
+}
+
+GSocketError _GAddress_translate_from(GAddress *address,
+ struct sockaddr *addr, int len)
+{
+ address->m_realfamily = addr->sa_family;
+ switch (addr->sa_family)
+ {
+ case AF_INET:
+ address->m_family = GSOCK_INET;
+ break;
+
+ case AF_UNIX:
+ address->m_family = GSOCK_UNIX;
+ break;
+
+#ifdef AF_INET6
+ case AF_INET6:
+ address->m_family = GSOCK_INET6;
+ break;
+#endif
+
+ default:
+ {
+ address->m_error = GSOCK_INVOP;
+ return GSOCK_INVOP;
+ }
+ }
+
+ if (address->m_addr)
+ free(address->m_addr);
+
+ address->m_len = len;
+ address->m_addr = (struct sockaddr *)malloc(len);
+
+ if (address->m_addr == NULL)
+ {
+ address->m_error = GSOCK_MEMERR;
+ return GSOCK_MEMERR;
+ }
+
+ memcpy(address->m_addr, addr, len);
+
+ return GSOCK_NOERROR;
+}
+
+GSocketError _GAddress_translate_to(GAddress *address,
+ struct sockaddr **addr, int *len)
+{
+ if (!address->m_addr)
+ {
+ address->m_error = GSOCK_INVADDR;
+ return GSOCK_INVADDR;
+ }
+
+ *len = address->m_len;
+ *addr = (struct sockaddr *)malloc(address->m_len);
+ if (*addr == NULL)
+ {
+ address->m_error = GSOCK_MEMERR;
+ return GSOCK_MEMERR;
+ }
+
+ memcpy(*addr, address->m_addr, address->m_len);
+ return GSOCK_NOERROR;
+}
+
+/*
+ * -------------------------------------------------------------------------
+ * Internet address family
+ * -------------------------------------------------------------------------
+ */
+
+GSocketError _GAddress_Init_INET(GAddress *address)
+{
+ address->m_len = sizeof(struct sockaddr_in);
+ address->m_addr = (struct sockaddr *) malloc(address->m_len);
+ if (address->m_addr == NULL)
+ {
+ address->m_error = GSOCK_MEMERR;
+ return GSOCK_MEMERR;
+ }
+
+ memset( address->m_addr , 0 , address->m_len ) ;
+ address->m_family = GSOCK_INET;
+ address->m_realfamily = PF_INET;
+ ((struct sockaddr_in *)address->m_addr)->sin_family = AF_INET;
+ ((struct sockaddr_in *)address->m_addr)->sin_addr.s_addr = INADDR_ANY;
+
+ return GSOCK_NOERROR;
+}
+
+GSocketError GAddress_INET_SetHostName(GAddress *address, const char *hostname)
+{
+ struct hostent *he;
+ struct in_addr *addr;
+
+ assert( address != NULL );
+ CHECK_ADDRESS( address, INET );
+
+ addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
+
+ // If it is a numeric host name, convert it now
+#if defined(HAVE_INET_ATON)
+ if (inet_aton(hostname, addr) == 0)
+ {
+#elif defined(HAVE_INET_ADDR)
+ if ( (addr->s_addr = inet_addr(hostname)) == -1 )
+ {
+#else
+ // Use gethostbyname by default
+#ifndef __WXMAC__
+ int val = 1; // VA doesn't like constants in conditional expressions
+ if (val)
+#endif
+ {
+#endif
+ struct in_addr *array_addr;
+
+ // It is a real name, we solve it
+ if ((he = gethostbyname(hostname)) == NULL)
+ {
+ // Reset to invalid address
+ addr->s_addr = INADDR_NONE;
+ address->m_error = GSOCK_NOHOST;
+ return GSOCK_NOHOST;
+ }
+ array_addr = (struct in_addr *) *(he->h_addr_list);
+ addr->s_addr = array_addr[0].s_addr;
+ }
+
+ return GSOCK_NOERROR;
+}
+
+GSocketError GAddress_INET_SetBroadcastAddress(GAddress *address)
+{
+ return GAddress_INET_SetHostAddress(address, INADDR_BROADCAST);
+}
+
+GSocketError GAddress_INET_SetAnyAddress(GAddress *address)
+{
+ return GAddress_INET_SetHostAddress(address, INADDR_ANY);
+}
+
+GSocketError GAddress_INET_SetHostAddress(GAddress *address,
+ unsigned long hostaddr)
+{
+ struct in_addr *addr;
+
+ assert( address != NULL );
+ CHECK_ADDRESS( address, INET );
+
+ addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
+ addr->s_addr = htonl(hostaddr) ;
+
+ return GSOCK_NOERROR;
+}
+
+GSocketError GAddress_INET_SetPortName(GAddress *address, const char *port,
+ const char *protocol)
+{
+ struct servent *se;
+ struct sockaddr_in *addr;
+
+ assert( address != NULL );
+ CHECK_ADDRESS( address, INET );
+
+ if (!port)
+ {
+ address->m_error = GSOCK_INVPORT;
+ return GSOCK_INVPORT;
+ }
+
+ se = getservbyname(port, protocol);
+ if (!se)
+ {
+ // the cast to int suppresses compiler warnings
+ // about subscript having the type char
+ if (isdigit((int)port[0]))
+ {
+ int port_int;
+
+ port_int = atoi(port);
+ addr = (struct sockaddr_in *)address->m_addr;
+ addr->sin_port = htons(port_int);
+ return GSOCK_NOERROR;
+ }
+
+ address->m_error = GSOCK_INVPORT;
+ return GSOCK_INVPORT;
+ }
+
+ addr = (struct sockaddr_in *)address->m_addr;
+ addr->sin_port = se->s_port;
+
+ return GSOCK_NOERROR;
+}
+
+GSocketError GAddress_INET_SetPort(GAddress *address, unsigned short port)
+{
+ struct sockaddr_in *addr;
+
+ assert( address != NULL );
+ CHECK_ADDRESS( address, INET );
+
+ addr = (struct sockaddr_in *)address->m_addr;
+ addr->sin_port = htons(port);
+
+ return GSOCK_NOERROR;
+}
+
+GSocketError GAddress_INET_GetHostName(GAddress *address, char *hostname, size_t sbuf)
+{
+ struct hostent *he;
+ char *addr_buf;
+ struct sockaddr_in *addr;
+
+ assert( address != NULL );
+ CHECK_ADDRESS( address, INET );
+
+ addr = (struct sockaddr_in *)address->m_addr;
+ addr_buf = (char *)&(addr->sin_addr);
+
+ he = gethostbyaddr(addr_buf, sizeof(addr->sin_addr), AF_INET);
+ if (he == NULL)
+ {
+ address->m_error = GSOCK_NOHOST;
+ return GSOCK_NOHOST;
+ }
+
+ strncpy(hostname, he->h_name, sbuf);
+
+ return GSOCK_NOERROR;
+}
+
+unsigned long GAddress_INET_GetHostAddress(GAddress *address)
+{
+ struct sockaddr_in *addr;
+
+ assert( address != NULL );
+ CHECK_ADDRESS_RETVAL( address, INET, 0 );
+
+ addr = (struct sockaddr_in *)address->m_addr;
+
+ return ntohl(addr->sin_addr.s_addr) ;
+}
+
+unsigned short GAddress_INET_GetPort(GAddress *address)
+{
+ struct sockaddr_in *addr;
+
+ assert( address != NULL );
+ CHECK_ADDRESS_RETVAL( address, INET, 0 );
+
+ addr = (struct sockaddr_in *)address->m_addr;
+
+ return ntohs(addr->sin_port);
+}
+
+/*
+ * -------------------------------------------------------------------------
+ * Unix address family
+ * -------------------------------------------------------------------------
+ */
+
+GSocketError _GAddress_Init_UNIX(GAddress *address)
+{
+ address->m_len = sizeof(struct sockaddr_un);
+ address->m_addr = (struct sockaddr *)malloc(address->m_len);
+ if (address->m_addr == NULL)
+ {
+ address->m_error = GSOCK_MEMERR;
+ return GSOCK_MEMERR;
+ }
+
+ address->m_family = GSOCK_UNIX;
+ address->m_realfamily = PF_UNIX;
+ ((struct sockaddr_un *)address->m_addr)->sun_family = AF_UNIX;
+ ((struct sockaddr_un *)address->m_addr)->sun_path[0] = 0;
+
+ return GSOCK_NOERROR;
+}
+
+#define UNIX_SOCK_PATHLEN (sizeof(addr->sun_path)/sizeof(addr->sun_path[0]))
+
+GSocketError GAddress_UNIX_SetPath(GAddress *address, const char *path)
+{
+ struct sockaddr_un *addr;
+
+ assert( address != NULL );
+ CHECK_ADDRESS( address, UNIX );
+
+ addr = ((struct sockaddr_un *)address->m_addr);
+ strncpy(addr->sun_path, path, UNIX_SOCK_PATHLEN);
+ addr->sun_path[UNIX_SOCK_PATHLEN - 1] = '\0';
+
+ return GSOCK_NOERROR;
+}
+
+GSocketError GAddress_UNIX_GetPath(GAddress *address, char *path, size_t sbuf)
+{
+ struct sockaddr_un *addr;
+
+ assert( address != NULL );
+ CHECK_ADDRESS( address, UNIX );
+
+ addr = (struct sockaddr_un *)address->m_addr;
+
+ strncpy(path, addr->sun_path, sbuf);
+
+ return GSOCK_NOERROR;
+}
+
+/* Address handling */
+
+/* GSocket_SetLocal:
+ * GSocket_GetLocal:
+ * GSocket_SetPeer:
+ * GSocket_GetPeer:
+ * Set or get the local or peer address for this socket. The 'set'
+ * functions return GSOCK_NOERROR on success, an error code otherwise.
+ * The 'get' functions return a pointer to a GAddress object on success,
+ * or NULL otherwise, in which case they set the error code of the
+ * corresponding GSocket.
+ *
+ * Error codes:
+ * GSOCK_INVSOCK - the socket is not valid.
+ * GSOCK_INVADDR - the address is not valid.
+ */
+
+GSocketError GSocket_SetLocal(GSocket *socket, GAddress *address)
+{
+ assert( socket != NULL );
+
+ // the socket must be initialized, or it must be a server
+ if ((socket->m_fd != INVALID_SOCKET && !socket->m_server))
+ {
+ socket->m_error = GSOCK_INVSOCK;
+ return GSOCK_INVSOCK;
+ }
+
+ // check address
+ if (address == NULL || address->m_family == GSOCK_NOFAMILY)
+ {
+ socket->m_error = GSOCK_INVADDR;
+ return GSOCK_INVADDR;
+ }
+
+ if (socket->m_local)
+ GAddress_destroy(socket->m_local);
+
+ socket->m_local = GAddress_copy(address);
+
+ return GSOCK_NOERROR;
+}
+
+GSocketError GSocket_SetPeer(GSocket *socket, GAddress *address)
+{
+ assert(socket != NULL);
+
+ // check address
+ if (address == NULL || address->m_family == GSOCK_NOFAMILY)
+ {
+ socket->m_error = GSOCK_INVADDR;
+ return GSOCK_INVADDR;
+ }
+
+ if (socket->m_peer)
+ GAddress_destroy(socket->m_peer);
+
+ socket->m_peer = GAddress_copy(address);
+
+ return GSOCK_NOERROR;
+}
+
+GAddress *GSocket_GetLocal(GSocket *socket)
+{
+ GAddress *address;
+ struct sockaddr addr;
+ socklen_t size = sizeof(addr);
+ GSocketError err;
+
+ assert( socket != NULL );
+
+ // try to get it from the m_local var first
+ if (socket->m_local)
+ return GAddress_copy(socket->m_local);
+
+ // else, if the socket is initialized, try getsockname
+ if (socket->m_fd == INVALID_SOCKET)
+ {
+ socket->m_error = GSOCK_INVSOCK;
+ return NULL;
+ }
+
+ if (getsockname(socket->m_fd, &addr, (socklen_t *) &size) < 0)
+ {
+ socket->m_error = GSOCK_IOERR;
+ return NULL;
+ }
+
+ // got a valid address from getsockname, create a GAddress object
+ address = GAddress_new();
+ if (address == NULL)
+ {
+ socket->m_error = GSOCK_MEMERR;
+ return NULL;
+ }
+
+ err = _GAddress_translate_from(address, &addr, size);
+ if (err != GSOCK_NOERROR)
+ {
+ GAddress_destroy(address);
+ socket->m_error = err;
+ return NULL;
+ }
+
+ return address;
+}
+
+GAddress *GSocket_GetPeer(GSocket *socket)
+{
+ assert(socket != NULL);
+
+ // try to get it from the m_peer var
+ if (socket->m_peer)
+ return GAddress_copy(socket->m_peer);
+
+ return NULL;
+}
+
+
+GSocket *GSocket_new(void)
+{
+ GSocket *socket;
+ socket = (GSocket *)malloc(sizeof(GSocket));
+
+ if (socket == NULL)
+ return NULL;
+
+ socket->m_fd = INVALID_SOCKET;
+
+ for (int i=0;im_cbacks[i] = NULL;
+ }
+
+ socket->m_detected = 0;
+
+ socket->m_local = NULL;
+ socket->m_peer = NULL;
+ socket->m_error = GSOCK_NOERROR;
+
+ socket->m_non_blocking = false ;
+ socket->m_stream = true;
+// socket->m_oriented = true;
+ socket->m_server = false;
+ socket->m_establishing = false;
+ socket->m_timeout = 10 * 60 * 1000;
+ // 10 minutes * 60 sec * 1000 millisec
+
+ socket->m_cfSocket = NULL ;
+ socket->m_runLoopSource = NULL ;
+ socket->m_readStream = NULL;
+ socket->m_writeStream = NULL;
+
+ return socket ;
+}
+
+void GSocket_close(GSocket *socket)
+{
+ if ( socket->m_cfSocket != NULL )
+ {
+ if ( socket->m_readStream )
+ {
+ CFReadStreamClose(socket->m_readStream);
+ CFRelease( socket->m_readStream ) ;
+ socket->m_readStream = NULL ;
+ }
+
+ if ( socket->m_writeStream )
+ {
+ CFWriteStreamClose(socket->m_writeStream);
+ CFRelease( socket->m_writeStream ) ;
+ socket->m_writeStream = NULL ;
+ }
+
+ CFSocketInvalidate( socket->m_cfSocket ) ;
+ CFRelease( socket->m_cfSocket ) ;
+ socket->m_cfSocket = NULL ;
+ socket->m_fd = INVALID_SOCKET ;
+ }
+}
+
+void GSocket_Shutdown(GSocket *socket)
+{
+ GSocket_close( socket );
+
+ // Disable GUI callbacks
+ for (int evt = 0; evt < GSOCK_MAX_EVENT; evt++)
+ socket->m_cbacks[evt] = NULL;
+
+ socket->m_detected = GSOCK_LOST_FLAG;
+}
+
+void GSocket_destroy(GSocket *socket)
+{
+ assert( socket != NULL );
+
+ // Check that the socket is really shut down
+ if (socket->m_fd != INVALID_SOCKET)
+ GSocket_Shutdown(socket);
+
+ // Destroy private addresses
+ if (socket->m_local)
+ GAddress_destroy(socket->m_local);
+
+ if (socket->m_peer)
+ GAddress_destroy(socket->m_peer);
+
+ // Destroy the socket itself
+ free(socket);
+}
+
+GSocketError GSocket_Connect(GSocket *socket, GSocketStream stream)
+{
+ assert( socket != NULL );
+
+ if (socket->m_fd != INVALID_SOCKET)
+ {
+ socket->m_error = GSOCK_INVSOCK;
+ return GSOCK_INVSOCK;
+ }
+
+ if (!socket->m_peer)
+ {
+ socket->m_error = GSOCK_INVADDR;
+ return GSOCK_INVADDR;
+ }
+
+ // Streamed or dgram socket?
+ socket->m_stream = (stream == GSOCK_STREAMED);
+ socket->m_oriented = true;
+ socket->m_server = false;
+ socket->m_establishing = false;
+
+ GSocketError returnErr = GSOCK_NOERROR ;
+ CFSocketError err ;
+
+ CFAllocatorRef alloc = kCFAllocatorDefault ;
+ CFSocketContext ctx ;
+ memset( &ctx , 0 , sizeof( ctx ) ) ;
+ ctx.info = socket ;
+ socket->m_cfSocket = CFSocketCreate( alloc , socket->m_peer->m_realfamily ,
+ stream == GSOCK_STREAMED ? SOCK_STREAM : SOCK_DGRAM , 0 ,
+ kCFSocketReadCallBack | kCFSocketWriteCallBack | kCFSocketConnectCallBack , wxMacCFSocketCallback , &ctx ) ;
+ _GSocket_Enable(socket, GSOCK_CONNECTION);
+
+ socket->m_fd = CFSocketGetNative( socket->m_cfSocket ) ;
+
+ CFStreamCreatePairWithSocket ( alloc , socket->m_fd , &socket->m_readStream , &socket->m_writeStream );
+ if ((socket->m_readStream == NULL) || (socket->m_writeStream == NULL))
+ {
+ GSocket_close(socket);
+ socket->m_error = GSOCK_IOERR;
+ return GSOCK_IOERR;
+ }
+
+ if ( !CFReadStreamOpen( socket->m_readStream ) || !CFWriteStreamOpen( socket->m_writeStream ) )
+ {
+ GSocket_close(socket);
+ socket->m_error = GSOCK_IOERR;
+ return GSOCK_IOERR;
+ }
+
+ CFRunLoopSourceRef rls = CFSocketCreateRunLoopSource(alloc , socket->m_cfSocket , 0);
+ CFRunLoopAddSource(CFRunLoopGetCurrent() , rls, kCFRunLoopCommonModes);
+ CFRelease(rls);
+
+ CFDataRef address = CFDataCreateWithBytesNoCopy(alloc, (const UInt8*) socket->m_peer->m_addr, socket->m_peer->m_len , kCFAllocatorNull);
+ if ( !address )
+ return GSOCK_MEMERR ;
+
+ err = CFSocketConnectToAddress( socket->m_cfSocket , address, socket->m_non_blocking ? -1 : socket->m_timeout / 1000 ) ;
+ CFRelease(address);
+
+ if (err != kCFSocketSuccess)
+ {
+ if ( err == kCFSocketTimeout )
+ {
+ GSocket_close(socket);
+ socket->m_error = GSOCK_TIMEDOUT ;
+ return GSOCK_TIMEDOUT ;
+ }
+
+ // we don't know whether a connect in progress will be issued like this
+ if ( err != kCFSocketTimeout && socket->m_non_blocking )
+ {
+ socket->m_establishing = true;
+ socket->m_error = GSOCK_WOULDBLOCK;
+ return GSOCK_WOULDBLOCK;
+ }
+
+ GSocket_close(socket);
+ socket->m_error = GSOCK_IOERR;
+ return GSOCK_IOERR;
+ }
+
+ return GSOCK_NOERROR;
+}
+
+/* Flags */
+
+/* GSocket_SetNonBlocking:
+ * Sets the socket to non-blocking mode.
+ * All IO calls will return immediately.
+ */
+void GSocket_SetNonBlocking(GSocket *socket, int non_block)
+{
+ assert( socket != NULL );
+
+// GSocket_Debug( ("GSocket_SetNonBlocking: %d\n", (int)non_block) );
+
+ socket->m_non_blocking = non_block;
+}
+
+/*
+ * GSocket_SetTimeout:
+ * Sets the timeout for blocking calls. Time is expressed in
+ * milliseconds.
+ */
+void GSocket_SetTimeout(GSocket *socket, unsigned long millisec)
+{
+ assert( socket != NULL );
+
+ socket->m_timeout = millisec;
+}
+
+/* GSocket_GetError:
+ * Returns the last error which occurred for this socket. Note that successful
+ * operations do not clear this back to GSOCK_NOERROR, so use it only
+ * after an error.
+ */
+GSocketError GSocket_GetError(GSocket *socket)
+{
+ assert( socket != NULL );
+
+ return socket->m_error;
+}
+
+/* Callbacks */
+
+/* GSOCK_INPUT:
+ * There is data to be read in the input buffer. If, after a read
+ * operation, there is still data available, the callback function will
+ * be called again.
+ * GSOCK_OUTPUT:
+ * The socket is available for writing. That is, the next write call
+ * won't block. This event is generated only once, when the connection is
+ * first established, and then only if a call failed with GSOCK_WOULDBLOCK,
+ * when the output buffer empties again. This means that the app should
+ * assume that it can write since the first OUTPUT event, and no more
+ * OUTPUT events will be generated unless an error occurs.
+ * GSOCK_CONNECTION:
+ * Connection successfully established, for client sockets, or incoming
+ * client connection, for server sockets. Wait for this event (also watch
+ * out for GSOCK_LOST) after you issue a nonblocking GSocket_Connect() call.
+ * GSOCK_LOST:
+ * The connection is lost (or a connection request failed); this could
+ * be due to a failure, or due to the peer closing it gracefully.
+ */
+
+/* GSocket_SetCallback:
+ * Enables the callbacks specified by 'flags'. Note that 'flags'
+ * may be a combination of flags OR'ed toghether, so the same
+ * callback function can be made to accept different events.
+ * The callback function must have the following prototype:
+ *
+ * void function(GSocket *socket, GSocketEvent event, char *cdata)
+ */
+void GSocket_SetCallback(GSocket *socket, GSocketEventFlags flags,
+ GSocketCallback callback, char *cdata)
+{
+ int count;
+
+ assert( socket != NULL );
+
+ for (count = 0; count < GSOCK_MAX_EVENT; count++)
+ {
+ if ((flags & (1 << count)) != 0)
+ {
+ socket->m_cbacks[count] = callback;
+ socket->m_data[count] = cdata;
+ }
+ }
+}
+
+/* GSocket_UnsetCallback:
+ * Disables all callbacks specified by 'flags', which may be a
+ * combination of flags OR'ed toghether.
+ */
+void GSocket_UnsetCallback(GSocket *socket, GSocketEventFlags flags)
+{
+ int count;
+
+ assert(socket != NULL);
+
+ for (count = 0; count < GSOCK_MAX_EVENT; count++)
+ {
+ if ((flags & (1 << count)) != 0)
+ {
+ socket->m_cbacks[count] = NULL;
+ socket->m_data[count] = NULL;
+ }
+ }
+}
+
+
+#define CALL_CALLBACK(socket, event) { \
+ _GSocket_Disable(socket, event); \
+ if (socket->m_cbacks[event]) \
+ socket->m_cbacks[event](socket, event, socket->m_data[event]); \
+}
+
+void _GSocket_Install_Callback(GSocket *socket, GSocketEvent event)
+{
+ int c;
+ switch (event)
+ {
+ case GSOCK_CONNECTION:
+ if (socket->m_server)
+ c = kCFSocketReadCallBack;
+ else
+ c = kCFSocketConnectCallBack;
+ break;
+
+ case GSOCK_LOST:
+ case GSOCK_INPUT:
+ c = kCFSocketReadCallBack;
+ break;
+
+ case GSOCK_OUTPUT:
+ c = kCFSocketWriteCallBack;
+ break;
+
+ default:
+ c = 0;
+ }
+
+ CFSocketEnableCallBacks(socket->m_cfSocket, c);
+}
+
+void _GSocket_Uninstall_Callback(GSocket *socket, GSocketEvent event)
+{
+ int c;
+ switch (event)
+ {
+ case GSOCK_CONNECTION:
+ if (socket->m_server)
+ c = kCFSocketReadCallBack;
+ else
+ c = kCFSocketConnectCallBack;
+ break;
+
+ case GSOCK_LOST:
+ case GSOCK_INPUT:
+ c = kCFSocketReadCallBack;
+ break;
+
+ case GSOCK_OUTPUT:
+ c = kCFSocketWriteCallBack;
+ break;
+
+ default:
+ c = 0;
+ break;
+ }
+
+ CFSocketDisableCallBacks(socket->m_cfSocket, c);
+}
+
+void _GSocket_Enable(GSocket *socket, GSocketEvent event)
+{
+ socket->m_detected &= ~(1 << event);
+ _GSocket_Install_Callback(socket, event);
+}
+
+void _GSocket_Disable(GSocket *socket, GSocketEvent event)
+{
+ socket->m_detected |= (1 << event);
+ _GSocket_Uninstall_Callback(socket, event);
+}
+
+void wxMacCFSocketCallback(CFSocketRef s, CFSocketCallBackType callbackType,
+ CFDataRef address, const void* data, void* info)
+{
+ GSocket* socket = (GSocket*)info;
+
+ switch (callbackType)
+ {
+ case kCFSocketConnectCallBack:
+ if ( data )
+ {
+ SInt32 error = *((SInt32*)data) ;
+ CALL_CALLBACK( socket , GSOCK_LOST ) ;
+ GSocket_Shutdown(socket);
+ }
+ else
+ {
+ CALL_CALLBACK( socket , GSOCK_CONNECTION ) ;
+ }
+ break;
+
+ case kCFSocketReadCallBack:
+ CALL_CALLBACK( socket , GSOCK_INPUT ) ;
+ break;
+
+ case kCFSocketWriteCallBack:
+ CALL_CALLBACK( socket , GSOCK_OUTPUT ) ;
+ break;
+
+ default:
+ break; // We shouldn't get here.
+ }
+}
+
+int GSocket_Read(GSocket *socket, char *buffer, int size)
+{
+ int ret = 0 ;
+
+ assert(socket != NULL);
+ // if ( !CFReadStreamHasBytesAvailable() )
+ ret = CFReadStreamRead( socket->m_readStream , (UInt8*) buffer , size ) ;
+
+ return ret;
+}
+
+int GSocket_Write(GSocket *socket, const char *buffer, int size)
+{
+ int ret;
+
+ assert(socket != NULL);
+ ret = CFWriteStreamWrite( socket->m_writeStream , (UInt8*) buffer , size ) ;
+
+ return ret;
+}
+
+GSocketEventFlags GSocket_Select(GSocket *socket, GSocketEventFlags flags)
+{
+ assert( socket != NULL );
+
+ return flags & socket->m_detected;
+}
+
+// ==========================================================================
+// wxSocketModule
+// ==========================================================================
+
+class wxSocketModule : public wxModule
+{
+public:
+ virtual bool OnInit()
+ {
+ // wxSocketBase will call GSocket_Init() itself when/if needed
+ return true;
+ }
+
+ virtual void OnExit()
+ {
+ if ( wxSocketBase::IsInitialized() )
+ wxSocketBase::Shutdown();
+ }
+
+private:
+ DECLARE_DYNAMIC_CLASS(wxSocketModule)
+};
+
+IMPLEMENT_DYNAMIC_CLASS(wxSocketModule, wxModule)
+
+#endif
+ // wxUSE_SOCKETS
diff --git a/src/osx/carbon/checkbox.cpp b/src/osx/carbon/checkbox.cpp
new file mode 100644
index 0000000000..982869b0aa
--- /dev/null
+++ b/src/osx/carbon/checkbox.cpp
@@ -0,0 +1,186 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/checkbox.cpp
+// Purpose: wxCheckBox
+// Author: Stefan Csomor
+// Modified by:
+// Created: 04/01/98
+// RCS-ID: $Id$
+// Copyright: (c) Stefan Csomor
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/wxprec.h"
+
+#if wxUSE_CHECKBOX
+
+#include "wx/checkbox.h"
+#include "wx/mac/uma.h"
+
+
+IMPLEMENT_DYNAMIC_CLASS(wxCheckBox, wxControl)
+IMPLEMENT_DYNAMIC_CLASS(wxBitmapCheckBox, wxCheckBox)
+
+
+// Single check box item
+bool wxCheckBox::Create(wxWindow *parent,
+ wxWindowID id,
+ const wxString& label,
+ const wxPoint& pos,
+ const wxSize& size,
+ long style,
+ const wxValidator& validator,
+ const wxString& name)
+{
+ m_macIsUserPane = false ;
+
+ if ( !wxCheckBoxBase::Create(parent, id, pos, size, style, validator, name) )
+ return false;
+
+ m_labelOrig = m_label = label ;
+
+ SInt32 maxValue = 1 /* kControlCheckboxCheckedValue */;
+ if (style & wxCHK_3STATE)
+ maxValue = 2 /* kControlCheckboxMixedValue */;
+
+ Rect bounds = wxMacGetBoundsForControl( this , pos , size ) ;
+ m_peer = new wxMacControl( this ) ;
+ verify_noerr( CreateCheckBoxControl(MAC_WXHWND(parent->MacGetTopLevelWindowRef()), &bounds ,
+ CFSTR("") , 0 , false , m_peer->GetControlRefAddr() ) );
+
+ m_peer->SetMaximum( maxValue ) ;
+
+ MacPostControlCreate(pos, size) ;
+
+ return true;
+}
+
+void wxCheckBox::SetValue(bool val)
+{
+ if (val)
+ Set3StateValue(wxCHK_CHECKED);
+ else
+ Set3StateValue(wxCHK_UNCHECKED);
+}
+
+bool wxCheckBox::GetValue() const
+{
+ return (DoGet3StateValue() != 0);
+}
+
+void wxCheckBox::Command(wxCommandEvent & event)
+{
+ int state = event.GetInt();
+
+ wxCHECK_RET( (state == wxCHK_UNCHECKED) || (state == wxCHK_CHECKED)
+ || (state == wxCHK_UNDETERMINED),
+ wxT("event.GetInt() returned an invalid checkbox state") );
+
+ Set3StateValue((wxCheckBoxState)state);
+
+ ProcessCommand(event);
+}
+
+wxCheckBoxState wxCheckBox::DoGet3StateValue() const
+{
+ return (wxCheckBoxState)m_peer->GetValue() ;
+}
+
+void wxCheckBox::DoSet3StateValue(wxCheckBoxState val)
+{
+ m_peer->SetValue( val ) ;
+}
+
+wxInt32 wxCheckBox::MacControlHit( WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) )
+{
+ wxCheckBoxState origState, newState;
+
+ newState = origState = Get3StateValue();
+
+ switch (origState)
+ {
+ case wxCHK_UNCHECKED:
+ newState = wxCHK_CHECKED;
+ break;
+
+ case wxCHK_CHECKED:
+ // If the style flag to allow the user setting the undetermined state is set,
+ // then set the state to undetermined; otherwise set state to unchecked.
+ newState = Is3rdStateAllowedForUser() ? wxCHK_UNDETERMINED : wxCHK_UNCHECKED;
+ break;
+
+ case wxCHK_UNDETERMINED:
+ newState = wxCHK_UNCHECKED;
+ break;
+
+ default:
+ break;
+ }
+
+ if (newState != origState)
+ {
+ Set3StateValue( newState );
+
+ wxCommandEvent event( wxEVT_COMMAND_CHECKBOX_CLICKED, m_windowId );
+ event.SetInt( newState );
+ event.SetEventObject( this );
+ ProcessCommand( event );
+ }
+
+ return noErr;
+}
+
+// Bitmap checkbox
+bool wxBitmapCheckBox::Create(wxWindow *parent,
+ wxWindowID id,
+ const wxBitmap *WXUNUSED(label),
+ const wxPoint& WXUNUSED(pos),
+ const wxSize& WXUNUSED(size),
+ long style,
+ const wxValidator& wxVALIDATOR_PARAM(validator),
+ const wxString& name)
+{
+ SetName(name);
+#if wxUSE_VALIDATORS
+ SetValidator(validator);
+#endif
+ m_windowStyle = style;
+
+ if (parent)
+ parent->AddChild(this);
+
+ if ( id == -1 )
+ m_windowId = NewControlId();
+ else
+ m_windowId = id;
+
+ // TODO: Create the bitmap checkbox
+
+ return false;
+}
+
+void wxBitmapCheckBox::SetLabel(const wxBitmap *WXUNUSED(bitmap))
+{
+ // TODO
+ wxFAIL_MSG(wxT("wxBitmapCheckBox::SetLabel() not yet implemented"));
+}
+
+void wxBitmapCheckBox::SetSize(int x, int y, int width, int height, int sizeFlags)
+{
+ wxControl::SetSize( x , y , width , height , sizeFlags ) ;
+}
+
+void wxBitmapCheckBox::SetValue(bool WXUNUSED(val))
+{
+ // TODO
+ wxFAIL_MSG(wxT("wxBitmapCheckBox::SetValue() not yet implemented"));
+}
+
+bool wxBitmapCheckBox::GetValue() const
+{
+ // TODO
+ wxFAIL_MSG(wxT("wxBitmapCheckBox::GetValue() not yet implemented"));
+
+ return false;
+}
+
+#endif
diff --git a/src/osx/carbon/checklst.cpp b/src/osx/carbon/checklst.cpp
new file mode 100644
index 0000000000..5f0fecb5e2
--- /dev/null
+++ b/src/osx/carbon/checklst.cpp
@@ -0,0 +1,273 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/checklst.cpp
+// Purpose: implementation of wxCheckListBox class
+// Author: Stefan Csomor
+// Modified by:
+// Created: 1998-01-01
+// RCS-ID: $Id$
+// Copyright: (c) Stefan Csomor
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+//
+// new DataBrowser-based version
+
+
+#include "wx/wxprec.h"
+
+#if wxUSE_CHECKLISTBOX
+
+#include "wx/checklst.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/arrstr.h"
+#endif
+
+#include "wx/mac/uma.h"
+
+IMPLEMENT_DYNAMIC_CLASS(wxCheckListBox, wxListBox)
+
+BEGIN_EVENT_TABLE(wxCheckListBox, wxListBox)
+END_EVENT_TABLE()
+
+class wxMacDataBrowserCheckListControl : public wxMacDataBrowserListControl , public wxMacCheckListControl
+{
+public:
+ wxMacDataBrowserCheckListControl( wxListBox *peer, const wxPoint& pos, const wxSize& size, long style );
+ wxMacDataBrowserCheckListControl() {}
+ virtual ~wxMacDataBrowserCheckListControl();
+
+ virtual wxMacDataItem* CreateItem();
+
+ virtual bool MacIsChecked(unsigned int n) const;
+ virtual void MacCheck(unsigned int n, bool bCheck = true);
+ DECLARE_DYNAMIC_CLASS_NO_COPY(wxMacDataBrowserCheckListControl)
+};
+
+IMPLEMENT_DYNAMIC_CLASS( wxMacDataBrowserCheckListControl , wxMacDataBrowserListControl )
+
+void wxCheckListBox::Init()
+{
+}
+
+bool wxCheckListBox::Create(
+ wxWindow *parent,
+ wxWindowID id,
+ const wxPoint &pos,
+ const wxSize &size,
+ const wxArrayString& choices,
+ long style,
+ const wxValidator& validator,
+ const wxString &name )
+{
+ wxCArrayString chs( choices );
+
+ return Create( parent, id, pos, size, chs.GetCount(), chs.GetStrings(), style, validator, name );
+}
+
+bool wxCheckListBox::Create(
+ wxWindow *parent,
+ wxWindowID id,
+ const wxPoint& pos,
+ const wxSize& size,
+ int n,
+ const wxString choices[],
+ long style,
+ const wxValidator& validator,
+ const wxString& name )
+{
+ m_macIsUserPane = false;
+
+ wxASSERT_MSG( !(style & wxLB_MULTIPLE) || !(style & wxLB_EXTENDED),
+ wxT("only one of listbox selection modes can be specified") );
+
+ if ( !wxListBoxBase::Create( parent, id, pos, size, style & ~(wxHSCROLL | wxVSCROLL), validator, name ) )
+ return false;
+
+ // this will be increased by our Append command
+ wxMacDataBrowserCheckListControl* control = new wxMacDataBrowserCheckListControl( this, pos, size, style );
+ // TODO CHECK control->SetClientDataType( m_clientDataItemsType );
+ m_peer = control;
+
+ MacPostControlCreate(pos,size);
+
+ InsertItems( n , choices , 0 );
+
+ // Needed because it is a wxControlWithItems
+ SetInitialSize( size );
+
+ return true;
+}
+
+// ----------------------------------------------------------------------------
+// wxCheckListBox functions
+// ----------------------------------------------------------------------------
+
+bool wxCheckListBox::IsChecked(unsigned int item) const
+{
+ wxCHECK_MSG( IsValid(item), false,
+ wxT("invalid index in wxCheckListBox::IsChecked") );
+
+ return GetPeer()->MacIsChecked( item );
+}
+
+void wxCheckListBox::Check(unsigned int item, bool check)
+{
+ wxCHECK_RET( IsValid(item),
+ wxT("invalid index in wxCheckListBox::Check") );
+
+ bool isChecked = GetPeer()->MacIsChecked( item );
+ if ( check != isChecked )
+ {
+ GetPeer()->MacCheck( item , check );
+ }
+}
+
+wxMacCheckListControl* wxCheckListBox::GetPeer() const
+{
+ wxMacDataBrowserCheckListControl *lb = wxDynamicCast(m_peer,wxMacDataBrowserCheckListControl);
+ return lb ? wx_static_cast(wxMacCheckListControl*,lb) : 0 ;
+}
+
+const short kCheckboxColumnId = 1026;
+
+wxMacDataBrowserCheckListControl::wxMacDataBrowserCheckListControl( wxListBox *peer, const wxPoint& pos, const wxSize& size, long style)
+ : wxMacDataBrowserListControl( peer, pos, size, style )
+{
+ OSStatus err = noErr;
+
+ DataBrowserListViewColumnDesc columnDesc;
+ columnDesc.headerBtnDesc.titleOffset = 0;
+ columnDesc.headerBtnDesc.version = kDataBrowserListViewLatestHeaderDesc;
+
+ columnDesc.headerBtnDesc.btnFontStyle.flags =
+ kControlUseFontMask | kControlUseJustMask;
+
+ columnDesc.headerBtnDesc.btnContentInfo.contentType = kControlNoContent;
+ columnDesc.headerBtnDesc.btnFontStyle.just = teFlushDefault;
+ columnDesc.headerBtnDesc.btnFontStyle.font = kControlFontViewSystemFont;
+ columnDesc.headerBtnDesc.btnFontStyle.style = normal;
+ columnDesc.headerBtnDesc.titleString = NULL;
+
+ columnDesc.headerBtnDesc.minimumWidth = 30;
+ columnDesc.headerBtnDesc.maximumWidth = 30;
+
+ columnDesc.propertyDesc.propertyID = kCheckboxColumnId;
+ columnDesc.propertyDesc.propertyType = kDataBrowserCheckboxType;
+ columnDesc.propertyDesc.propertyFlags =
+ kDataBrowserPropertyIsMutable
+ | kDataBrowserTableViewSelectionColumn
+ | kDataBrowserDefaultPropertyFlags;
+
+ err = AddColumn( &columnDesc, 0 );
+ verify_noerr( err );
+}
+
+wxMacDataBrowserCheckListControl::~wxMacDataBrowserCheckListControl()
+{
+
+}
+
+class wxMacCheckListBoxItem : public wxMacListBoxItem
+{
+public :
+ wxMacCheckListBoxItem()
+ {
+ m_isChecked = false;
+ }
+
+ virtual ~wxMacCheckListBoxItem()
+ {
+ }
+
+ virtual OSStatus GetSetData( wxMacDataItemBrowserControl *owner ,
+ DataBrowserPropertyID property,
+ DataBrowserItemDataRef itemData,
+ bool changeValue )
+ {
+ OSStatus err = errDataBrowserPropertyNotSupported;
+
+ wxCheckListBox *checklist = wxDynamicCast( owner->GetPeer() , wxCheckListBox );
+ wxCHECK_MSG( checklist != NULL , errDataBrowserPropertyNotSupported , wxT("wxCheckListBox expected"));
+
+ if ( !changeValue )
+ {
+ switch (property)
+ {
+ case kCheckboxColumnId:
+ verify_noerr(SetDataBrowserItemDataButtonValue( itemData, m_isChecked ? kThemeButtonOn : kThemeButtonOff ));
+ err = noErr;
+ break;
+
+ case kDataBrowserItemIsEditableProperty:
+ verify_noerr(SetDataBrowserItemDataBooleanValue( itemData, true ));
+ err = noErr;
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+ {
+ switch (property)
+ {
+ case kCheckboxColumnId:
+ {
+ // we have to change this behind the back, since Check() would be triggering another update round
+ bool newVal = !m_isChecked;
+ verify_noerr(SetDataBrowserItemDataButtonValue( itemData, newVal ? kThemeButtonOn : kThemeButtonOff ));
+ m_isChecked = newVal;
+ err = noErr;
+
+ wxCommandEvent event( wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, checklist->GetId() );
+ event.SetInt( owner->GetLineFromItem( this ) );
+ event.SetEventObject( checklist );
+ checklist->HandleWindowEvent( event );
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if ( err == errDataBrowserPropertyNotSupported )
+ err = wxMacListBoxItem::GetSetData( owner , property, itemData , changeValue);
+
+ return err;
+ }
+
+ void Check( bool check )
+ {
+ m_isChecked = check;
+ }
+ bool IsChecked() const
+ {
+ return m_isChecked;
+ }
+
+protected :
+ bool m_isChecked;
+};
+
+wxMacDataItem* wxMacDataBrowserCheckListControl::CreateItem()
+{
+ return new wxMacCheckListBoxItem();
+}
+
+void wxMacDataBrowserCheckListControl::MacCheck( unsigned int n, bool bCheck)
+{
+ wxMacCheckListBoxItem* item = wx_static_cast(wxMacCheckListBoxItem*, GetItemFromLine( n) );
+ item->Check( bCheck);
+ UpdateItem(wxMacDataBrowserRootContainer, item , kCheckboxColumnId);
+}
+
+bool wxMacDataBrowserCheckListControl::MacIsChecked( unsigned int n) const
+{
+ wxMacCheckListBoxItem * item = wx_static_cast( wxMacCheckListBoxItem*, GetItemFromLine( n ) );
+ return item->IsChecked();
+}
+
+
+
+#endif // wxUSE_CHECKLISTBOX
diff --git a/src/osx/carbon/choice.cpp b/src/osx/carbon/choice.cpp
new file mode 100644
index 0000000000..c395a39d19
--- /dev/null
+++ b/src/osx/carbon/choice.cpp
@@ -0,0 +1,308 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/choice.cpp
+// Purpose: wxChoice
+// Author: Stefan Csomor
+// Modified by:
+// Created: 1998-01-01
+// RCS-ID: $Id$
+// Copyright: (c) Stefan Csomor
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/wxprec.h"
+
+#if wxUSE_CHOICE
+
+#include "wx/choice.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/menu.h"
+ #include "wx/dcclient.h"
+#endif
+
+#include "wx/mac/uma.h"
+
+extern MenuHandle NewUniqueMenu() ;
+
+IMPLEMENT_DYNAMIC_CLASS(wxChoice, wxControlWithItems)
+
+
+wxChoice::~wxChoice()
+{
+ if ( HasClientObjectData() )
+ {
+ unsigned int i, max = GetCount();
+
+ for ( i = 0; i < max; ++i )
+ delete GetClientObject( i );
+ }
+
+ // DeleteMenu( m_macPopUpMenuId ) ;
+ // DisposeMenu( m_macPopUpMenuHandle ) ;
+}
+
+bool wxChoice::Create(wxWindow *parent,
+ wxWindowID id,
+ const wxPoint& pos,
+ const wxSize& size,
+ const wxArrayString& choices,
+ long style,
+ const wxValidator& validator,
+ const wxString& name )
+{
+ if ( !Create( parent, id, pos, size, 0, NULL, style, validator, name ) )
+ return false;
+
+ Append( choices );
+
+ if ( !choices.empty() )
+ SetSelection( 0 );
+
+ SetInitialSize( size );
+
+ return true;
+}
+
+bool wxChoice::Create(wxWindow *parent,
+ wxWindowID id,
+ const wxPoint& pos,
+ const wxSize& size,
+ int n,
+ const wxString choices[],
+ long style,
+ const wxValidator& validator,
+ const wxString& name )
+{
+ m_macIsUserPane = false;
+
+ if ( !wxChoiceBase::Create( parent, id, pos, size, style, validator, name ) )
+ return false;
+
+ Rect bounds = wxMacGetBoundsForControl( this , pos , size );
+
+ m_peer = new wxMacControl( this ) ;
+ OSStatus err = CreatePopupButtonControl(
+ MAC_WXHWND(parent->MacGetTopLevelWindowRef()) , &bounds , CFSTR("") ,
+ -12345 , false /* no variable width */ , 0 , 0 , 0 , m_peer->GetControlRefAddr() );
+ verify_noerr( err );
+
+ m_macPopUpMenuHandle = NewUniqueMenu() ;
+ m_peer->SetData( kControlNoPart , kControlPopupButtonMenuHandleTag , (MenuHandle) m_macPopUpMenuHandle ) ;
+ m_peer->SetValueAndRange( n > 0 ? 1 : 0 , 0 , 0 );
+ MacPostControlCreate( pos, size );
+
+#if !wxUSE_STL
+ if ( style & wxCB_SORT )
+ // autosort
+ m_strings = wxArrayString( 1 );
+#endif
+
+ Append(n, choices);
+
+ // Set the first item as being selected
+ if (n > 0)
+ SetSelection( 0 );
+
+ // Needed because it is a wxControlWithItems
+ SetInitialSize( size );
+
+ return true;
+}
+
+// ----------------------------------------------------------------------------
+// adding/deleting items to/from the list
+// ----------------------------------------------------------------------------
+
+int wxChoice::DoInsertItems(const wxArrayStringsAdapter & items,
+ unsigned int pos,
+ void **clientData, wxClientDataType type)
+{
+ const unsigned int numItems = items.GetCount();
+ for( unsigned int i = 0; i < numItems; ++i, ++pos )
+ {
+ unsigned int idx;
+
+#if wxUSE_STL
+ if ( IsSorted() )
+ {
+ wxArrayString::iterator
+ insertPoint = std::lower_bound( m_strings.begin(), m_strings.end(), items[i] );
+ idx = insertPoint - m_strings.begin();
+ m_strings.insert( insertPoint, items[i] );
+ }
+ else
+#endif // wxUSE_STL
+ {
+ idx = pos;
+ m_strings.Insert( items[i], idx );
+ }
+
+ UMAInsertMenuItem(MAC_WXHMENU( m_macPopUpMenuHandle ),
+ items[i],
+ GetFont().GetEncoding(),
+ idx);
+ m_datas.Insert( NULL, idx );
+ AssignNewItemClientData(idx, clientData, i, type);
+ }
+
+ m_peer->SetMaximum( GetCount() );
+
+ return pos - 1;
+}
+
+void wxChoice::DoDeleteOneItem(unsigned int n)
+{
+ wxCHECK_RET( IsValid(n) , wxT("wxChoice::Delete: invalid index") );
+
+ if ( HasClientObjectData() )
+ delete GetClientObject( n );
+
+ ::DeleteMenuItem( MAC_WXHMENU(m_macPopUpMenuHandle) , n + 1 ) ;
+ m_strings.RemoveAt( n ) ;
+ m_datas.RemoveAt( n ) ;
+ m_peer->SetMaximum( GetCount() ) ;
+}
+
+void wxChoice::DoClear()
+{
+ for ( unsigned int i = 0 ; i < GetCount() ; i++ )
+ {
+ ::DeleteMenuItem( MAC_WXHMENU(m_macPopUpMenuHandle) , 1 ) ;
+ }
+
+ m_strings.Empty() ;
+ m_datas.Empty() ;
+ m_peer->SetMaximum( 0 ) ;
+}
+
+// ----------------------------------------------------------------------------
+// selection
+// ----------------------------------------------------------------------------
+int wxChoice::GetSelection() const
+{
+ return m_peer->GetValue() - 1 ;
+}
+
+void wxChoice::SetSelection( int n )
+{
+ m_peer->SetValue( n + 1 ) ;
+}
+
+// ----------------------------------------------------------------------------
+// string list functions
+// ----------------------------------------------------------------------------
+
+unsigned int wxChoice::GetCount() const
+{
+ return m_strings.GetCount() ;
+}
+
+int wxChoice::FindString( const wxString& s, bool bCase ) const
+{
+#if !wxUSE_STL
+ // Avoid assert for non-default args passed to sorted array Index
+ if ( IsSorted() )
+ bCase = true;
+#endif
+
+ return m_strings.Index( s , bCase ) ;
+}
+
+void wxChoice::SetString(unsigned int n, const wxString& s)
+{
+ wxCHECK_RET( IsValid(n), wxT("wxChoice::SetString(): invalid index") );
+
+ m_strings[n] = s ;
+
+ // apple menu pos is 1-based
+ UMASetMenuItemText( MAC_WXHMENU(m_macPopUpMenuHandle) , n + 1 , s , wxFont::GetDefaultEncoding() ) ;
+}
+
+wxString wxChoice::GetString(unsigned int n) const
+{
+ wxCHECK_MSG( IsValid(n), wxEmptyString, wxT("wxChoice::GetString(): invalid index") );
+
+ return m_strings[n] ;
+}
+
+// ----------------------------------------------------------------------------
+// client data
+// ----------------------------------------------------------------------------
+void wxChoice::DoSetItemClientData(unsigned int n, void* clientData)
+{
+ wxCHECK_RET( IsValid(n), wxT("wxChoice::DoSetItemClientData: invalid index") );
+
+ m_datas[n] = (char*)clientData ;
+}
+
+void * wxChoice::DoGetItemClientData(unsigned int n) const
+{
+ wxCHECK_MSG( IsValid(n), NULL, wxT("wxChoice::DoGetClientData: invalid index") );
+
+ return (void *)m_datas[n];
+}
+
+wxInt32 wxChoice::MacControlHit( WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) )
+{
+ wxCommandEvent event( wxEVT_COMMAND_CHOICE_SELECTED, m_windowId );
+
+ // actually n should be made sure by the os to be a valid selection, but ...
+ int n = GetSelection();
+ if ( n > -1 )
+ {
+ event.SetInt( n );
+ event.SetString( GetStringSelection() );
+ event.SetEventObject( this );
+
+ if ( HasClientObjectData() )
+ event.SetClientObject( GetClientObject( n ) );
+ else if ( HasClientUntypedData() )
+ event.SetClientData( GetClientData( n ) );
+
+ ProcessCommand( event );
+ }
+
+ return noErr ;
+}
+
+wxSize wxChoice::DoGetBestSize() const
+{
+ int lbWidth = GetCount() > 0 ? 20 : 100; // some defaults
+ int lbHeight = 20;
+ int wLine;
+
+ SInt32 metric ;
+
+ GetThemeMetric( kThemeMetricPopupButtonHeight , &metric );
+ lbHeight = metric ;
+
+ {
+ wxClientDC dc(const_cast(this));
+
+ // Find the widest line
+ for(unsigned int i = 0; i < GetCount(); i++)
+ {
+ wxString str(GetString(i));
+
+ wxCoord width, height ;
+ dc.GetTextExtent( str , &width, &height);
+ wLine = width ;
+
+ lbWidth = wxMax( lbWidth, wLine ) ;
+ }
+
+ // Add room for the popup arrow
+ lbWidth += 2 * lbHeight ;
+
+ wxCoord width, height ;
+ dc.GetTextExtent( wxT("X"), &width, &height);
+ int cx = width ;
+ lbHeight += 4;
+
+ lbWidth += cx ;
+ }
+
+ return wxSize( lbWidth, lbHeight );
+}
+
+#endif // wxUSE_CHOICE
diff --git a/src/osx/carbon/clipbrd.cpp b/src/osx/carbon/clipbrd.cpp
new file mode 100644
index 0000000000..7acd5845f4
--- /dev/null
+++ b/src/osx/carbon/clipbrd.cpp
@@ -0,0 +1,209 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/clipbrd.cpp
+// Purpose: Clipboard functionality
+// Author: Stefan Csomor;
+// Generalized clipboard implementation by Matthew Flatt
+// Modified by:
+// Created: 1998-01-01
+// RCS-ID: $Id$
+// Copyright: (c) Stefan Csomor
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/wxprec.h"
+
+#if wxUSE_CLIPBOARD
+
+#include "wx/clipbrd.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/intl.h"
+ #include "wx/log.h"
+ #include "wx/app.h"
+ #include "wx/utils.h"
+ #include "wx/frame.h"
+ #include "wx/bitmap.h"
+#endif
+
+#include "wx/metafile.h"
+
+#include "wx/mac/uma.h"
+
+#define wxUSE_DATAOBJ 1
+
+#include
+
+// the trace mask we use with wxLogTrace() - call
+// wxLog::AddTraceMask(TRACE_CLIPBOARD) to enable the trace messages from here
+// (there will be a *lot* of them!)
+#define TRACE_CLIPBOARD _T("clipboard")
+
+IMPLEMENT_DYNAMIC_CLASS(wxClipboard, wxObject)
+
+wxClipboard::wxClipboard()
+{
+ m_open = false;
+ m_data = NULL ;
+ PasteboardRef clipboard = 0;
+ OSStatus err = PasteboardCreate( kPasteboardClipboard, &clipboard );
+ if (err != noErr)
+ {
+ wxLogSysError( wxT("Failed to create the clipboard.") );
+ }
+ m_pasteboard.reset(clipboard);
+}
+
+wxClipboard::~wxClipboard()
+{
+ m_pasteboard.reset((PasteboardRef)0);
+ delete m_data;
+}
+
+void wxClipboard::Clear()
+{
+ if (m_data != NULL)
+ {
+ delete m_data;
+ m_data = NULL;
+ }
+
+ OSStatus err = PasteboardClear( m_pasteboard );
+ if (err != noErr)
+ {
+ wxLogSysError( wxT("Failed to empty the clipboard.") );
+ }
+}
+
+bool wxClipboard::Flush()
+{
+ return false;
+}
+
+bool wxClipboard::Open()
+{
+ wxCHECK_MSG( !m_open, false, wxT("clipboard already open") );
+
+ m_open = true;
+
+ return true;
+}
+
+bool wxClipboard::IsOpened() const
+{
+ return m_open;
+}
+
+bool wxClipboard::SetData( wxDataObject *data )
+{
+ if ( IsUsingPrimarySelection() )
+ return false;
+
+ wxCHECK_MSG( m_open, false, wxT("clipboard not open") );
+ wxCHECK_MSG( data, false, wxT("data is invalid") );
+
+ Clear();
+
+ // as we can only store one wxDataObject,
+ // this is the same in this implementation
+ return AddData( data );
+}
+
+bool wxClipboard::AddData( wxDataObject *data )
+{
+ if ( IsUsingPrimarySelection() )
+ return false;
+
+ wxCHECK_MSG( m_open, false, wxT("clipboard not open") );
+ wxCHECK_MSG( data, false, wxT("data is invalid") );
+
+ // we can only store one wxDataObject
+ Clear();
+
+ PasteboardSyncFlags syncFlags = PasteboardSynchronize( m_pasteboard );
+ wxCHECK_MSG( !(syncFlags&kPasteboardModified), false, wxT("clipboard modified after clear") );
+ wxCHECK_MSG( (syncFlags&kPasteboardClientIsOwner), false, wxT("client couldn't own clipboard") );
+
+ m_data = data;
+
+ data->AddToPasteboard( m_pasteboard, 1 );
+
+ return true;
+}
+
+void wxClipboard::Close()
+{
+ wxCHECK_RET( m_open, wxT("clipboard not open") );
+
+ m_open = false;
+
+ // Get rid of cached object.
+ // If this is not done, copying data from
+ // another application will only work once
+ if (m_data)
+ {
+ delete m_data;
+ m_data = (wxDataObject*) NULL;
+ }
+}
+
+bool wxClipboard::IsSupported( const wxDataFormat &dataFormat )
+{
+ wxLogTrace(TRACE_CLIPBOARD, wxT("Checking if format %s is available"),
+ dataFormat.GetId().c_str());
+
+ if ( m_data )
+ return m_data->IsSupported( dataFormat );
+ return wxDataObject::IsFormatInPasteboard( m_pasteboard, dataFormat );
+}
+
+bool wxClipboard::GetData( wxDataObject& data )
+{
+ if ( IsUsingPrimarySelection() )
+ return false;
+
+ wxCHECK_MSG( m_open, false, wxT("clipboard not open") );
+
+ size_t formatcount = data.GetFormatCount() + 1;
+ wxDataFormat *array = new wxDataFormat[ formatcount ];
+ array[0] = data.GetPreferredFormat();
+ data.GetAllFormats( &array[1] );
+
+ bool transferred = false;
+
+ if ( m_data )
+ {
+ for (size_t i = 0; !transferred && i < formatcount; i++)
+ {
+ wxDataFormat format = array[ i ];
+ if ( m_data->IsSupported( format ) )
+ {
+ int dataSize = m_data->GetDataSize( format );
+ transferred = true;
+
+ if (dataSize == 0)
+ {
+ data.SetData( format, 0, 0 );
+ }
+ else
+ {
+ char *d = new char[ dataSize ];
+ m_data->GetDataHere( format, (void*)d );
+ data.SetData( format, dataSize, d );
+ delete [] d;
+ }
+ }
+ }
+ }
+
+ // get formats from wxDataObjects
+ if ( !transferred )
+ {
+ transferred = data.GetFromPasteboard( m_pasteboard ) ;
+ }
+
+ delete [] array;
+
+ return transferred;
+}
+
+#endif
diff --git a/src/osx/carbon/colordlg.cpp b/src/osx/carbon/colordlg.cpp
new file mode 100644
index 0000000000..377276d0c4
--- /dev/null
+++ b/src/osx/carbon/colordlg.cpp
@@ -0,0 +1,75 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: colordlg.cpp
+// Purpose: wxColourDialog class. NOTE: you can use the generic class
+// if you wish, instead of implementing this.
+// Author: Stefan Csomor
+// Modified by:
+// Created: 1998-01-01
+// RCS-ID: $Id$
+// Copyright: (c) Stefan Csomor
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/wxprec.h"
+
+#include "wx/mac/colordlg.h"
+#include "wx/fontdlg.h"
+
+
+#if !USE_NATIVE_FONT_DIALOG_FOR_MACOSX
+
+IMPLEMENT_DYNAMIC_CLASS(wxColourDialog, wxDialog)
+
+#include "wx/mac/private.h"
+
+/*
+ * wxColourDialog
+ */
+
+wxColourDialog::wxColourDialog()
+{
+ m_dialogParent = NULL;
+}
+
+wxColourDialog::wxColourDialog(wxWindow *parent, wxColourData *data)
+{
+ Create(parent, data);
+}
+
+bool wxColourDialog::Create(wxWindow *parent, wxColourData *data)
+{
+ m_dialogParent = parent;
+
+ if (data)
+ m_colourData = *data;
+ return true;
+}
+
+int wxColourDialog::ShowModal()
+{
+ RGBColor currentColor ;
+
+ m_colourData.m_dataColour.GetRGBColor( currentColor );
+ NColorPickerInfo info;
+ OSStatus err ;
+ memset(&info, 0, sizeof(info)) ;
+ // TODO : use parent to determine better position and then kAtSpecifiedOrigin
+ info.placeWhere = kCenterOnMainScreen ;
+ info.flags = kColorPickerDialogIsMoveable | kColorPickerDialogIsModal ;
+ info.theColor.color.rgb.red = currentColor.red ;
+ info.theColor.color.rgb.green = currentColor.green ;
+ info.theColor.color.rgb.blue = currentColor.blue ;
+ err = NPickColor(&info);
+ if ((err == noErr) && info.newColorChosen)
+ {
+ currentColor.red = info.theColor.color.rgb.red ;
+ currentColor.green = info.theColor.color.rgb.green ;
+ currentColor.blue = info.theColor.color.rgb.blue ;
+ m_colourData.m_dataColour = currentColor;
+
+ return wxID_OK;
+ }
+ return wxID_CANCEL;
+}
+
+#endif
diff --git a/src/osx/carbon/colordlgosx.mm b/src/osx/carbon/colordlgosx.mm
new file mode 100644
index 0000000000..ea058c24f7
--- /dev/null
+++ b/src/osx/carbon/colordlgosx.mm
@@ -0,0 +1,193 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/colordlg.mm
+// Purpose: wxColourDialog class. NOTE: you can use the generic class
+// if you wish, instead of implementing this.
+// Author: Ryan Norton
+// Modified by:
+// Created: 2004-11-16
+// RCS-ID: $Id$
+// Copyright: (c) Ryan Norton
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+// ===========================================================================
+// declarations
+// ===========================================================================
+
+// ---------------------------------------------------------------------------
+// headers
+// ---------------------------------------------------------------------------
+
+#include "wx/wxprec.h"
+
+#include "wx/mac/colordlg.h"
+#include "wx/fontdlg.h"
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+//Mac OSX 10.2+ only
+#if USE_NATIVE_FONT_DIALOG_FOR_MACOSX
+
+IMPLEMENT_DYNAMIC_CLASS(wxColourDialog, wxDialog)
+
+// Cocoa headers
+#include "wx/cocoa/autorelease.h"
+#include "wx/cocoa/string.h"
+
+#import
+#import
+#import
+#import
+#import
+
+// ---------------------------------------------------------------------------
+// wxCPWCDelegate - Window Closed delegate
+// ---------------------------------------------------------------------------
+
+@interface wxCPWCDelegate : NSObject
+{
+ bool m_bIsClosed;
+}
+
+// Delegate methods
+- (id)init;
+- (BOOL)windowShouldClose:(id)sender;
+- (BOOL)isClosed;
+@end // interface wxNSFontPanelDelegate : NSObject
+
+@implementation wxCPWCDelegate : NSObject
+
+- (id)init
+{
+ [super init];
+ m_bIsClosed = false;
+
+ return self;
+}
+
+- (BOOL)windowShouldClose:(id)sender
+{
+ wxUnusedVar(sender);
+
+ m_bIsClosed = true;
+
+ [NSApp abortModal];
+ [NSApp stopModal];
+ return YES;
+}
+
+- (BOOL)isClosed
+{
+ return m_bIsClosed;
+}
+
+@end // wxNSFontPanelDelegate
+
+/*
+ * wxColourDialog
+ */
+
+wxColourDialog::wxColourDialog()
+{
+ m_dialogParent = NULL;
+}
+
+wxColourDialog::wxColourDialog(wxWindow *parent, wxColourData *data)
+{
+ Create(parent, data);
+}
+
+bool wxColourDialog::Create(wxWindow *parent, wxColourData *data)
+{
+ m_dialogParent = parent;
+
+ if (data)
+ m_colourData = *data;
+
+ //
+ // This is the key call - this initializes
+ // events and window stuff for cocoa for carbon
+ // applications.
+ //
+ // This is also the only call here that is
+ // 10.2+ specific (the rest is OSX only),
+ // which, ironically, the carbon font
+ // panel requires.
+ //
+ bool bOK = NSApplicationLoad();
+
+ //autorelease pool - req'd for carbon
+ NSAutoreleasePool *thePool;
+ thePool = [[NSAutoreleasePool alloc] init];
+
+ if(m_colourData.m_dataColour.Ok())
+ [[NSColorPanel sharedColorPanel] setColor:
+ [NSColor colorWithCalibratedRed:m_colourData.m_dataColour.Red() / 255.0
+ green:m_colourData.m_dataColour.Green() / 255.0
+ blue:m_colourData.m_dataColour.Blue() / 255.0
+ alpha:1.0]
+ ];
+ else
+ [[NSColorPanel sharedColorPanel] setColor:[NSColor blackColor]];
+
+ //We're done - free up the pool
+ [thePool release];
+
+ return bOK;
+}
+int wxColourDialog::ShowModal()
+{
+ //Start the pool. Required for carbon interaction
+ //(For those curious, the only thing that happens
+ //if you don't do this is a bunch of error
+ //messages about leaks on the console,
+ //with no windows shown or anything).
+ NSAutoreleasePool *thePool;
+ thePool = [[NSAutoreleasePool alloc] init];
+
+ //Get the shared color and font panel
+ NSColorPanel* theColorPanel = [NSColorPanel sharedColorPanel];
+
+ //Create and assign the delegates (cocoa event handlers) so
+ //we can tell if a window has closed/open or not
+ wxCPWCDelegate* theCPDelegate = [[wxCPWCDelegate alloc] init];
+ [theColorPanel setDelegate:theCPDelegate];
+
+ //
+ // Start the color panel modal loop
+ //
+ NSModalSession session = [NSApp beginModalSessionForWindow:theColorPanel];
+ for (;;)
+ {
+ [NSApp runModalSession:session];
+
+ //If the color panel is closed, return the font panel modal loop
+ if ([theCPDelegate isClosed])
+ break;
+ }
+ [NSApp endModalSession:session];
+
+ //free up the memory for the delegates - we don't need them anymore
+ [theCPDelegate release];
+
+ //Get the shared color panel along with the chosen color and set the chosen color
+ NSColor* theColor = [[theColorPanel color] colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
+
+ m_colourData.m_dataColour.Set(
+ (unsigned char) ([theColor redComponent] * 255.0),
+ (unsigned char) ([theColor greenComponent] * 255.0),
+ (unsigned char) ([theColor blueComponent] * 255.0)
+ );
+
+ //Release the pool, we're done :)
+ [thePool release];
+
+ //Return ID_OK - there are no "apply" buttons or the like
+ //on either the font or color panel
+ return wxID_OK;
+}
+
+#endif //use native font dialog
+
diff --git a/src/osx/carbon/colour.cpp b/src/osx/carbon/colour.cpp
new file mode 100644
index 0000000000..9eb24718a3
--- /dev/null
+++ b/src/osx/carbon/colour.cpp
@@ -0,0 +1,147 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/colour.cpp
+// Purpose: wxColour class
+// Author: Stefan Csomor
+// Modified by:
+// Created: 1998-01-01
+// RCS-ID: $Id$
+// Copyright: (c) Stefan Csomor
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/wxprec.h"
+
+#include "wx/colour.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/gdicmn.h"
+#endif
+
+#include "wx/mac/private.h"
+
+IMPLEMENT_DYNAMIC_CLASS(wxColour, wxObject)
+
+#if wxMAC_USE_QUICKDRAW
+wxColour::wxColour(const RGBColor& col)
+{
+ InitRGBColor(col);
+}
+#endif
+
+wxColour::wxColour(CGColorRef col)
+{
+ InitCGColorRef(col);
+}
+
+#if wxMAC_USE_QUICKDRAW
+void wxColour::GetRGBColor( RGBColor *col ) const
+{
+ col->red = (m_red << 8) + m_red;
+ col->blue = (m_blue << 8) + m_blue;
+ col->green = (m_green << 8) + m_green;
+}
+
+wxColour& wxColour::operator=(const RGBColor& col)
+{
+ InitRGBColor(col);
+ return *this;
+}
+#endif
+
+wxColour& wxColour::operator=(CGColorRef col)
+{
+ InitCGColorRef(col);
+ return *this;
+}
+
+wxColour& wxColour::operator=(const wxColour& col)
+{
+ m_red = col.m_red;
+ m_green = col.m_green;
+ m_blue = col.m_blue;
+ m_alpha = col.m_alpha;
+ m_cgColour = col.m_cgColour;
+ return *this;
+}
+
+void wxColour::InitRGBA (ChannelType r, ChannelType g, ChannelType b, ChannelType a)
+{
+ m_red = r;
+ m_green = g;
+ m_blue = b;
+ m_alpha = a ;
+
+ CGColorRef col = 0 ;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+ if ( CGColorCreateGenericRGB )
+ col = CGColorCreateGenericRGB( (CGFloat)(r / 255.0), (CGFloat) (g / 255.0), (CGFloat) (b / 255.0), (CGFloat) (a / 255.0) );
+ else
+#endif
+ {
+ CGFloat components[4] = { (CGFloat)(r / 255.0), (CGFloat) (g / 255.0), (CGFloat) (b / 255.0), (CGFloat) (a / 255.0) } ;
+ col = CGColorCreate( wxMacGetGenericRGBColorSpace() , components ) ;
+ }
+ m_cgColour.reset( col );
+}
+
+#if wxMAC_USE_QUICKDRAW
+void wxColour::InitRGBColor( const RGBColor& col )
+{
+ m_red = col.red >> 8;
+ m_blue = col.blue >> 8;
+ m_green = col.green >> 8;
+ m_alpha = wxALPHA_OPAQUE;
+ CGColorRef cfcol;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+ if ( CGColorCreateGenericRGB )
+ cfcol = CGColorCreateGenericRGB((CGFloat)(col.red / 65535.0), (CGFloat)(col.green / 65535.0),
+ (CGFloat)(col.blue / 65535.0), (CGFloat) 1.0 );
+ else
+#endif
+ {
+ CGFloat components[4] = { (CGFloat)(col.red / 65535.0), (CGFloat)(col.green / 65535.0),
+ (CGFloat)(col.blue / 65535.0), (CGFloat) 1.0 } ;
+ cfcol = CGColorCreate( wxMacGetGenericRGBColorSpace() , components ) ;
+ }
+ m_cgColour.reset( cfcol );
+}
+#endif
+
+void wxColour::InitCGColorRef( CGColorRef col )
+{
+ m_cgColour.reset( col );
+ size_t noComp = CGColorGetNumberOfComponents( col );
+ if ( noComp >= 1 && noComp <= 4 )
+ {
+ // TODO verify whether we really are on a RGB color space
+ m_alpha = wxALPHA_OPAQUE;
+ const CGFloat *components = CGColorGetComponents( col );
+ if ( noComp >= 3 )
+ {
+ m_red = (int)(components[0]*255+0.5);
+ m_green = (int)(components[1]*255+0.5);
+ m_blue = (int)(components[2]*255+0.5);
+ if ( noComp == 4 )
+ m_alpha = (int)(components[3]*255+0.5);
+ }
+ else
+ {
+ m_red = (int)(components[0]*255+0.5);
+ m_green = (int)(components[0]*255+0.5);
+ m_blue = (int)(components[0]*255+0.5);
+ }
+ }
+ else
+ {
+ m_alpha = wxALPHA_OPAQUE;
+ m_red = m_green = m_blue = 0;
+ }
+}
+
+bool wxColour::operator == (const wxColour& colour) const
+{
+ return ( (IsOk() == colour.IsOk()) && (!IsOk() ||
+ CGColorEqualToColor( m_cgColour, colour.m_cgColour ) ) );
+}
+
+
diff --git a/src/osx/carbon/combobox.cpp b/src/osx/carbon/combobox.cpp
new file mode 100644
index 0000000000..90ba52c9c8
--- /dev/null
+++ b/src/osx/carbon/combobox.cpp
@@ -0,0 +1,668 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/combobox.cpp
+// Purpose: wxComboBox class
+// Author: Stefan Csomor, Dan "Bud" Keith (composite combobox)
+// Modified by:
+// Created: 1998-01-01
+// RCS-ID: $Id$
+// Copyright: (c) Stefan Csomor
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/wxprec.h"
+
+#if wxUSE_COMBOBOX
+
+#include "wx/combobox.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/button.h"
+ #include "wx/menu.h"
+ #include "wx/containr.h"
+ #include "wx/toplevel.h"
+ #include "wx/textctrl.h"
+#endif
+
+#include "wx/mac/uma.h"
+
+IMPLEMENT_DYNAMIC_CLASS(wxComboBox, wxControl)
+
+WX_DELEGATE_TO_CONTROL_CONTAINER(wxComboBox, wxControl)
+
+BEGIN_EVENT_TABLE(wxComboBox, wxControl)
+ WX_EVENT_TABLE_CONTROL_CONTAINER(wxComboBox)
+END_EVENT_TABLE()
+
+
+static int nextPopUpMenuId = 1000 ;
+
+MenuHandle NewUniqueMenu()
+{
+ MenuHandle handle = UMANewMenu(nextPopUpMenuId, wxString(wxT("Menu")), wxFont::GetDefaultEncoding() );
+ nextPopUpMenuId++ ;
+
+ return handle ;
+}
+
+
+// ----------------------------------------------------------------------------
+// constants
+// ----------------------------------------------------------------------------
+
+// the margin between the text control and the choice
+// margin should be bigger on OS X due to blue highlight
+// around text control.
+static const wxCoord MARGIN = 4;
+// this is the border a focus rect on OSX is needing
+static const int TEXTFOCUSBORDER = 3 ;
+
+
+// ----------------------------------------------------------------------------
+// wxComboBoxText: text control forwards events to combobox
+// ----------------------------------------------------------------------------
+
+class wxComboBoxText : public wxTextCtrl
+{
+public:
+ wxComboBoxText( wxComboBox * cb )
+ : wxTextCtrl( cb , 1 )
+ {
+ m_cb = cb;
+ SetTriggerOnSetValue( false );
+ }
+
+protected:
+ void OnChar( wxKeyEvent& event )
+ {
+ // Allows processing the tab key to go to the next control
+ if (event.GetKeyCode() == WXK_TAB)
+ {
+ wxNavigationKeyEvent NavEvent;
+ NavEvent.SetEventObject(this);
+ NavEvent.SetDirection(true);
+ NavEvent.SetWindowChange(false);
+
+ // Get the parent of the combo and have it process the navigation?
+ if (m_cb->GetParent()->HandleWindowEvent(NavEvent))
+ return;
+ }
+
+ // send the event to the combobox class in case the user has bound EVT_CHAR
+ wxKeyEvent kevt(event);
+ kevt.SetEventObject(m_cb);
+ if (m_cb->HandleWindowEvent(kevt))
+ // If the event was handled and not skipped then we're done
+ return;
+
+ if ( event.GetKeyCode() == WXK_RETURN )
+ {
+ wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_cb->GetId());
+ event.SetString( GetValue() );
+ event.SetInt( m_cb->GetSelection() );
+ event.SetEventObject( m_cb );
+
+ // This will invoke the dialog default action,
+ // such as the clicking the default button.
+ if (!m_cb->HandleWindowEvent( event ))
+ {
+ wxTopLevelWindow *tlw = wxDynamicCast(wxGetTopLevelParent(this), wxTopLevelWindow);
+ if ( tlw && tlw->GetDefaultItem() )
+ {
+ wxButton *def = wxDynamicCast(tlw->GetDefaultItem(), wxButton);
+ if ( def && def->IsEnabled() )
+ {
+ wxCommandEvent event( wxEVT_COMMAND_BUTTON_CLICKED, def->GetId() );
+ event.SetEventObject(def);
+ def->Command(event);
+ }
+ }
+
+ return;
+ }
+ }
+
+ event.Skip();
+ }
+
+ void OnKeyUp( wxKeyEvent& event )
+ {
+ event.SetEventObject(m_cb);
+ event.SetId(m_cb->GetId());
+ if (! m_cb->HandleWindowEvent(event))
+ event.Skip();
+ }
+
+ void OnKeyDown( wxKeyEvent& event )
+ {
+ event.SetEventObject(m_cb);
+ event.SetId(m_cb->GetId());
+ if (! m_cb->HandleWindowEvent(event))
+ event.Skip();
+ }
+
+ void OnText( wxCommandEvent& event )
+ {
+ event.SetEventObject(m_cb);
+ event.SetId(m_cb->GetId());
+ if (! m_cb->HandleWindowEvent(event))
+ event.Skip();
+ }
+
+private:
+ wxComboBox *m_cb;
+
+ DECLARE_EVENT_TABLE()
+};
+
+BEGIN_EVENT_TABLE(wxComboBoxText, wxTextCtrl)
+ EVT_KEY_DOWN(wxComboBoxText::OnKeyDown)
+ EVT_CHAR(wxComboBoxText::OnChar)
+ EVT_KEY_UP(wxComboBoxText::OnKeyUp)
+ EVT_TEXT(wxID_ANY, wxComboBoxText::OnText)
+END_EVENT_TABLE()
+
+class wxComboBoxChoice : public wxChoice
+{
+public:
+ wxComboBoxChoice( wxComboBox *cb, int style )
+ : wxChoice( cb , 1 , wxDefaultPosition , wxDefaultSize , 0 , NULL , style & (wxCB_SORT) )
+ {
+ m_cb = cb;
+ }
+
+ int GetPopupWidth() const
+ {
+ switch ( GetWindowVariant() )
+ {
+ case wxWINDOW_VARIANT_NORMAL :
+ case wxWINDOW_VARIANT_LARGE :
+ return 24 ;
+
+ default :
+ return 21 ;
+ }
+ }
+
+protected:
+ void OnChoice( wxCommandEvent& e )
+ {
+ wxString s = e.GetString();
+
+ m_cb->DelegateChoice( s );
+ wxCommandEvent event2(wxEVT_COMMAND_COMBOBOX_SELECTED, m_cb->GetId() );
+ event2.SetInt(m_cb->GetSelection());
+ event2.SetEventObject(m_cb);
+ event2.SetString(m_cb->GetStringSelection());
+ m_cb->ProcessCommand(event2);
+
+ // For consistency with MSW and GTK, also send a text updated event
+ // After all, the text is updated when a selection is made
+ wxCommandEvent TextEvent( wxEVT_COMMAND_TEXT_UPDATED, m_cb->GetId() );
+ TextEvent.SetString( m_cb->GetStringSelection() );
+ TextEvent.SetEventObject( m_cb );
+ m_cb->ProcessCommand( TextEvent );
+ }
+
+ virtual wxSize DoGetBestSize() const
+ {
+ wxSize sz = wxChoice::DoGetBestSize() ;
+ if (! m_cb->HasFlag(wxCB_READONLY) )
+ sz.x = GetPopupWidth() ;
+
+ return sz ;
+ }
+
+private:
+ wxComboBox *m_cb;
+
+ friend class wxComboBox;
+
+ DECLARE_EVENT_TABLE()
+};
+
+BEGIN_EVENT_TABLE(wxComboBoxChoice, wxChoice)
+ EVT_CHOICE(wxID_ANY, wxComboBoxChoice::OnChoice)
+END_EVENT_TABLE()
+
+wxComboBox::~wxComboBox()
+{
+ // delete the controls now, don't leave them alive even though they would
+ // still be eventually deleted by our parent - but it will be too late, the
+ // user code expects them to be gone now
+ if (m_text != NULL)
+ {
+ delete m_text;
+ m_text = NULL;
+ }
+
+ if (m_choice != NULL)
+ {
+ delete m_choice;
+ m_choice = NULL;
+ }
+}
+
+// ----------------------------------------------------------------------------
+// geometry
+// ----------------------------------------------------------------------------
+
+wxSize wxComboBox::DoGetBestSize() const
+{
+ if (!m_choice && !m_text)
+ return GetSize();
+
+ wxSize size = m_choice->GetBestSize();
+
+ if ( m_text != NULL )
+ {
+ wxSize sizeText = m_text->GetBestSize();
+ if (sizeText.y > size.y)
+ size.y = sizeText.y;
+
+ size.x = m_choice->GetPopupWidth() + sizeText.x + MARGIN;
+ size.x += TEXTFOCUSBORDER ;
+ size.y += 2 * TEXTFOCUSBORDER ;
+ }
+ else
+ {
+ // clipping is too tight
+ size.y += 1 ;
+ }
+
+ return size;
+}
+
+void wxComboBox::DoMoveWindow(int x, int y, int width, int height)
+{
+ wxControl::DoMoveWindow( x, y, width , height );
+
+ if ( m_text == NULL )
+ {
+ // we might not be fully constructed yet, therefore watch out...
+ if ( m_choice )
+ m_choice->SetSize(0, 0 , width, -1);
+ }
+ else
+ {
+ wxCoord wText = width - m_choice->GetPopupWidth() - MARGIN;
+ m_text->SetSize(TEXTFOCUSBORDER, TEXTFOCUSBORDER, wText, -1);
+
+ // put it at an inset of 1 to have outer area shadows drawn as well
+ m_choice->SetSize(TEXTFOCUSBORDER + wText + MARGIN - 1 , TEXTFOCUSBORDER, m_choice->GetPopupWidth() , -1);
+ }
+}
+
+// ----------------------------------------------------------------------------
+// operations forwarded to the subcontrols
+// ----------------------------------------------------------------------------
+
+bool wxComboBox::Enable(bool enable)
+{
+ if ( !wxControl::Enable(enable) )
+ return false;
+
+ if (m_text)
+ m_text->Enable(enable);
+
+ return true;
+}
+
+bool wxComboBox::Show(bool show)
+{
+ if ( !wxControl::Show(show) )
+ return false;
+
+ return true;
+}
+
+void wxComboBox::DelegateTextChanged( const wxString& value )
+{
+ SetStringSelection( value );
+}
+
+void wxComboBox::DelegateChoice( const wxString& value )
+{
+ SetStringSelection( value );
+}
+
+void wxComboBox::Init()
+{
+ WX_INIT_CONTROL_CONTAINER();
+}
+
+bool wxComboBox::Create(wxWindow *parent,
+ wxWindowID id,
+ const wxString& value,
+ const wxPoint& pos,
+ const wxSize& size,
+ const wxArrayString& choices,
+ long style,
+ const wxValidator& validator,
+ const wxString& name)
+{
+ if ( !Create( parent, id, value, pos, size, 0, NULL,
+ style, validator, name ) )
+ return false;
+
+ Append(choices);
+
+ return true;
+}
+
+bool wxComboBox::Create(wxWindow *parent,
+ wxWindowID id,
+ const wxString& value,
+ const wxPoint& pos,
+ const wxSize& size,
+ int n,
+ const wxString choices[],
+ long style,
+ const wxValidator& validator,
+ const wxString& name)
+{
+ if ( !wxControl::Create(parent, id, wxDefaultPosition, wxDefaultSize, style ,
+ validator, name) )
+ {
+ return false;
+ }
+
+ wxSize csize = size;
+ if ( style & wxCB_READONLY )
+ {
+ m_text = NULL;
+ }
+ else
+ {
+ m_text = new wxComboBoxText(this);
+ if ( size.y == -1 )
+ {
+ csize.y = m_text->GetSize().y ;
+ csize.y += 2 * TEXTFOCUSBORDER ;
+ }
+ }
+ m_choice = new wxComboBoxChoice(this, style );
+
+ DoSetSize(pos.x, pos.y, csize.x, csize.y);
+
+ Append( n, choices );
+
+ // Needed because it is a wxControlWithItems
+ SetInitialSize(size);
+ SetStringSelection(value);
+
+ return true;
+}
+
+wxString wxComboBox::GetValue() const
+{
+ wxString result;
+
+ if ( m_text == NULL )
+ result = m_choice->GetString( m_choice->GetSelection() );
+ else
+ result = m_text->GetValue();
+
+ return result;
+}
+
+unsigned int wxComboBox::GetCount() const
+{
+ return m_choice->GetCount() ;
+}
+
+void wxComboBox::SetValue(const wxString& value)
+{
+ if ( HasFlag(wxCB_READONLY) )
+ SetStringSelection( value ) ;
+ else
+ m_text->SetValue( value );
+}
+
+void wxComboBox::WriteText(const wxString& text)
+{
+ m_text->WriteText(text);
+}
+
+void wxComboBox::GetSelection(long *from, long *to) const
+{
+ m_text->GetSelection(from, to);
+}
+
+// Clipboard operations
+
+void wxComboBox::Copy()
+{
+ if ( m_text != NULL )
+ m_text->Copy();
+}
+
+void wxComboBox::Cut()
+{
+ if ( m_text != NULL )
+ m_text->Cut();
+}
+
+void wxComboBox::Paste()
+{
+ if ( m_text != NULL )
+ m_text->Paste();
+}
+
+void wxComboBox::SetEditable(bool editable)
+{
+ if ( ( m_text == NULL ) && editable )
+ {
+ m_text = new wxComboBoxText( this );
+ }
+ else if ( ( m_text != NULL ) && !editable )
+ {
+ delete m_text;
+ m_text = NULL;
+ }
+
+ int currentX, currentY;
+ GetPosition( ¤tX, ¤tY );
+
+ int currentW, currentH;
+ GetSize( ¤tW, ¤tH );
+
+ DoMoveWindow( currentX, currentY, currentW, currentH );
+}
+
+void wxComboBox::SetInsertionPoint(long pos)
+{
+ if ( m_text )
+ m_text->SetInsertionPoint(pos);
+}
+
+void wxComboBox::SetInsertionPointEnd()
+{
+ if ( m_text )
+ m_text->SetInsertionPointEnd();
+}
+
+long wxComboBox::GetInsertionPoint() const
+{
+ if ( m_text )
+ return m_text->GetInsertionPoint();
+ return 0;
+}
+
+wxTextPos wxComboBox::GetLastPosition() const
+{
+ if ( m_text )
+ return m_text->GetLastPosition();
+ return 0;
+}
+
+void wxComboBox::Replace(long from, long to, const wxString& value)
+{
+ if ( m_text )
+ m_text->Replace(from,to,value);
+}
+
+void wxComboBox::Remove(long from, long to)
+{
+ if ( m_text )
+ m_text->Remove(from,to);
+}
+
+void wxComboBox::SetSelection(long from, long to)
+{
+ if ( m_text )
+ m_text->SetSelection(from,to);
+}
+
+int wxComboBox::DoInsertItems(const wxArrayStringsAdapter& items,
+ unsigned int pos,
+ void **clientData,
+ wxClientDataType type)
+{
+ return m_choice->DoInsertItems(items, pos, clientData, type);
+}
+
+void wxComboBox::DoSetItemClientData(unsigned int n, void* clientData)
+{
+ return m_choice->DoSetItemClientData( n , clientData ) ;
+}
+
+void* wxComboBox::DoGetItemClientData(unsigned int n) const
+{
+ return m_choice->DoGetItemClientData( n ) ;
+}
+
+wxClientDataType wxComboBox::GetClientDataType() const
+{
+ return m_choice->GetClientDataType();
+}
+
+void wxComboBox::SetClientDataType(wxClientDataType clientDataItemsType)
+{
+ m_choice->SetClientDataType(clientDataItemsType);
+}
+
+void wxComboBox::DoDeleteOneItem(unsigned int n)
+{
+ m_choice->DoDeleteOneItem( n );
+}
+
+void wxComboBox::DoClear()
+{
+ m_choice->DoClear();
+}
+
+int wxComboBox::GetSelection() const
+{
+ return m_choice->GetSelection();
+}
+
+void wxComboBox::SetSelection(int n)
+{
+ m_choice->SetSelection( n );
+
+ if ( m_text != NULL )
+ m_text->SetValue(n != wxNOT_FOUND ? GetString(n) : wxString(wxEmptyString));
+}
+
+int wxComboBox::FindString(const wxString& s, bool bCase) const
+{
+ return m_choice->FindString( s, bCase );
+}
+
+wxString wxComboBox::GetString(unsigned int n) const
+{
+ return m_choice->GetString( n );
+}
+
+wxString wxComboBox::GetStringSelection() const
+{
+ int sel = GetSelection();
+ if (sel != wxNOT_FOUND)
+ return wxString(this->GetString((unsigned int)sel));
+ else
+ return wxEmptyString;
+}
+
+void wxComboBox::SetString(unsigned int n, const wxString& s)
+{
+ m_choice->SetString( n , s );
+}
+
+bool wxComboBox::IsEditable() const
+{
+ return m_text != NULL && !HasFlag(wxCB_READONLY);
+}
+
+void wxComboBox::Undo()
+{
+ if (m_text != NULL)
+ m_text->Undo();
+}
+
+void wxComboBox::Redo()
+{
+ if (m_text != NULL)
+ m_text->Redo();
+}
+
+void wxComboBox::SelectAll()
+{
+ if (m_text != NULL)
+ m_text->SelectAll();
+}
+
+bool wxComboBox::CanCopy() const
+{
+ if (m_text != NULL)
+ return m_text->CanCopy();
+ else
+ return false;
+}
+
+bool wxComboBox::CanCut() const
+{
+ if (m_text != NULL)
+ return m_text->CanCut();
+ else
+ return false;
+}
+
+bool wxComboBox::CanPaste() const
+{
+ if (m_text != NULL)
+ return m_text->CanPaste();
+ else
+ return false;
+}
+
+bool wxComboBox::CanUndo() const
+{
+ if (m_text != NULL)
+ return m_text->CanUndo();
+ else
+ return false;
+}
+
+bool wxComboBox::CanRedo() const
+{
+ if (m_text != NULL)
+ return m_text->CanRedo();
+ else
+ return false;
+}
+
+wxInt32 wxComboBox::MacControlHit( WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) )
+{
+/*
+ For consistency with other platforms, clicking in the text area does not constitute a selection
+ wxCommandEvent event(wxEVT_COMMAND_COMBOBOX_SELECTED, m_windowId );
+ event.SetInt(GetSelection());
+ event.SetEventObject(this);
+ event.SetString(GetStringSelection());
+ ProcessCommand(event);
+*/
+
+ return noErr ;
+}
+
+#endif // wxUSE_COMBOBOX
diff --git a/src/osx/carbon/combobxc.cpp b/src/osx/carbon/combobxc.cpp
new file mode 100644
index 0000000000..c494f9fada
--- /dev/null
+++ b/src/osx/carbon/combobxc.cpp
@@ -0,0 +1,793 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/combobxc.cpp
+// Purpose: wxComboBox class using HIView ComboBox
+// Author: Stefan Csomor
+// Modified by:
+// Created: 1998-01-01
+// RCS-ID: $Id$
+// Copyright: (c) Stefan Csomor
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/wxprec.h"
+
+#include "wx/combobox.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/button.h"
+ #include "wx/menu.h"
+#endif
+
+#include "wx/mac/uma.h"
+#if TARGET_API_MAC_OSX
+#ifndef __HIVIEW__
+ #include
+#endif
+#endif
+
+IMPLEMENT_DYNAMIC_CLASS(wxComboBox, wxControl)
+
+#if TARGET_API_MAC_OSX
+#define USE_HICOMBOBOX 1 //use hi combobox define
+#else
+#define USE_HICOMBOBOX 0
+#endif
+
+static int nextPopUpMenuId = 1000;
+MenuHandle NewUniqueMenu()
+{
+ MenuHandle handle = NewMenu( nextPopUpMenuId , "\pMenu" );
+ nextPopUpMenuId++;
+ return handle;
+}
+
+#if USE_HICOMBOBOX
+static const EventTypeSpec eventList[] =
+{
+ { kEventClassTextField , kEventTextAccepted } ,
+};
+
+static pascal OSStatus wxMacComboBoxEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
+{
+ OSStatus result = eventNotHandledErr;
+ wxComboBox* cb = (wxComboBox*) data;
+
+ wxMacCarbonEvent cEvent( event );
+
+ switch( cEvent.GetClass() )
+ {
+ case kEventClassTextField :
+ switch( cEvent.GetKind() )
+ {
+ case kEventTextAccepted :
+ {
+ wxCommandEvent event( wxEVT_COMMAND_COMBOBOX_SELECTED, cb->GetId() );
+ event.SetInt( cb->GetSelection() );
+ event.SetString( cb->GetStringSelection() );
+ event.SetEventObject( cb );
+ cb->HandleWindowEvent( event );
+ }
+ break;
+ default :
+ break;
+ }
+ break;
+ default :
+ break;
+ }
+
+
+ return result;
+}
+
+DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacComboBoxEventHandler )
+
+#endif
+
+// ----------------------------------------------------------------------------
+// constants
+// ----------------------------------------------------------------------------
+
+// the margin between the text control and the choice
+static const wxCoord MARGIN = 2;
+#if TARGET_API_MAC_OSX
+static const int POPUPWIDTH = 24;
+#else
+static const int POPUPWIDTH = 18;
+#endif
+static const int POPUPHEIGHT = 23;
+
+// ----------------------------------------------------------------------------
+// wxComboBoxText: text control forwards events to combobox
+// ----------------------------------------------------------------------------
+
+class wxComboBoxText : public wxTextCtrl
+{
+public:
+ wxComboBoxText( wxComboBox * cb )
+ : wxTextCtrl( cb , 1 )
+ {
+ m_cb = cb;
+ }
+
+protected:
+ void OnChar( wxKeyEvent& event )
+ {
+ if ( event.GetKeyCode() == WXK_RETURN )
+ {
+ wxString value = GetValue();
+
+ if ( m_cb->GetCount() == 0 )
+ {
+ // make Enter generate "selected" event if there is only one item
+ // in the combobox - without it, it's impossible to select it at
+ // all!
+ wxCommandEvent event( wxEVT_COMMAND_COMBOBOX_SELECTED, m_cb->GetId() );
+ event.SetInt( 0 );
+ event.SetString( value );
+ event.SetEventObject( m_cb );
+ m_cb->HandleWindowEvent( event );
+ }
+ else
+ {
+ // add the item to the list if it's not there yet
+ if ( m_cb->FindString(value) == wxNOT_FOUND )
+ {
+ m_cb->Append(value);
+ m_cb->SetStringSelection(value);
+
+ // and generate the selected event for it
+ wxCommandEvent event( wxEVT_COMMAND_COMBOBOX_SELECTED, m_cb->GetId() );
+ event.SetInt( m_cb->GetCount() - 1 );
+ event.SetString( value );
+ event.SetEventObject( m_cb );
+ m_cb->HandleWindowEvent( event );
+ }
+
+ // This will invoke the dialog default action, such
+ // as the clicking the default button.
+
+ wxTopLevelWindow *tlw = wxDynamicCast(wxGetTopLevelParent(this), wxTopLevelWindow);
+ if ( tlw && tlw->GetDefaultItem() )
+ {
+ wxButton *def = wxDynamicCast(tlw->GetDefaultItem(), wxButton);
+ if ( def && def->IsEnabled() )
+ {
+ wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, def->GetId() );
+ event.SetEventObject(def);
+ def->Command(event);
+ return;
+ }
+ }
+
+ return;
+ }
+ }
+
+ event.Skip();
+ }
+private:
+ wxComboBox *m_cb;
+
+ DECLARE_EVENT_TABLE()
+};
+
+BEGIN_EVENT_TABLE(wxComboBoxText, wxTextCtrl)
+ EVT_CHAR( wxComboBoxText::OnChar)
+END_EVENT_TABLE()
+
+class wxComboBoxChoice : public wxChoice
+{
+public:
+ wxComboBoxChoice(wxComboBox *cb, int style)
+ : wxChoice( cb , 1 )
+ {
+ m_cb = cb;
+ }
+
+protected:
+ void OnChoice( wxCommandEvent& e )
+ {
+ wxString s = e.GetString();
+
+ m_cb->DelegateChoice( s );
+ wxCommandEvent event2(wxEVT_COMMAND_COMBOBOX_SELECTED, m_cb->GetId() );
+ event2.SetInt(m_cb->GetSelection());
+ event2.SetEventObject(m_cb);
+ event2.SetString(m_cb->GetStringSelection());
+ m_cb->ProcessCommand(event2);
+ }
+ virtual wxSize DoGetBestSize() const
+ {
+ wxSize sz = wxChoice::DoGetBestSize();
+ sz.x = POPUPWIDTH;
+ return sz;
+ }
+
+private:
+ wxComboBox *m_cb;
+
+ DECLARE_EVENT_TABLE()
+};
+
+BEGIN_EVENT_TABLE(wxComboBoxChoice, wxChoice)
+ EVT_CHOICE(wxID_ANY, wxComboBoxChoice::OnChoice)
+END_EVENT_TABLE()
+
+wxComboBox::~wxComboBox()
+{
+ // delete the controls now, don't leave them alive even though they would
+ // still be eventually deleted by our parent - but it will be too late, the
+ // user code expects them to be gone now
+ if (m_text != NULL) {
+ delete m_text;
+ m_text = NULL;
+ }
+ if (m_choice != NULL) {
+ delete m_choice;
+ m_choice = NULL;
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// geometry
+// ----------------------------------------------------------------------------
+
+wxSize wxComboBox::DoGetBestSize() const
+{
+#if USE_HICOMBOBOX
+ return wxControl::DoGetBestSize();
+#else
+ wxSize size = m_choice->GetBestSize();
+
+ if ( m_text != NULL )
+ {
+ wxSize sizeText = m_text->GetBestSize();
+
+ size.x = POPUPWIDTH + sizeText.x + MARGIN;
+ }
+
+ return size;
+#endif
+}
+
+void wxComboBox::DoMoveWindow(int x, int y, int width, int height) {
+#if USE_HICOMBOBOX
+ wxControl::DoMoveWindow(x, y, width, height);
+#else
+ height = POPUPHEIGHT;
+
+ wxControl::DoMoveWindow(x, y, width, height);
+
+ if ( m_text == NULL )
+ {
+ // we might not be fully constructed yet, therefore watch out...
+ if ( m_choice )
+ m_choice->SetSize(0, 0 , width, wxDefaultCoord);
+ }
+ else
+ {
+ wxCoord wText = width - POPUPWIDTH - MARGIN;
+ m_text->SetSize(0, 0, wText, height);
+ m_choice->SetSize(0 + wText + MARGIN, 0, POPUPWIDTH, wxDefaultCoord);
+ }
+#endif
+}
+
+
+
+// ----------------------------------------------------------------------------
+// operations forwarded to the subcontrols
+// ----------------------------------------------------------------------------
+
+bool wxComboBox::Enable(bool enable)
+{
+ if ( !wxControl::Enable(enable) )
+ return false;
+
+ return true;
+}
+
+bool wxComboBox::Show(bool show)
+{
+ if ( !wxControl::Show(show) )
+ return false;
+
+ return true;
+}
+
+void wxComboBox::SetFocus()
+{
+#if USE_HICOMBOBOX
+ wxControl::SetFocus();
+#else
+ if ( m_text != NULL) {
+ m_text->SetFocus();
+ }
+#endif
+}
+
+
+void wxComboBox::DelegateTextChanged( const wxString& value )
+{
+ SetStringSelection( value );
+}
+
+
+void wxComboBox::DelegateChoice( const wxString& value )
+{
+ SetStringSelection( value );
+}
+
+
+bool wxComboBox::Create(wxWindow *parent, wxWindowID id,
+ const wxString& value,
+ const wxPoint& pos,
+ const wxSize& size,
+ const wxArrayString& choices,
+ long style,
+ const wxValidator& validator,
+ const wxString& name)
+{
+ wxCArrayString chs( choices );
+
+ return Create( parent, id, value, pos, size, chs.GetCount(),
+ chs.GetStrings(), style, validator, name );
+}
+
+
+bool wxComboBox::Create(wxWindow *parent, wxWindowID id,
+ const wxString& value,
+ const wxPoint& pos,
+ const wxSize& size,
+ int n, const wxString choices[],
+ long style,
+ const wxValidator& validator,
+ const wxString& name)
+{
+ m_text = NULL;
+ m_choice = NULL;
+#if USE_HICOMBOBOX
+ m_macIsUserPane = false;
+#endif
+ if ( !wxControl::Create(parent, id, wxDefaultPosition, wxDefaultSize, style ,
+ wxDefaultValidator, name) )
+ {
+ return false;
+ }
+#if USE_HICOMBOBOX
+ Rect bounds = wxMacGetBoundsForControl( this , pos , size );
+ HIRect hiRect;
+
+ hiRect.origin.x = 20; //bounds.left;
+ hiRect.origin.y = 25; //bounds.top;
+ hiRect.size.width = 120;// bounds.right - bounds.left;
+ hiRect.size.height = 24;
+
+ //For some reason, this code causes the combo box not to be displayed at all.
+ //hiRect.origin.x = bounds.left;
+ //hiRect.origin.y = bounds.top;
+ //hiRect.size.width = bounds.right - bounds.left;
+ //hiRect.size.height = bounds.bottom - bounds.top;
+ //printf("left = %d, right = %d, top = %d, bottom = %d\n", bounds.left, bounds.right, bounds.top, bounds.bottom);
+ //printf("x = %d, y = %d, width = %d, height = %d\n", hibounds.origin.x, hibounds.origin.y, hibounds.size.width, hibounds.size.height);
+ m_peer = new wxMacControl(this);
+ verify_noerr( HIComboBoxCreate( &hiRect, CFSTR(""), NULL, NULL, kHIComboBoxStandardAttributes, m_peer->GetControlRefAddr() ) );
+
+
+ m_peer->SetMinimum( 0 );
+ m_peer->SetMaximum( 100);
+ if ( n > 0 )
+ m_peer->SetValue( 1 );
+
+ MacPostControlCreate(pos,size);
+
+ Append( choices[ i ] );
+
+ HIViewSetVisible( m_peer->GetControlRef(), true );
+ SetSelection(0);
+ EventHandlerRef comboEventHandler;
+ InstallControlEventHandler( m_peer->GetControlRef(), GetwxMacComboBoxEventHandlerUPP(),
+ GetEventTypeCount(eventList), eventList, this,
+ (EventHandlerRef *)&comboEventHandler);
+#else
+ m_choice = new wxComboBoxChoice(this, style );
+ m_choice->SetMinSize( wxSize( POPUPWIDTH , POPUPHEIGHT ) );
+
+ wxSize csize = size;
+ if ( style & wxCB_READONLY )
+ {
+ m_text = NULL;
+ }
+ else
+ {
+ m_text = new wxComboBoxText(this);
+ if ( size.y == wxDefaultCoord ) {
+ csize.y = m_text->GetSize().y;
+ }
+ }
+
+ DoSetSize(pos.x, pos.y, csize.x, csize.y);
+
+ m_choice->Append( n, choices );
+ SetInitialSize(csize); // Needed because it is a wxControlWithItems
+#endif
+
+ return true;
+}
+
+wxString wxComboBox::GetValue() const
+{
+#if USE_HICOMBOBOX
+ CFStringRef myString;
+ HIComboBoxCopyTextItemAtIndex( m_peer->GetControlRef(), (CFIndex)GetSelection(), &myString );
+ return wxMacCFStringHolder( myString, GetFont().GetEncoding() ).AsString();
+#else
+ wxString result;
+
+ if ( m_text == NULL )
+ {
+ result = m_choice->GetString( m_choice->GetSelection() );
+ }
+ else
+ {
+ result = m_text->GetValue();
+ }
+
+ return result;
+#endif
+}
+
+void wxComboBox::SetValue(const wxString& value)
+{
+#if USE_HICOMBOBOX
+
+#else
+ int s = FindString (value);
+ if (s == wxNOT_FOUND && !HasFlag(wxCB_READONLY) )
+ {
+ m_choice->Append(value);
+ }
+ SetStringSelection( value );
+#endif
+}
+
+// Clipboard operations
+void wxComboBox::Copy()
+{
+ if ( m_text != NULL )
+ {
+ m_text->Copy();
+ }
+}
+
+void wxComboBox::Cut()
+{
+ if ( m_text != NULL )
+ {
+ m_text->Cut();
+ }
+}
+
+void wxComboBox::Paste()
+{
+ if ( m_text != NULL )
+ {
+ m_text->Paste();
+ }
+}
+
+void wxComboBox::SetEditable(bool editable)
+{
+ if ( ( m_text == NULL ) && editable )
+ {
+ m_text = new wxComboBoxText( this );
+ }
+ else if ( ( m_text != NULL ) && !editable )
+ {
+ delete m_text;
+ m_text = NULL;
+ }
+
+ int currentX, currentY;
+ GetPosition( ¤tX, ¤tY );
+
+ int currentW, currentH;
+ GetSize( ¤tW, ¤tH );
+
+ DoMoveWindow( currentX, currentY, currentW, currentH );
+}
+
+void wxComboBox::SetInsertionPoint(long pos)
+{
+ // TODO
+}
+
+void wxComboBox::SetInsertionPointEnd()
+{
+ // TODO
+}
+
+long wxComboBox::GetInsertionPoint() const
+{
+ // TODO
+ return 0;
+}
+
+wxTextPos wxComboBox::GetLastPosition() const
+{
+ // TODO
+ return 0;
+}
+
+void wxComboBox::Replace(long from, long to, const wxString& value)
+{
+ // TODO
+}
+
+void wxComboBox::Remove(long from, long to)
+{
+ // TODO
+}
+
+void wxComboBox::SetSelection(long from, long to)
+{
+ // TODO
+}
+
+int wxComboBox::DoInsertItems(const wxArrayStringsAdapter& items,
+ unsigned int pos,
+ void **clientData, wxClientDataType type)
+{
+#if USE_HICOMBOBOX
+ const unsigned int count = items.GetCount();
+ for ( unsigned int i = 0; i < count; ++i, ++pos )
+ {
+ HIComboBoxInsertTextItemAtIndex(m_peer->GetControlRef(),
+ (CFIndex)pos,
+ wxMacCFStringHolder(items[i],
+ GetFont().GetEncoding()));
+ AssignNewItemClientData(pos, clientData, i, type);
+ }
+
+ //SetControl32BitMaximum( m_peer->GetControlRef(), GetCount() );
+
+ return pos - 1;
+#else
+ return m_choice->DoInsertItems( items, pos, clientData, type );
+#endif
+}
+
+void wxComboBox::DoSetItemClientData(unsigned int n, void* clientData)
+{
+#if USE_HICOMBOBOX
+ return; //TODO
+#else
+ return m_choice->DoSetItemClientData( n , clientData );
+#endif
+}
+
+void* wxComboBox::DoGetItemClientData(unsigned int n) const
+{
+#if USE_HICOMBOBOX
+ return NULL; //TODO
+#else
+ return m_choice->DoGetItemClientData( n );
+#endif
+}
+
+unsigned int wxComboBox::GetCount() const {
+#if USE_HICOMBOBOX
+ return (unsigned int) HIComboBoxGetItemCount( m_peer->GetControlRef() );
+#else
+ return m_choice->GetCount();
+#endif
+}
+
+void wxComboBox::DoDeleteOneItem(unsigned int n)
+{
+#if USE_HICOMBOBOX
+ HIComboBoxRemoveItemAtIndex( m_peer->GetControlRef(), (CFIndex)n );
+#else
+ m_choice->Delete( n );
+#endif
+}
+
+void wxComboBox::DoClear()
+{
+#if USE_HICOMBOBOX
+ for ( CFIndex i = GetCount() - 1; i >= 0; ++ i )
+ verify_noerr( HIComboBoxRemoveItemAtIndex( m_peer->GetControlRef(), i ) );
+ m_peer->SetData(kHIComboBoxEditTextPart,kControlEditTextCFStringTag,CFSTR(""));
+#else
+ m_choice->Clear();
+#endif
+}
+
+int wxComboBox::GetSelection() const
+{
+#if USE_HICOMBOBOX
+ return FindString( GetStringSelection() );
+#else
+ return m_choice->GetSelection();
+#endif
+}
+
+void wxComboBox::SetSelection(int n)
+{
+#if USE_HICOMBOBOX
+ SetControl32BitValue( m_peer->GetControlRef() , n + 1 );
+#else
+ m_choice->SetSelection( n );
+
+ if ( m_text != NULL )
+ {
+ m_text->SetValue(GetString(n));
+ }
+#endif
+}
+
+int wxComboBox::FindString(const wxString& s, bool bCase) const
+{
+#if USE_HICOMBOBOX
+ for( unsigned int i = 0 ; i < GetCount() ; i++ )
+ {
+ if (GetString(i).IsSameAs(s, bCase) )
+ return i ;
+ }
+ return wxNOT_FOUND;
+#else
+ return m_choice->FindString( s, bCase );
+#endif
+}
+
+wxString wxComboBox::GetString(unsigned int n) const
+{
+#if USE_HICOMBOBOX
+ CFStringRef itemText;
+ HIComboBoxCopyTextItemAtIndex( m_peer->GetControlRef(), (CFIndex)n, &itemText );
+ return wxMacCFStringHolder(itemText).AsString();
+#else
+ return m_choice->GetString( n );
+#endif
+}
+
+wxString wxComboBox::GetStringSelection() const
+{
+#if USE_HICOMBOBOX
+ return wxMacCFStringHolder(m_peer->GetData(kHIComboBoxEditTextPart,kControlEditTextCFStringTag)).AsString();
+#else
+ int sel = GetSelection ();
+ if (sel != wxNOT_FOUND)
+ return wxString(this->GetString((unsigned int)sel));
+ else
+ return wxEmptyString;
+#endif
+}
+
+void wxComboBox::SetString(unsigned int n, const wxString& s)
+{
+#if USE_HICOMBOBOX
+ verify_noerr ( HIComboBoxInsertTextItemAtIndex( m_peer->GetControlRef(), (CFIndex) n,
+ wxMacCFStringHolder(s, GetFont().GetEncoding()) ) );
+ verify_noerr ( HIComboBoxRemoveItemAtIndex( m_peer->GetControlRef(), (CFIndex) n + 1 ) );
+#else
+ m_choice->SetString( n , s );
+#endif
+}
+
+bool wxComboBox::IsEditable() const
+{
+#if USE_HICOMBOBOX
+ // TODO
+ return !HasFlag(wxCB_READONLY);
+#else
+ return m_text != NULL && !HasFlag(wxCB_READONLY);
+#endif
+}
+
+void wxComboBox::Undo()
+{
+#if USE_HICOMBOBOX
+ // TODO
+#else
+ if (m_text != NULL)
+ m_text->Undo();
+#endif
+}
+
+void wxComboBox::Redo()
+{
+#if USE_HICOMBOBOX
+ // TODO
+#else
+ if (m_text != NULL)
+ m_text->Redo();
+#endif
+}
+
+void wxComboBox::SelectAll()
+{
+#if USE_HICOMBOBOX
+ // TODO
+#else
+ if (m_text != NULL)
+ m_text->SelectAll();
+#endif
+}
+
+bool wxComboBox::CanCopy() const
+{
+#if USE_HICOMBOBOX
+ // TODO
+ return false;
+#else
+ if (m_text != NULL)
+ return m_text->CanCopy();
+ else
+ return false;
+#endif
+}
+
+bool wxComboBox::CanCut() const
+{
+#if USE_HICOMBOBOX
+ // TODO
+ return false;
+#else
+ if (m_text != NULL)
+ return m_text->CanCut();
+ else
+ return false;
+#endif
+}
+
+bool wxComboBox::CanPaste() const
+{
+#if USE_HICOMBOBOX
+ // TODO
+ return false;
+#else
+ if (m_text != NULL)
+ return m_text->CanPaste();
+ else
+ return false;
+#endif
+}
+
+bool wxComboBox::CanUndo() const
+{
+#if USE_HICOMBOBOX
+ // TODO
+ return false;
+#else
+ if (m_text != NULL)
+ return m_text->CanUndo();
+ else
+ return false;
+#endif
+}
+
+bool wxComboBox::CanRedo() const
+{
+#if USE_HICOMBOBOX
+ // TODO
+ return false;
+#else
+ if (m_text != NULL)
+ return m_text->CanRedo();
+ else
+ return false;
+#endif
+}
+
+wxInt32 wxComboBox::MacControlHit(WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) )
+{
+ wxCommandEvent event(wxEVT_COMMAND_COMBOBOX_SELECTED, m_windowId );
+ event.SetInt(GetSelection());
+ event.SetEventObject(this);
+ event.SetString(GetStringSelection());
+ ProcessCommand(event);
+ return noErr;
+}
diff --git a/src/osx/carbon/control.cpp b/src/osx/carbon/control.cpp
new file mode 100644
index 0000000000..f787ea9812
--- /dev/null
+++ b/src/osx/carbon/control.cpp
@@ -0,0 +1,97 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/control.cpp
+// Purpose: wxControl class
+// Author: Stefan Csomor
+// Modified by:
+// Created: 1998-01-01
+// RCS-ID: $Id$
+// Copyright: (c) Stefan Csomor
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/wxprec.h"
+
+#include "wx/control.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/app.h"
+ #include "wx/panel.h"
+ #include "wx/dc.h"
+ #include "wx/dcclient.h"
+ #include "wx/button.h"
+ #include "wx/dialog.h"
+ #include "wx/scrolbar.h"
+ #include "wx/stattext.h"
+ #include "wx/statbox.h"
+ #include "wx/radiobox.h"
+ #include "wx/sizer.h"
+#endif // WX_PRECOMP
+
+#include "wx/notebook.h"
+#include "wx/tabctrl.h"
+#include "wx/spinbutt.h"
+
+#include "wx/mac/uma.h"
+#include "wx/mac/private.h"
+
+IMPLEMENT_ABSTRACT_CLASS(wxControl, wxWindow)
+
+
+wxControl::wxControl()
+{
+}
+
+bool wxControl::Create( wxWindow *parent,
+ wxWindowID id,
+ const wxPoint& pos,
+ const wxSize& size,
+ long style,
+ const wxValidator& validator,
+ const wxString& name )
+{
+ bool rval = wxWindow::Create( parent, id, pos, size, style, name );
+
+#if 0
+ // no automatic inheritance as we most often need transparent backgrounds
+ if ( parent )
+ {
+ m_backgroundColour = parent->GetBackgroundColour();
+ m_foregroundColour = parent->GetForegroundColour();
+ }
+#endif
+
+#if wxUSE_VALIDATORS
+ if (rval)
+ SetValidator( validator );
+#endif
+
+ return rval;
+}
+
+wxControl::~wxControl()
+{
+ m_isBeingDeleted = true;
+}
+
+bool wxControl::ProcessCommand( wxCommandEvent &event )
+{
+ // Tries:
+ // 1) OnCommand, starting at this window and working up parent hierarchy
+ // 2) OnCommand then calls ProcessEvent to search the event tables.
+ return HandleWindowEvent( event );
+}
+
+void wxControl::OnKeyDown( wxKeyEvent &WXUNUSED(event) )
+{
+ if ( m_peer == NULL || !m_peer->Ok() )
+ return;
+
+ UInt32 keyCode, modifiers;
+ char charCode;
+
+ GetEventParameter( (EventRef)wxTheApp->MacGetCurrentEvent(), kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode );
+ GetEventParameter( (EventRef)wxTheApp->MacGetCurrentEvent(), kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &charCode );
+ GetEventParameter( (EventRef)wxTheApp->MacGetCurrentEvent(), kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers );
+
+ m_peer->HandleKey( keyCode, charCode, modifiers );
+}
diff --git a/src/osx/carbon/corersrc.r b/src/osx/carbon/corersrc.r
new file mode 100644
index 0000000000..676a4d3d2a
--- /dev/null
+++ b/src/osx/carbon/corersrc.r
@@ -0,0 +1,159 @@
+#ifdef __UNIX__
+ #include
+#else
+ #include
+ #if UNIVERSAL_INTERFACES_VERSION > 0x320
+ #include
+ #endif
+#endif
+
+resource 'ldes' ( 128 )
+{
+ versionZero
+ {
+ 0 ,
+ 0 ,
+ 0 ,
+ 0 ,
+ hasVertScroll ,
+ noHorizScroll ,
+ 0 ,
+ noGrowSpace ,
+ }
+} ;
+
+resource 'ldes' ( 129 )
+{
+ versionZero
+ {
+ 0 ,
+ 0 ,
+ 0 ,
+ 0 ,
+ hasVertScroll ,
+ hasHorizScroll ,
+ 0 ,
+ noGrowSpace ,
+ }
+} ;
+
+data 'CURS' (10) {
+ $"0000 03E0 0630 0808 1004 31C6 2362 2222"
+ $"2362 31C6 1004 0808 0630 03E0 0000 0000"
+ $"0000 03E0 07F0 0FF8 1FFC 3FFE 3FFE 3FFE"
+ $"3FFE 3FFE 1FFC 0FF8 07F0 03E0 0000 0000"
+ $"0007 0008"
+};
+
+data 'CURS' (11) {
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0000 0000"
+};
+
+data 'CURS' (12) {
+ $"00F0 0088 0108 0190 0270 0220 0440 0440"
+ $"0880 0880 1100 1E00 1C00 1800 1000 0000"
+ $"00F0 00F8 01F8 01F0 03F0 03E0 07C0 07C0"
+ $"0F80 0F80 1F00 1E00 1C00 1800 1000 0000"
+ $"000E 0003"
+};
+
+data 'CURS' (13) {
+ $"0000 1E00 2100 4080 4080 4080 4080 2180"
+ $"1FC0 00E0 0070 0038 001C 000E 0006 0000"
+ $"3F00 7F80 FFC0 FFC0 FFC0 FFC0 FFC0 7FC0"
+ $"3FE0 1FF0 00F8 007C 003E 001F 000F 0007"
+ $"0004 0004"
+};
+
+data 'CURS' (14) {
+ $"0000 07E0 1FF0 3838 3C0C 6E0E 6706 6386"
+ $"61C6 60E6 7076 303C 1C1C 0FF8 07E0 0000"
+ $"0540 0FF0 3FF8 3C3C 7E0E FF0F 6F86 E7C7"
+ $"63E6 E1F7 70FE 707E 3C3C 1FFC 0FF0 0540"
+ $"0007 0007"
+};
+
+data 'CURS' (15) {
+ $"0000 0380 0380 0380 0380 0380 0380 0FE0"
+ $"1FF0 1FF0 0000 1FF0 1FF0 1550 1550 1550"
+ $"07C0 07C0 07C0 07C0 07C0 07C0 0FE0 1FF0"
+ $"3FF8 3FF8 3FF8 3FF8 3FF8 3FF8 3FF8 3FF8"
+ $"000B 0007"
+};
+
+data 'CURS' (16) {
+ $"00C0 0140 0640 08C0 3180 47FE 8001 8001"
+ $"81FE 8040 01C0 0040 03C0 C080 3F80 0000"
+ $"00C0 01C0 07C0 0FC0 3F80 7FFE FFFF FFFF"
+ $"FFFE FFC0 FFC0 FFC0 FFC0 FF80 3F80 0000"
+ $"0006 000F"
+};
+
+data 'CURS' (17) {
+ $"0100 0280 0260 0310 018C 7FE3 8000 8000"
+ $"7F80 0200 0380 0200 03C0 0107 01F8 0000"
+ $"0100 0380 03E0 03F0 01FC 7FFF FFFF FFFF"
+ $"FFFF 03FF 03FF 03FF 03FF 01FF 01F8 0000"
+ $"0006 0000"
+};
+
+data 'CURS' (18) {
+ $"0000 4078 60FC 71CE 7986 7C06 7E0E 7F1C"
+ $"7FB8 7C30 6C30 4600 0630 0330 0300 0000"
+ $"C078 E0FC F1FE FBFF FFCF FF8F FF1F FFBE"
+ $"FFFC FE78 FF78 EFF8 CFF8 87F8 07F8 0300"
+ $"0001 0001"
+};
+
+data 'CURS' (19) {
+ $"0000 0002 0006 000E 001E 003E 007E 00FE"
+ $"01FE 003E 0036 0062 0060 00C0 00C0 0000"
+ $"0003 0007 000F 001F 003F 007F 00FF 01FF"
+ $"03FF 07FF 007F 00F7 00F3 01E1 01E0 01C0"
+ $"0001 000E"
+};
+
+data 'CURS' (20) {
+ $"0000 0080 01C0 03E0 0080 0080 0080 1FFC"
+ $"1FFC 0080 0080 0080 03E0 01C0 0080 0000"
+ $"0080 01C0 03E0 07F0 0FF8 01C0 3FFE 3FFE"
+ $"3FFE 3FFE 01C0 0FF8 07F0 03E0 01C0 0080"
+ $"0007 0008"
+};
+
+data 'CURS' (21) {
+ $"0000 0080 01C0 03E0 0080 0888 188C 3FFE"
+ $"188C 0888 0080 03E0 01C0 0080 0000 0000"
+ $"0080 01C0 03E0 07F0 0BE8 1DDC 3FFE 7FFF"
+ $"3FFE 1DDC 0BE8 07F0 03E0 01C0 0080 0000"
+ $"0007 0008"
+};
+
+data 'CURS' (22) {
+ $"0000 001E 000E 060E 0712 03A0 01C0 00E0"
+ $"0170 1238 1C18 1C00 1E00 0000 0000 0000"
+ $"007F 003F 0E1F 0F0F 0F97 07E3 03E1 21F0"
+ $"31F8 3A7C 3C3C 3E1C 3F00 3F80 0000 0000"
+ $"0006 0009"
+};
+
+data 'CURS' (23) {
+ $"0000 7800 7000 7060 48E0 05C0 0380 0700"
+ $"0E80 1C48 1838 0038 0078 0000 0000 0000"
+ $"FE00 FC00 F870 F0F0 E9F0 C7E0 87C0 0F84"
+ $"1F8C 3E5C 3C3C 387C 00FC 01FC 0000 0000"
+ $"0006 0006"
+};
+
+data 'CURS' (24) {
+ $"0006 000E 001C 0018 0020 0040 00F8 0004"
+ $"1FF4 200C 2AA8 1FF0 1F80 3800 6000 8000"
+ $"000F 001F 003E 007C 0070 00E0 01FC 3FF6"
+ $"7FF6 7FFE 7FFC 7FF8 3FF0 7FC0 F800 E000"
+ $"000A 0006"
+};
+
diff --git a/src/osx/carbon/cursor.cpp b/src/osx/carbon/cursor.cpp
new file mode 100644
index 0000000000..36e40a7de9
--- /dev/null
+++ b/src/osx/carbon/cursor.cpp
@@ -0,0 +1,697 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/cursor.cpp
+// Purpose: wxCursor class
+// Author: Stefan Csomor
+// Modified by:
+// Created: 1998-01-01
+// RCS-ID: $Id$
+// Copyright: (c) Stefan Csomor
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/wxprec.h"
+
+#include "wx/cursor.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/app.h"
+ #include "wx/icon.h"
+ #include "wx/image.h"
+#endif // WX_PRECOMP
+
+#include "wx/xpmdecod.h"
+
+#include "wx/mac/private.h"
+
+
+IMPLEMENT_DYNAMIC_CLASS(wxCursor, wxGDIObject)
+
+
+class WXDLLEXPORT wxCursorRefData: public wxGDIRefData
+{
+public:
+ wxCursorRefData();
+ wxCursorRefData(const wxCursorRefData& cursor);
+ virtual ~wxCursorRefData();
+
+ virtual bool IsOk() const
+ {
+ if ( m_hCursor != NULL )
+ return true;
+#if !wxMAC_USE_COCOA
+ if ( m_themeCursor != -1 )
+ return true;
+#endif
+
+ return false;
+ }
+
+protected:
+#if wxMAC_USE_COCOA
+ WX_NSCursor m_hCursor;
+#else
+ WXHCURSOR m_hCursor;
+ bool m_disposeHandle;
+ bool m_releaseHandle;
+ bool m_isColorCursor;
+ long m_themeCursor;
+#endif
+
+ friend class wxCursor;
+
+ DECLARE_NO_ASSIGN_CLASS(wxCursorRefData)
+};
+
+#define M_CURSORDATA wx_static_cast(wxCursorRefData*, m_refData)
+
+ClassicCursor gMacCursors[kwxCursorLast+1] =
+{
+
+{
+{0x0000, 0x03E0, 0x0630, 0x0808, 0x1004, 0x31C6, 0x2362, 0x2222,
+0x2362, 0x31C6, 0x1004, 0x0808, 0x0630, 0x03E0, 0x0000, 0x0000},
+{0x0000, 0x03E0, 0x07F0, 0x0FF8, 0x1FFC, 0x3FFE, 0x3FFE, 0x3FFE,
+0x3FFE, 0x3FFE, 0x1FFC, 0x0FF8, 0x07F0, 0x03E0, 0x0000, 0x0000},
+{0x0007, 0x0008}
+},
+
+{
+{0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
+{0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
+{0x0000, 0x0000}
+},
+
+{
+{0x00F0, 0x0088, 0x0108, 0x0190, 0x0270, 0x0220, 0x0440, 0x0440,
+0x0880, 0x0880, 0x1100, 0x1E00, 0x1C00, 0x1800, 0x1000, 0x0000},
+{0x00F0, 0x00F8, 0x01F8, 0x01F0, 0x03F0, 0x03E0, 0x07C0, 0x07C0,
+0x0F80, 0x0F80, 0x1F00, 0x1E00, 0x1C00, 0x1800, 0x1000, 0x0000},
+{0x000E, 0x0003}
+},
+
+{
+{0x0000, 0x1E00, 0x2100, 0x4080, 0x4080, 0x4080, 0x4080, 0x2180,
+0x1FC0, 0x00E0, 0x0070, 0x0038, 0x001C, 0x000E, 0x0006, 0x0000},
+{0x3F00, 0x7F80, 0xFFC0, 0xFFC0, 0xFFC0, 0xFFC0, 0xFFC0, 0x7FC0,
+0x3FE0, 0x1FF0, 0x00F8, 0x007C, 0x003E, 0x001F, 0x000F, 0x0007},
+{0x0004, 0x0004}
+},
+
+{
+{0x0000, 0x07E0, 0x1FF0, 0x3838, 0x3C0C, 0x6E0E, 0x6706, 0x6386,
+0x61C6, 0x60E6, 0x7076, 0x303C, 0x1C1C, 0x0FF8, 0x07E0, 0x0000},
+{0x0540, 0x0FF0, 0x3FF8, 0x3C3C, 0x7E0E, 0xFF0F, 0x6F86, 0xE7C7,
+0x63E6, 0xE1F7, 0x70FE, 0x707E, 0x3C3C, 0x1FFC, 0x0FF0, 0x0540},
+{0x0007, 0x0007}
+},
+
+{
+{0x0000, 0x0380, 0x0380, 0x0380, 0x0380, 0x0380, 0x0380, 0x0FE0,
+0x1FF0, 0x1FF0, 0x0000, 0x1FF0, 0x1FF0, 0x1550, 0x1550, 0x1550},
+{0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x0FE0, 0x1FF0,
+0x3FF8, 0x3FF8, 0x3FF8, 0x3FF8, 0x3FF8, 0x3FF8, 0x3FF8, 0x3FF8},
+{0x000B, 0x0007}
+},
+
+{
+{0x00C0, 0x0140, 0x0640, 0x08C0, 0x3180, 0x47FE, 0x8001, 0x8001,
+0x81FE, 0x8040, 0x01C0, 0x0040, 0x03C0, 0xC080, 0x3F80, 0x0000},
+{0x00C0, 0x01C0, 0x07C0, 0x0FC0, 0x3F80, 0x7FFE, 0xFFFF, 0xFFFF,
+0xFFFE, 0xFFC0, 0xFFC0, 0xFFC0, 0xFFC0, 0xFF80, 0x3F80, 0x0000},
+{0x0006, 0x000F}
+},
+
+{
+{0x0100, 0x0280, 0x0260, 0x0310, 0x018C, 0x7FE3, 0x8000, 0x8000,
+0x7F80, 0x0200, 0x0380, 0x0200, 0x03C0, 0x0107, 0x01F8, 0x0000},
+{0x0100, 0x0380, 0x03E0, 0x03F0, 0x01FC, 0x7FFF, 0xFFFF, 0xFFFF,
+0xFFFF, 0x03FF, 0x03FF, 0x03FF, 0x03FF, 0x01FF, 0x01F8, 0x0000},
+{0x0006, 0x0000}
+},
+
+{
+{0x0000, 0x4078, 0x60FC, 0x71CE, 0x7986, 0x7C06, 0x7E0E, 0x7F1C,
+0x7FB8, 0x7C30, 0x6C30, 0x4600, 0x0630, 0x0330, 0x0300, 0x0000},
+{0xC078, 0xE0FC, 0xF1FE, 0xFBFF, 0xFFCF, 0xFF8F, 0xFF1F, 0xFFBE,
+0xFFFC, 0xFE78, 0xFF78, 0xEFF8, 0xCFF8, 0x87F8, 0x07F8, 0x0300},
+{0x0001, 0x0001}
+},
+
+{
+{0x0000, 0x0002, 0x0006, 0x000E, 0x001E, 0x003E, 0x007E, 0x00FE,
+0x01FE, 0x003E, 0x0036, 0x0062, 0x0060, 0x00C0, 0x00C0, 0x0000},
+{0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF,
+0x03FF, 0x07FF, 0x007F, 0x00F7, 0x00F3, 0x01E1, 0x01E0, 0x01C0},
+{0x0001, 0x000E}
+},
+
+{
+{0x0000, 0x0080, 0x01C0, 0x03E0, 0x0080, 0x0080, 0x0080, 0x1FFC,
+0x1FFC, 0x0080, 0x0080, 0x0080, 0x03E0, 0x01C0, 0x0080, 0x0000},
+{0x0080, 0x01C0, 0x03E0, 0x07F0, 0x0FF8, 0x01C0, 0x3FFE, 0x3FFE,
+0x3FFE, 0x3FFE, 0x01C0, 0x0FF8, 0x07F0, 0x03E0, 0x01C0, 0x0080},
+{0x0007, 0x0008}
+},
+
+{
+{0x0000, 0x0080, 0x01C0, 0x03E0, 0x0080, 0x0888, 0x188C, 0x3FFE,
+0x188C, 0x0888, 0x0080, 0x03E0, 0x01C0, 0x0080, 0x0000, 0x0000},
+{0x0080, 0x01C0, 0x03E0, 0x07F0, 0x0BE8, 0x1DDC, 0x3FFE, 0x7FFF,
+0x3FFE, 0x1DDC, 0x0BE8, 0x07F0, 0x03E0, 0x01C0, 0x0080, 0x0000},
+{0x0007, 0x0008}
+},
+
+{
+{0x0000, 0x001E, 0x000E, 0x060E, 0x0712, 0x03A0, 0x01C0, 0x00E0,
+0x0170, 0x1238, 0x1C18, 0x1C00, 0x1E00, 0x0000, 0x0000, 0x0000},
+{0x007F, 0x003F, 0x0E1F, 0x0F0F, 0x0F97, 0x07E3, 0x03E1, 0x21F0,
+0x31F8, 0x3A7C, 0x3C3C, 0x3E1C, 0x3F00, 0x3F80, 0x0000, 0x0000},
+{0x0006, 0x0009}
+},
+
+{
+{0x0000, 0x7800, 0x7000, 0x7060, 0x48E0, 0x05C0, 0x0380, 0x0700,
+0x0E80, 0x1C48, 0x1838, 0x0038, 0x0078, 0x0000, 0x0000, 0x0000},
+{0xFE00, 0xFC00, 0xF870, 0xF0F0, 0xE9F0, 0xC7E0, 0x87C0, 0x0F84,
+0x1F8C, 0x3E5C, 0x3C3C, 0x387C, 0x00FC, 0x01FC, 0x0000, 0x0000},
+{0x0006, 0x0006}
+},
+
+{
+{0x0006, 0x000E, 0x001C, 0x0018, 0x0020, 0x0040, 0x00F8, 0x0004,
+0x1FF4, 0x200C, 0x2AA8, 0x1FF0, 0x1F80, 0x3800, 0x6000, 0x8000},
+{0x000F, 0x001F, 0x003E, 0x007C, 0x0070, 0x00E0, 0x01FC, 0x3FF6,
+0x7FF6, 0x7FFE, 0x7FFC, 0x7FF8, 0x3FF0, 0x7FC0, 0xF800, 0xE000},
+{0x000A, 0x0006}
+},
+
+};
+
+wxCursor gMacCurrentCursor ;
+
+#if !wxMAC_USE_COCOA
+CursHandle wxGetStockCursor( int number )
+{
+ wxASSERT_MSG( number >= 0 && number <=kwxCursorLast , wxT("invalid stock cursor id") ) ;
+ CursHandle c = (CursHandle) NewHandle( sizeof(Cursor) ) ;
+ memcpy( *c, &gMacCursors[number], sizeof(Cursor) ) ;
+
+#ifndef WORDS_BIGENDIAN
+ short *sptr = (short*) *c ;
+ for ( int i = 0 ; i < 2 * 16 /* image and mask */ ; ++i, ++sptr )
+ {
+ *sptr = CFSwapInt16( *sptr ) ;
+ }
+#endif
+ return c ;
+}
+#endif
+
+wxCursorRefData::wxCursorRefData()
+{
+ m_hCursor = NULL;
+#if wxMAC_USE_COCOA
+#else
+ m_disposeHandle = false;
+ m_releaseHandle = false;
+ m_isColorCursor = false;
+ m_themeCursor = -1;
+#endif
+}
+
+wxCursorRefData::wxCursorRefData(const wxCursorRefData& cursor)
+{
+ // FIXME: need to copy the cursor
+ m_hCursor = NULL;
+
+#if wxMAC_USE_COCOA
+ wxUnusedVar(cursor);
+#else
+ m_disposeHandle = false;
+ m_releaseHandle = false;
+ m_isColorCursor = cursor.m_isColorCursor;
+ m_themeCursor = cursor.m_themeCursor;
+#endif
+}
+
+wxCursorRefData::~wxCursorRefData()
+{
+#if wxMAC_USE_COCOA
+ if ( m_hCursor )
+ wxMacCocoaRelease(m_hCursor);
+#else
+ if ( m_isColorCursor )
+ {
+#ifndef __LP64__
+ ::DisposeCCursor( (CCrsrHandle) m_hCursor ) ;
+#endif
+ }
+ else if ( m_disposeHandle )
+ {
+ ::DisposeHandle( (Handle ) m_hCursor ) ;
+ }
+ else if ( m_releaseHandle )
+ {
+ // we don't release the resource since it may already
+ // be in use again
+ }
+#endif
+}
+
+wxCursor::wxCursor()
+{
+}
+
+wxCursor::wxCursor(const char WXUNUSED(bits)[], int WXUNUSED(width), int WXUNUSED(height),
+ int WXUNUSED(hotSpotX), int WXUNUSED(hotSpotY), const char WXUNUSED(maskBits)[])
+{
+}
+
+wxCursor::wxCursor( const wxImage &image )
+{
+#if wxUSE_IMAGE
+ CreateFromImage( image ) ;
+#endif
+}
+
+wxCursor::wxCursor(const char* const* bits)
+{
+ (void) CreateFromXpm(bits);
+}
+
+wxGDIRefData *wxCursor::CreateGDIRefData() const
+{
+ return new wxCursorRefData;
+}
+
+wxGDIRefData *wxCursor::CloneGDIRefData(const wxGDIRefData *data) const
+{
+ return new wxCursorRefData(*wx_static_cast(const wxCursorRefData *, data));
+}
+
+bool wxCursor::CreateFromXpm(const char* const* bits)
+{
+#if wxUSE_IMAGE
+ wxCHECK_MSG( bits != NULL, false, wxT("invalid cursor data") );
+ wxXPMDecoder decoder;
+ wxImage img = decoder.ReadData(bits);
+ wxCHECK_MSG( img.Ok(), false, wxT("invalid cursor data") );
+ CreateFromImage( img ) ;
+ return true;
+#else
+ return false;
+#endif
+}
+
+WXHCURSOR wxCursor::GetHCURSOR() const
+{
+ return (M_CURSORDATA ? M_CURSORDATA->m_hCursor : 0);
+}
+
+#if !wxMAC_USE_COCOA
+short GetCTabIndex( CTabHandle colors , RGBColor *col )
+{
+ short retval = 0 ;
+ unsigned long bestdiff = 0xFFFF ;
+
+ for ( int i = 0 ; i < (**colors).ctSize ; ++i )
+ {
+ unsigned long diff = abs(col->red - (**colors).ctTable[i].rgb.red ) +
+ abs(col->green - (**colors).ctTable[i].rgb.green ) +
+ abs(col->blue - (**colors).ctTable[i].rgb.blue ) ;
+
+ if ( diff < bestdiff )
+ {
+ bestdiff = diff ;
+ retval = (**colors).ctTable[i].value ;
+ }
+ }
+
+ return retval ;
+}
+#endif
+
+#if wxUSE_IMAGE
+
+void wxCursor::CreateFromImage(const wxImage & image)
+{
+ m_refData = new wxCursorRefData;
+ int hotSpotX = image.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_X);
+ int hotSpotY = image.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_Y);
+#if wxMAC_USE_COCOA
+ wxBitmap bmp( image );
+ CGImageRef cgimage = wxMacCreateCGImageFromBitmap(bmp);
+ if ( cgimage )
+ {
+ M_CURSORDATA->m_hCursor = wxMacCocoaCreateCursorFromCGImage( cgimage, hotSpotX, hotSpotY );
+ CFRelease( cgimage );
+ }
+#else
+#ifndef __LP64__
+ int w = 16;
+ int h = 16;
+
+ int image_w = image.GetWidth();
+ int image_h = image.GetHeight();
+
+ wxASSERT_MSG( hotSpotX >= 0 && hotSpotX < image_w &&
+ hotSpotY >= 0 && hotSpotY < image_h,
+ wxT("invalid cursor hot spot coordinates") );
+
+ wxImage image16(image); // final image of correct size
+
+ // if image is too small then place it in the center, resize it if too big
+ if ((w > image_w) && (h > image_h))
+ {
+ wxPoint offset((w - image_w) / 2, (h - image_h) / 2);
+ hotSpotX = hotSpotX + offset.x;
+ hotSpotY = hotSpotY + offset.y;
+
+ image16 = image.Size(wxSize(w, h), offset);
+ }
+ else if ((w != image_w) || (h != image_h))
+ {
+ hotSpotX = int(hotSpotX * double(w) / double(image_w));
+ hotSpotY = int(hotSpotY * double(h) / double(image_h));
+
+ image16 = image.Scale(w, h);
+ }
+
+ unsigned char * rgbBits = image16.GetData();
+ bool bHasMask = image16.HasMask() ;
+
+ PixMapHandle pm = (PixMapHandle) NewHandleClear( sizeof(PixMap) ) ;
+ short extent = 16 ;
+ short bytesPerPixel = 1 ;
+ short depth = 8 ;
+ Rect bounds = { 0 , 0 , extent , extent } ;
+ CCrsrHandle ch = (CCrsrHandle) NewHandleClear( sizeof(CCrsr) ) ;
+ CTabHandle newColors = GetCTable( 8 ) ;
+ HandToHand( (Handle *) &newColors );
+
+ // set the values to the indices
+ for ( int i = 0 ; i < (**newColors).ctSize ; ++i )
+ {
+ (**newColors).ctTable[i].value = i ;
+ }
+
+ HLock( (Handle)ch );
+ (**ch).crsrType = 0x8001; // color cursors
+ (**ch).crsrMap = pm;
+ short bytesPerRow = bytesPerPixel * extent;
+
+ (**pm).baseAddr = 0;
+ (**pm).rowBytes = bytesPerRow | 0x8000;
+ (**pm).bounds = bounds;
+ (**pm).pmVersion = 0;
+ (**pm).packType = 0;
+ (**pm).packSize = 0;
+ (**pm).hRes = 0x00480000; // 72 DPI default res
+ (**pm).vRes = 0x00480000; // 72 DPI default res
+ (**pm).pixelSize = depth;
+ (**pm).pixelType = 0;
+ (**pm).cmpCount = 1;
+ (**pm).cmpSize = depth;
+ (**pm).pmTable = newColors;
+
+ (**ch).crsrData = NewHandleClear( extent * bytesPerRow ) ;
+ (**ch).crsrXData = NULL ;
+ (**ch).crsrXValid = 0;
+ (**ch).crsrXHandle = NULL;
+
+ (**ch).crsrHotSpot.h = hotSpotX ;
+ (**ch).crsrHotSpot.v = hotSpotY ;
+ (**ch).crsrXTable = 0 ;
+ (**ch).crsrID = GetCTSeed() ;
+
+ memset( (**ch).crsr1Data , 0 , sizeof( Bits16 ) ) ;
+ memset( (**ch).crsrMask , 0 , sizeof( Bits16 ) ) ;
+
+ unsigned char mr = image16.GetMaskRed() ;
+ unsigned char mg = image16.GetMaskGreen() ;
+ unsigned char mb = image16.GetMaskBlue() ;
+
+ for ( int y = 0 ; y < h ; ++y )
+ {
+ short rowbits = 0, maskbits = 0 ;
+
+ for ( int x = 0 ; x < w ; ++x )
+ {
+ long pos = (y * w + x) * 3;
+
+ unsigned char r = rgbBits[pos] ;
+ unsigned char g = rgbBits[pos + 1] ;
+ unsigned char b = rgbBits[pos + 2] ;
+ RGBColor col = { 0xFFFF, 0xFFFF, 0xFFFF } ;
+
+ if ( bHasMask && r == mr && g == mg && b == mb )
+ {
+ // masked area, does not appear anywhere
+ }
+ else
+ {
+ if ( (int)r + (int)g + (int)b < 0x0200 )
+ rowbits |= ( 1 << (15 - x) ) ;
+
+ maskbits |= ( 1 << (15 - x) ) ;
+
+ wxColor( r , g , b ).GetRGBColor( &col );
+ }
+
+ *((*(**ch).crsrData) + y * bytesPerRow + x) =
+ GetCTabIndex( newColors , &col) ;
+ }
+#ifdef WORDS_BIGENDIAN
+ (**ch).crsr1Data[y] = rowbits ;
+ (**ch).crsrMask[y] = maskbits ;
+#else
+ (**ch).crsr1Data[y] = CFSwapInt16(rowbits) ;
+ (**ch).crsrMask[y] = CFSwapInt16(maskbits) ;
+#endif
+ }
+
+ if ( !bHasMask )
+ memcpy( (**ch).crsrMask , (**ch).crsr1Data , sizeof( Bits16) ) ;
+
+ HUnlock( (Handle)ch ) ;
+ M_CURSORDATA->m_hCursor = ch ;
+ M_CURSORDATA->m_isColorCursor = true ;
+#endif
+#endif
+}
+
+#endif //wxUSE_IMAGE
+
+wxCursor::wxCursor(const wxString& cursor_file, wxBitmapType flags, int hotSpotX, int hotSpotY)
+{
+ m_refData = new wxCursorRefData;
+ if ( flags == wxBITMAP_TYPE_MACCURSOR_RESOURCE )
+ {
+#if wxMAC_USE_COCOA
+ wxFAIL_MSG( wxT("Not implemented") );
+#else
+#ifndef __LP64__
+ Str255 theName ;
+ wxMacStringToPascal( cursor_file , theName ) ;
+
+ Handle resHandle = ::GetNamedResource( 'crsr' , theName ) ;
+ if ( resHandle )
+ {
+ short theId = -1 ;
+ OSType theType ;
+
+ GetResInfo( resHandle , &theId , &theType , theName ) ;
+ ReleaseResource( resHandle ) ;
+
+ M_CURSORDATA->m_hCursor = GetCCursor( theId ) ;
+ if ( M_CURSORDATA->m_hCursor )
+ M_CURSORDATA->m_isColorCursor = true ;
+ }
+ else
+ {
+ Handle resHandle = ::GetNamedResource( 'CURS' , theName ) ;
+ if ( resHandle )
+ {
+ short theId = -1 ;
+ OSType theType ;
+
+ GetResInfo( resHandle , &theId , &theType , theName ) ;
+ ReleaseResource( resHandle ) ;
+
+ M_CURSORDATA->m_hCursor = GetCursor( theId ) ;
+ if ( M_CURSORDATA->m_hCursor )
+ M_CURSORDATA->m_releaseHandle = true ;
+ }
+ }
+#endif
+#endif
+ }
+ else
+ {
+#if wxUSE_IMAGE
+ wxImage image ;
+ image.LoadFile( cursor_file, flags ) ;
+ if ( image.Ok() )
+ {
+ image.SetOption( wxIMAGE_OPTION_CUR_HOTSPOT_X, hotSpotX ) ;
+ image.SetOption( wxIMAGE_OPTION_CUR_HOTSPOT_Y, hotSpotY ) ;
+ m_refData->DecRef() ;
+ m_refData = NULL ;
+ CreateFromImage( image ) ;
+ }
+#endif
+ }
+}
+
+// Cursors by stock number
+wxCursor::wxCursor(int cursor_type)
+{
+ m_refData = new wxCursorRefData;
+#if wxMAC_USE_COCOA
+ M_CURSORDATA->m_hCursor = wxMacCocoaCreateStockCursor( cursor_type );
+#else
+ switch (cursor_type)
+ {
+ case wxCURSOR_COPY_ARROW:
+ M_CURSORDATA->m_themeCursor = kThemeCopyArrowCursor;
+ break;
+
+ case wxCURSOR_WAIT:
+ M_CURSORDATA->m_themeCursor = kThemeWatchCursor;
+ break;
+
+ case wxCURSOR_IBEAM:
+ M_CURSORDATA->m_themeCursor = kThemeIBeamCursor;
+ break;
+
+ case wxCURSOR_CROSS:
+ M_CURSORDATA->m_themeCursor = kThemeCrossCursor;
+ break;
+
+ case wxCURSOR_SIZENWSE:
+ M_CURSORDATA->m_hCursor = wxGetStockCursor(kwxCursorSizeNWSE);
+ break;
+
+ case wxCURSOR_SIZENESW:
+ M_CURSORDATA->m_hCursor = wxGetStockCursor(kwxCursorSizeNESW);
+ break;
+
+ case wxCURSOR_SIZEWE:
+ M_CURSORDATA->m_themeCursor = kThemeResizeLeftRightCursor;
+ break;
+
+ case wxCURSOR_SIZENS:
+ M_CURSORDATA->m_hCursor = wxGetStockCursor(kwxCursorSizeNS);
+ break;
+
+ case wxCURSOR_SIZING:
+ M_CURSORDATA->m_hCursor = wxGetStockCursor(kwxCursorSize);
+ break;
+
+ case wxCURSOR_HAND:
+ M_CURSORDATA->m_themeCursor = kThemePointingHandCursor;
+ break;
+
+ case wxCURSOR_BULLSEYE:
+ M_CURSORDATA->m_hCursor = wxGetStockCursor(kwxCursorBullseye);
+ break;
+
+ case wxCURSOR_PENCIL:
+ M_CURSORDATA->m_hCursor = wxGetStockCursor(kwxCursorPencil);
+ break;
+
+ case wxCURSOR_MAGNIFIER:
+ M_CURSORDATA->m_hCursor = wxGetStockCursor(kwxCursorMagnifier);
+ break;
+
+ case wxCURSOR_NO_ENTRY:
+ M_CURSORDATA->m_hCursor = wxGetStockCursor(kwxCursorNoEntry);
+ break;
+
+ case wxCURSOR_WATCH:
+ M_CURSORDATA->m_themeCursor = kThemeWatchCursor;
+ break;
+
+ case wxCURSOR_PAINT_BRUSH:
+ M_CURSORDATA->m_hCursor = wxGetStockCursor(kwxCursorPaintBrush);
+ break;
+
+ case wxCURSOR_POINT_LEFT:
+ M_CURSORDATA->m_hCursor = wxGetStockCursor(kwxCursorPointLeft);
+ break;
+
+ case wxCURSOR_POINT_RIGHT:
+ M_CURSORDATA->m_hCursor = wxGetStockCursor(kwxCursorPointRight);
+ break;
+
+ case wxCURSOR_QUESTION_ARROW:
+ M_CURSORDATA->m_hCursor = wxGetStockCursor(kwxCursorQuestionArrow);
+ break;
+
+ case wxCURSOR_BLANK:
+ M_CURSORDATA->m_hCursor = wxGetStockCursor(kwxCursorBlank);
+ break;
+
+ case wxCURSOR_RIGHT_ARROW:
+ M_CURSORDATA->m_hCursor = wxGetStockCursor(kwxCursorRightArrow);
+ break;
+
+ case wxCURSOR_SPRAYCAN:
+ M_CURSORDATA->m_hCursor = wxGetStockCursor(kwxCursorRoller);
+ break;
+
+ case wxCURSOR_CHAR:
+ case wxCURSOR_ARROW:
+ case wxCURSOR_LEFT_BUTTON:
+ case wxCURSOR_RIGHT_BUTTON:
+ case wxCURSOR_MIDDLE_BUTTON:
+ default:
+ M_CURSORDATA->m_themeCursor = kThemeArrowCursor;
+ break;
+ }
+
+ if ( M_CURSORDATA->m_themeCursor == -1 )
+ M_CURSORDATA->m_releaseHandle = true;
+#endif
+}
+
+void wxCursor::MacInstall() const
+{
+ gMacCurrentCursor = *this ;
+#if wxMAC_USE_COCOA
+ if ( IsOk() )
+ wxMacCocoaSetCursor( M_CURSORDATA->m_hCursor );
+#else
+ if ( m_refData && M_CURSORDATA->m_themeCursor != -1 )
+ {
+ SetThemeCursor( M_CURSORDATA->m_themeCursor ) ;
+ }
+ else if ( m_refData && M_CURSORDATA->m_hCursor )
+ {
+#ifndef __LP64__
+ if ( M_CURSORDATA->m_isColorCursor )
+ ::SetCCursor( (CCrsrHandle) M_CURSORDATA->m_hCursor ) ;
+ else
+ ::SetCursor( * (CursHandle) M_CURSORDATA->m_hCursor ) ;
+#endif
+ }
+ else
+ {
+ SetThemeCursor( kThemeArrowCursor ) ;
+ }
+#endif
+}
+
+wxCursor::~wxCursor()
+{
+}
+
+// Global cursor setting
+wxCursor gGlobalCursor;
+void wxSetCursor(const wxCursor& cursor)
+{
+ cursor.MacInstall() ;
+ gGlobalCursor = cursor;
+}
diff --git a/src/osx/carbon/databrow.cpp b/src/osx/carbon/databrow.cpp
new file mode 100644
index 0000000000..6d4e55cc5b
--- /dev/null
+++ b/src/osx/carbon/databrow.cpp
@@ -0,0 +1,1145 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/databrow.cpp
+// Purpose: Classes and functions for the Carbon data browser
+// Author:
+// Modified by:
+// Created: 2007-05-18
+// RCS-ID: $Id$
+// Copyright: (c)
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/wxprec.h"
+
+#if wxUSE_DATAVIEWCTRL
+#ifndef wxUSE_GENERICDATAVIEWCTRL
+
+#ifndef WX_PRECOMP
+ #include "wx/app.h"
+ #include "wx/toplevel.h"
+ #include "wx/font.h"
+ #include "wx/settings.h"
+ #include "wx/utils.h"
+#endif
+
+#include "wx/dataview.h"
+#include "wx/mac/carbon/databrow.h"
+#include "wx/mac/private.h"
+#include "wx/mac/uma.h"
+
+#include
+
+// ============================================================================
+// Variables used globally in databrow.cpp
+// ============================================================================
+DataBrowserGetContextualMenuUPP gDataBrowserTableViewGetContextualMenuUPP = NULL;
+DataBrowserItemCompareUPP gDataBrowserTableViewItemCompareUPP = NULL;
+DataBrowserItemDataUPP gDataBrowserTableViewItemDataUPP = NULL;
+DataBrowserItemNotificationUPP gDataBrowserTableViewItemNotificationUPP = NULL;
+
+DataBrowserDrawItemUPP gDataBrowserTableViewDrawItemUPP = NULL;
+DataBrowserEditItemUPP gDataBrowserTableViewEditItemUPP = NULL;
+DataBrowserHitTestUPP gDataBrowserTableViewHitTestUPP = NULL;
+DataBrowserTrackingUPP gDataBrowserTableViewTrackingUPP = NULL;
+
+// ============================================================================
+// wxMacDataBrowserTableViewControl
+// ============================================================================
+
+pascal Boolean wxMacDataBrowserTableViewControl::DataBrowserCompareProc(ControlRef browser, DataBrowserItemID itemOneID, DataBrowserItemID itemTwoID, DataBrowserPropertyID sortProperty)
+{
+ wxMacDataBrowserTableViewControl* ControlPtr(dynamic_cast(wxMacControl::GetReferenceFromNativeControl(browser)));
+
+
+ if (ControlPtr != NULL)
+ return ControlPtr->DataBrowserCompareProc(itemOneID,itemTwoID,sortProperty);
+ else
+ return errDataBrowserPropertyNotSupported;
+} /* wxMacDataBrowserTableViewControl::DataBrowserCompareProc(ControlRef, DataBrowserItemID, DataBrowserItemID, DataBrowserPropertyID) */
+
+pascal void wxMacDataBrowserTableViewControl::DataBrowserGetContextualMenuProc(ControlRef browser, MenuRef* menu, UInt32* helpType, CFStringRef* helpItemString, AEDesc* selection)
+{
+ wxMacDataBrowserTableViewControl* ControlPtr(dynamic_cast(wxMacControl::GetReferenceFromNativeControl(browser)));
+
+
+ if (ControlPtr != NULL)
+ ControlPtr->DataBrowserGetContextualMenuProc(menu,helpType,helpItemString,selection);
+} /* wxMacDataBrowserTableViewControl::DataBrowserGetContextualMenuProc(ControlRef, MenuRef*, UInt32*, CFStringRef*, AEDesc*) */
+
+pascal OSStatus wxMacDataBrowserTableViewControl::DataBrowserGetSetItemDataProc(ControlRef browser, DataBrowserItemID itemID, DataBrowserPropertyID propertyID, DataBrowserItemDataRef itemData, Boolean getValue)
+{
+ wxMacDataBrowserTableViewControl* ControlPtr(dynamic_cast(wxMacControl::GetReferenceFromNativeControl(browser)));
+
+
+ if (ControlPtr != NULL)
+ return ControlPtr->DataBrowserGetSetItemDataProc(itemID,propertyID,itemData,getValue);
+ else
+ return errDataBrowserPropertyNotSupported;
+} /* wxMacDataBrowserTableViewControl::DataBrowserGetSetItemDataProc(ControlRef, DataBrowserItemID, DataBrowserPropertyID, DataBrowserItemDataRef, Boolean) */
+
+pascal void wxMacDataBrowserTableViewControl::DataBrowserItemNotificationProc(ControlRef browser, DataBrowserItemID itemID, DataBrowserItemNotification message, DataBrowserItemDataRef itemData)
+{
+ wxMacDataBrowserTableViewControl* ControlPtr(dynamic_cast(wxMacControl::GetReferenceFromNativeControl(browser)));
+
+
+ if (ControlPtr != NULL)
+ ControlPtr->DataBrowserItemNotificationProc(itemID,message,itemData);
+} /* wxMacDataBrowserTableViewControl::DataBrowserItemNotificationProc(ControlRef, DataBrowserItemID, DataBrowserItemNotification, DataBrowserItemDataRef) */
+
+pascal void wxMacDataBrowserTableViewControl::DataBrowserDrawItemProc(ControlRef browser, DataBrowserItemID itemID, DataBrowserPropertyID propertyID, DataBrowserItemState state, Rect const* rectangle, SInt16 bitDepth, Boolean colorDevice)
+{
+ wxMacDataBrowserTableViewControl* ControlPtr(dynamic_cast(wxMacControl::GetReferenceFromNativeControl(browser)));
+
+
+ if (ControlPtr != NULL)
+ ControlPtr->DataBrowserDrawItemProc(itemID,propertyID,state,rectangle,bitDepth,colorDevice);
+} /* wxMacDataBrowserTableViewControl::DataBrowserDrawItemProc(ControlRef, DataBrowserItemID, DataBrowserPropertyID, DataBrowserItemState, Rect const*, SInt16, Boolean) */
+
+pascal Boolean wxMacDataBrowserTableViewControl::DataBrowserEditItemProc(ControlRef browser, DataBrowserItemID itemID, DataBrowserPropertyID propertyID, CFStringRef theString, Rect* maxEditTextRect, Boolean* shrinkToFit)
+{
+ wxMacDataBrowserTableViewControl* ControlPtr(dynamic_cast(wxMacControl::GetReferenceFromNativeControl(browser)));
+
+
+ return ((ControlPtr != NULL) && ControlPtr->DataBrowserEditItemProc(itemID,propertyID,theString,maxEditTextRect,shrinkToFit));
+} /* wxMacDataBrowserTableViewControl::DataBrowserEditItemProc(ControlRef, DataBrowserItemID, DataBrowserPropertyID, CFStringRef, Rect*, Boolean*) */
+
+pascal Boolean wxMacDataBrowserTableViewControl::DataBrowserHitTestProc(ControlRef browser, DataBrowserItemID itemID, DataBrowserPropertyID propertyID, Rect const* theRect, Rect const* mouseRect)
+{
+ wxMacDataBrowserTableViewControl* ControlPtr(dynamic_cast(wxMacControl::GetReferenceFromNativeControl(browser)));
+
+
+ return ((ControlPtr != NULL) && ControlPtr->DataBrowserHitTestProc(itemID,propertyID,theRect,mouseRect));
+} /* wxMacDataBrowserTableViewControl::DataBrowserHitTestProc(ControlRef, DataBrowserItemID, DataBrowserPropertyID, Rect const*, Rect const*) */
+
+pascal DataBrowserTrackingResult wxMacDataBrowserTableViewControl::DataBrowserTrackingProc(ControlRef browser, DataBrowserItemID itemID, DataBrowserPropertyID propertyID, Rect const* theRect, Point startPt, EventModifiers modifiers)
+{
+ wxMacDataBrowserTableViewControl* ControlPtr(dynamic_cast(wxMacControl::GetReferenceFromNativeControl(browser)));
+
+
+ if (ControlPtr != NULL)
+ return ControlPtr->DataBrowserTrackingProc(itemID,propertyID,theRect,startPt,modifiers);
+ else
+ return kDataBrowserNothingHit;
+} /* wxMacDataBrowserTableViewControl::DataBrowserTrackingProc(ControlRef, DataBrowserItemID, DataBrowserPropertyID, Rect const*, Point, EventModifiers) */
+
+wxMacDataBrowserTableViewControl::wxMacDataBrowserTableViewControl(wxWindow* peer, wxPoint const& pos, wxSize const& size, long style)
+ :wxMacControl(peer)
+{
+ Rect bounds = wxMacGetBoundsForControl(peer,pos,size);
+ OSStatus err = ::CreateDataBrowserControl(MAC_WXHWND(peer->MacGetTopLevelWindowRef()),&bounds,kDataBrowserListView,&(this->m_controlRef));
+
+
+ SetReferenceInNativeControl();
+ verify_noerr(err);
+ // setup standard callbacks:
+ if (gDataBrowserTableViewGetContextualMenuUPP == NULL) gDataBrowserTableViewGetContextualMenuUPP = NewDataBrowserGetContextualMenuUPP(wxMacDataBrowserTableViewControl::DataBrowserGetContextualMenuProc);
+ if (gDataBrowserTableViewItemCompareUPP == NULL) gDataBrowserTableViewItemCompareUPP = NewDataBrowserItemCompareUPP (wxMacDataBrowserTableViewControl::DataBrowserCompareProc);
+ if (gDataBrowserTableViewItemDataUPP == NULL) gDataBrowserTableViewItemDataUPP = NewDataBrowserItemDataUPP (wxMacDataBrowserTableViewControl::DataBrowserGetSetItemDataProc);
+ if (gDataBrowserTableViewItemNotificationUPP == NULL)
+ {
+ gDataBrowserTableViewItemNotificationUPP =
+#if TARGET_API_MAC_OSX
+ (DataBrowserItemNotificationUPP) NewDataBrowserItemNotificationWithItemUPP(wxMacDataBrowserTableViewControl::DataBrowserItemNotificationProc);
+#else
+ NewDataBrowserItemNotificationUPP(wxMacDataBrowserTableViewControl::DataBrowserItemNotificationProc);
+#endif
+ }
+ DataBrowserCallbacks callbacks; // variable definition
+
+ InitializeDataBrowserCallbacks(&callbacks,kDataBrowserLatestCallbacks);
+ callbacks.u.v1.getContextualMenuCallback = gDataBrowserTableViewGetContextualMenuUPP;
+ callbacks.u.v1.itemDataCallback = gDataBrowserTableViewItemDataUPP;
+ callbacks.u.v1.itemCompareCallback = gDataBrowserTableViewItemCompareUPP;
+ callbacks.u.v1.itemNotificationCallback = gDataBrowserTableViewItemNotificationUPP;
+ this->SetCallbacks(&callbacks);
+
+ // setup callbacks for customized items:
+ if (gDataBrowserTableViewDrawItemUPP == NULL) gDataBrowserTableViewDrawItemUPP = NewDataBrowserDrawItemUPP(wxMacDataBrowserTableViewControl::DataBrowserDrawItemProc);
+ if (gDataBrowserTableViewEditItemUPP == NULL) gDataBrowserTableViewEditItemUPP = NewDataBrowserEditItemUPP(wxMacDataBrowserTableViewControl::DataBrowserEditItemProc);
+ if (gDataBrowserTableViewHitTestUPP == NULL) gDataBrowserTableViewHitTestUPP = NewDataBrowserHitTestUPP (wxMacDataBrowserTableViewControl::DataBrowserHitTestProc);
+ if (gDataBrowserTableViewTrackingUPP == NULL) gDataBrowserTableViewTrackingUPP = NewDataBrowserTrackingUPP(wxMacDataBrowserTableViewControl::DataBrowserTrackingProc);
+
+ DataBrowserCustomCallbacks customCallbacks; // variable definition
+
+ InitializeDataBrowserCustomCallbacks(&customCallbacks,kDataBrowserLatestCallbacks);
+ customCallbacks.u.v1.drawItemCallback = gDataBrowserTableViewDrawItemUPP;
+ customCallbacks.u.v1.editTextCallback = gDataBrowserTableViewEditItemUPP;
+ customCallbacks.u.v1.hitTestCallback = gDataBrowserTableViewHitTestUPP;
+ customCallbacks.u.v1.trackingCallback = gDataBrowserTableViewTrackingUPP;
+ this->SetCustomCallbacks(&customCallbacks);
+
+ // style setting:
+ this->EnableCellSizeModification( ((style & wxDV_VARIABLE_LINE_HEIGHT) != 0), true );
+
+ DataBrowserSelectionFlags flags; // variable definition
+
+ if (this->GetSelectionFlags(&flags) == noErr) // get default settings
+ {
+ if ((style & wxDV_MULTIPLE) != 0)
+ flags &= ~kDataBrowserSelectOnlyOne;
+ else
+ flags |= kDataBrowserSelectOnlyOne;
+ (void) this->SetSelectionFlags(flags);
+ } /* if */
+
+ OptionBits attributes; // variable definition
+
+ if (this->GetAttributes(&attributes) == noErr) // get default settings
+ {
+ if ((style & wxDV_VERT_RULES) != 0)
+ attributes |= kDataBrowserAttributeListViewDrawColumnDividers;
+ else
+ attributes &= ~kDataBrowserAttributeListViewDrawColumnDividers;
+ if ((style & wxDV_ROW_LINES) != 0)
+ attributes |= kDataBrowserAttributeListViewAlternatingRowColors;
+ else
+ attributes &= ~kDataBrowserAttributeListViewAlternatingRowColors;
+ (void) this->SetAttributes(attributes);
+ } /* if */
+
+ if ((style & wxDV_NO_HEADER) != 0)
+ this->SetHeaderButtonHeight(0);
+} /* wxMacDataBrowserTableViewControl::wxMacDataBrowserTableViewControl(wxWindow*, wxPoint const&, wxSize const&, long) */
+
+//
+// callback handling
+//
+OSStatus wxMacDataBrowserTableViewControl::SetCallbacks(DataBrowserCallbacks const* callbacks)
+{
+ return ::SetDataBrowserCallbacks(this->m_controlRef,callbacks);
+} /* wxMacDataBrowserTableViewControl::SetCallbacks(DataBrowserCallbacks const*) */
+
+OSStatus wxMacDataBrowserTableViewControl::SetCustomCallbacks(DataBrowserCustomCallbacks const* customCallbacks)
+{
+ return ::SetDataBrowserCustomCallbacks(this->m_controlRef,customCallbacks);
+} /* xMacDataBrowserTableViewControl::SetCustomCallbacks(DataBrowserCustomCallbacks const*) */
+
+//
+// header handling
+//
+OSStatus wxMacDataBrowserTableViewControl::GetHeaderDesc(DataBrowserPropertyID propertyID, DataBrowserListViewHeaderDesc* desc) const
+{
+ desc->version = kDataBrowserListViewLatestHeaderDesc; // if this statement is missing the next call will fail (NOT DOCUMENTED!!)
+ return ::GetDataBrowserListViewHeaderDesc(this->m_controlRef,propertyID,desc);
+}
+
+OSStatus wxMacDataBrowserTableViewControl::SetHeaderDesc(DataBrowserPropertyID propertyID, DataBrowserListViewHeaderDesc* desc)
+{
+ return ::SetDataBrowserListViewHeaderDesc(this->m_controlRef,propertyID,desc);
+}
+
+//
+// layout handling
+//
+OSStatus wxMacDataBrowserTableViewControl::AutoSizeColumns()
+{
+ return AutoSizeDataBrowserListViewColumns(this->m_controlRef);
+}
+
+OSStatus wxMacDataBrowserTableViewControl::EnableCellSizeModification(bool enableHeight, bool enableWidth)
+{
+ return ::SetDataBrowserTableViewGeometry(this->GetControlRef(),enableWidth,enableHeight);
+} /* wxMacDataBrowserTableViewControl::EnableCellSizeModification(bool, bool) */
+
+OSStatus wxMacDataBrowserTableViewControl::GetAttributes(OptionBits* attributes)
+{
+ return ::DataBrowserGetAttributes(this->GetControlRef(),attributes);
+} /* wxMacDataBrowserTableViewControl::GetAttributes(OptionBits*) */
+
+OSStatus wxMacDataBrowserTableViewControl::GetColumnWidth(DataBrowserPropertyID propertyID, UInt16* width) const
+{
+ return ::GetDataBrowserTableViewNamedColumnWidth(this->m_controlRef,propertyID,width);
+}
+
+OSStatus wxMacDataBrowserTableViewControl::GetDefaultColumnWidth( UInt16 *width ) const
+{
+ return GetDataBrowserTableViewColumnWidth(this->m_controlRef, width );
+}
+
+OSStatus wxMacDataBrowserTableViewControl::GetDefaultRowHeight(UInt16* height) const
+{
+ return ::GetDataBrowserTableViewRowHeight(this->m_controlRef,height);
+}
+
+OSStatus wxMacDataBrowserTableViewControl::GetHeaderButtonHeight(UInt16 *height)
+{
+ return ::GetDataBrowserListViewHeaderBtnHeight(this->m_controlRef,height);
+}
+
+OSStatus wxMacDataBrowserTableViewControl::GetPartBounds(DataBrowserItemID item, DataBrowserPropertyID propertyID, DataBrowserPropertyPart part, Rect* bounds)
+{
+ return ::GetDataBrowserItemPartBounds(this->m_controlRef,item,propertyID,part,bounds);
+} /* wxMacDataBrowserTableViewControl::GetPartBounds(DataBrowserItemID, DataBrowswerPropertyID, DataBrowserPropertyPart, Rect*) */
+
+OSStatus wxMacDataBrowserTableViewControl::GetRowHeight(DataBrowserItemID item, UInt16* height) const
+{
+ return ::GetDataBrowserTableViewItemRowHeight(this->m_controlRef,item,height);
+} /* wxMacDataBrowserTableViewControl::GetRowHeight(DataBrowserItemID, UInt16*) const */
+
+OSStatus wxMacDataBrowserTableViewControl::GetScrollPosition( UInt32 *top , UInt32 *left ) const
+{
+ return GetDataBrowserScrollPosition(this->m_controlRef, top , left );
+}
+
+OSStatus wxMacDataBrowserTableViewControl::SetAttributes(OptionBits attributes)
+{
+ return ::DataBrowserChangeAttributes(this->GetControlRef(),attributes,~attributes);
+} /* wxMacDataBrowserTableViewControl::SetAttributes(OptionBits) */
+
+OSStatus wxMacDataBrowserTableViewControl::SetColumnWidth(DataBrowserPropertyID propertyID, UInt16 width)
+{
+ return ::SetDataBrowserTableViewNamedColumnWidth(this->m_controlRef,propertyID,width);
+}
+
+OSStatus wxMacDataBrowserTableViewControl::SetDefaultColumnWidth(UInt16 width)
+{
+ return ::SetDataBrowserTableViewColumnWidth(this->m_controlRef,width);
+}
+
+OSStatus wxMacDataBrowserTableViewControl::SetDefaultRowHeight(UInt16 height)
+{
+ return ::SetDataBrowserTableViewRowHeight(this->m_controlRef,height);
+}
+
+OSStatus wxMacDataBrowserTableViewControl::SetHasScrollBars(bool horiz, bool vert)
+{
+ return ::SetDataBrowserHasScrollBars(this->m_controlRef,horiz,vert);
+} /* wxMacDataBrowserTableViewControl::SetHasScrollBars(bool, bool) */
+
+OSStatus wxMacDataBrowserTableViewControl::SetHeaderButtonHeight(UInt16 height)
+{
+ return ::SetDataBrowserListViewHeaderBtnHeight(this->m_controlRef,height);
+} /* wxMacDataBrowserTableViewControl::SetHeaderButtonHeight(UInt16) */
+
+OSStatus wxMacDataBrowserTableViewControl::SetHiliteStyle(DataBrowserTableViewHiliteStyle hiliteStyle)
+{
+ return ::SetDataBrowserTableViewHiliteStyle(this->m_controlRef,hiliteStyle);
+} /*wxMacDataBrowserTableViewControl::SetHiliteStyle(DataBrowserTableViewHiliteStyle) */
+
+OSStatus wxMacDataBrowserTableViewControl::SetIndent(float Indent)
+{
+ return ::DataBrowserSetMetric(this->m_controlRef,kDataBrowserMetricDisclosureColumnPerDepthGap,true,Indent);
+} /* wxMacDataBrowserTableViewControl::SetIndent(float* Indent) */
+
+OSStatus wxMacDataBrowserTableViewControl::SetRowHeight(DataBrowserItemID item, UInt16 height)
+{
+ return ::SetDataBrowserTableViewItemRowHeight(this->m_controlRef,item,height);
+}
+
+OSStatus wxMacDataBrowserTableViewControl::SetScrollPosition(UInt32 top, UInt32 left)
+{
+ return ::SetDataBrowserScrollPosition(this->m_controlRef,top,left);
+}
+
+//
+// column handling
+//
+OSStatus wxMacDataBrowserTableViewControl::GetColumnCount(UInt32* numColumns) const
+{
+ return ::GetDataBrowserTableViewColumnCount(this->m_controlRef,numColumns);
+}
+
+OSStatus wxMacDataBrowserTableViewControl::GetColumnIndex(DataBrowserPropertyID propertyID, DataBrowserTableViewColumnIndex* index) const
+{
+ return ::GetDataBrowserTableViewColumnPosition(this->m_controlRef,propertyID,index);
+} /* wxMacDataBrowserTableViewControl::GetColumnIndex(DataBrowserPropertyID, DataBrowserTableViewColumnIndex*) const */
+
+OSStatus wxMacDataBrowserTableViewControl::GetFreePropertyID(DataBrowserPropertyID* propertyID) const
+{
+ for (*propertyID=kMinPropertyID; *propertyID::max(); ++(*propertyID))
+ if (this->IsUsedPropertyID(*propertyID) == errDataBrowserPropertyNotFound)
+ return noErr;
+ return errDataBrowserPropertyNotSupported;
+} /* wxMacDataBrowserTableViewControl::GetFreePropertyID(DataBrowserPropertyID*) const */
+
+OSStatus wxMacDataBrowserTableViewControl::GetPropertyFlags(DataBrowserPropertyID propertyID, DataBrowserPropertyFlags *flags) const
+{
+ return ::GetDataBrowserPropertyFlags(this->m_controlRef,propertyID,flags);
+}
+
+OSStatus wxMacDataBrowserTableViewControl::GetPropertyID(DataBrowserItemDataRef itemData, DataBrowserPropertyID* propertyID)
+{
+ return ::GetDataBrowserItemDataProperty(itemData,propertyID);
+} /* wxMacDataBrowserTableViewControl::GetPropertyID(DataBrowserItemDataRef, DataBrowserPropertyID*) */
+
+OSStatus wxMacDataBrowserTableViewControl::GetPropertyID(DataBrowserTableViewColumnIndex index, DataBrowserTableViewColumnID* propertyID)
+{
+ return ::GetDataBrowserTableViewColumnProperty(this->m_controlRef,index,propertyID);
+} /* wxMacDataBrowserTableViewControl::GetPropertyID(DataBrowserTableViewColumnIndex, DataBrowserTableViewColumnID*) */
+
+OSStatus wxMacDataBrowserTableViewControl::IsUsedPropertyID(DataBrowserPropertyID propertyID) const
+{
+ // as the Mac interface does not provide a function that checks if the property id is in use or not a function is chosen that should not
+ // lead to a large overhead for the call but returns an error code if the property id does not exist, here we use the function that returns
+ // the column position for the property id:
+ DataBrowserTableViewColumnIndex index;
+
+ return ::GetDataBrowserTableViewColumnPosition(this->m_controlRef,propertyID,&index);
+} /* wxMacDataBrowserTableViewControl::IsUsedPropertyId(DataBrowserPropertyID) const */
+
+OSStatus wxMacDataBrowserTableViewControl::RemoveColumnByProperty(DataBrowserTableViewColumnID propertyID)
+{
+ return ::RemoveDataBrowserTableViewColumn(this->m_controlRef,propertyID);
+} /* wxMacDataBrowserTableViewControl::RemoveColumnByProperty(DataBrowserTableViewColumnID) */
+
+OSStatus wxMacDataBrowserTableViewControl::RemoveColumnByIndex(DataBrowserTableViewColumnIndex index)
+{
+ DataBrowserTableViewColumnID propertyID;
+
+
+ this->GetPropertyID(index,&propertyID);
+ return ::RemoveDataBrowserTableViewColumn(this->m_controlRef,propertyID);
+} /* wxMacDataBrowserTableViewControl::RemoveColumnByIndex(DataBrowserTableViewColumnIndex) */
+
+OSStatus wxMacDataBrowserTableViewControl::SetColumnIndex(DataBrowserPropertyID propertyID, DataBrowserTableViewColumnIndex index)
+{
+ return ::SetDataBrowserTableViewColumnPosition(this->m_controlRef,propertyID,index);
+} /* wxMacDataBrowserTableViewControl::SetColumnIndex(DataBrowserPropertyID, DataBrowserTableViewColumnIndex) */
+
+OSStatus wxMacDataBrowserTableViewControl::SetDisclosureColumn(DataBrowserPropertyID propertyID, Boolean expandableRows)
+{
+ return ::SetDataBrowserListViewDisclosureColumn(this->m_controlRef,propertyID,expandableRows);
+}
+
+OSStatus wxMacDataBrowserTableViewControl::SetPropertyFlags(DataBrowserPropertyID propertyID, DataBrowserPropertyFlags flags)
+{
+ return ::SetDataBrowserPropertyFlags(this->m_controlRef,propertyID,flags);
+} /* wxMacDataBrowserTableViewControl::SetPropertyFlags(DataBrowserPropertyID, DataBrowserPropertyFlags) */
+
+//
+// item handling
+//
+OSStatus wxMacDataBrowserTableViewControl::AddItems(DataBrowserItemID container, UInt32 numItems, DataBrowserItemID const* items, DataBrowserPropertyID preSortProperty)
+{
+ return ::AddDataBrowserItems(this->m_controlRef,container,numItems,items,preSortProperty);
+} /* wxMacDataBrowserTableViewControl::AddItems(DataBrowserItemID, UInt32, DataBrowserItemID const*, DataBrowserPropertyID) */
+
+OSStatus wxMacDataBrowserTableViewControl::GetFreeItemID(DataBrowserItemID* id) const
+{
+ ItemCount NoOfItems;
+
+ OSStatus status;
+
+
+ status = this->GetItemCount(&NoOfItems);
+ wxCHECK_MSG(status == noErr,status,_("Could not retrieve number of items"));
+ if (NoOfItems == 0)
+ {
+ *id = 1;
+ return noErr;
+ } /* if */
+ else
+ {
+ // as there might be a lot of items in the data browser and mostly the data is added item by item the largest used ID number is roughly in the order of magnitude
+ // as the number of items; therefore, start from the number of items to look for a new ID:
+ for (*id=NoOfItems; *id::max(); ++(*id))
+ if (this->IsUsedItemID(*id) == errDataBrowserItemNotFound)
+ return noErr;
+ // as the first approach was not successful, try from the beginning:
+ for (*id=0; *idIsUsedItemID(*id) == errDataBrowserItemNotFound)
+ return noErr;
+ // sorry, data browser is full:
+ return errDataBrowserItemNotAdded;
+ } /* if */
+} /* wxMacDataBrowserTableViewControl::GetFreeItemID(DataBrowserItemID*) const */
+
+OSStatus wxMacDataBrowserTableViewControl::GetItemCount(DataBrowserItemID container, Boolean recurse, DataBrowserItemState state, ItemCount* numItems) const
+{
+ return GetDataBrowserItemCount(this->m_controlRef,container,recurse,state,numItems);
+} /* wxMacDataBrowserTableViewControl::GetItemCount(DataBrowserItemID, Boolean, DataBrowserItemState, ItemCount*) const */
+
+OSStatus wxMacDataBrowserTableViewControl::GetItemID( DataBrowserTableViewRowIndex row, DataBrowserItemID * item ) const
+{
+ return GetDataBrowserTableViewItemID(this->m_controlRef,row,item);
+}
+
+OSStatus wxMacDataBrowserTableViewControl::GetItems(DataBrowserItemID container, Boolean recurse, DataBrowserItemState state, Handle items) const
+{
+ return GetDataBrowserItems(this->m_controlRef,container,recurse,state,items);
+} /* wxMacDataBrowserTableViewControl::GetItems(DataBrowserItemID, Boolean, DataBrowserItemState, Handle) const */
+
+OSStatus wxMacDataBrowserTableViewControl::GetItemRow(DataBrowserItemID item, DataBrowserTableViewRowIndex* row) const
+{
+ return GetDataBrowserTableViewItemRow(this->m_controlRef,item,row);
+}
+
+OSStatus wxMacDataBrowserTableViewControl::IsUsedItemID(DataBrowserItemID itemID) const
+{
+ // as the Mac interface does not provide a function that checks if the property id is in use or not a function is chosen that should not
+ // lead to a large overhead for the call but returns an error code if the property id does not exist, here we use the function that returns
+ // the column position for the property id:
+ DataBrowserTableViewColumnIndex index;
+
+ return ::GetDataBrowserTableViewItemRow(this->m_controlRef,itemID,&index);
+} /* wxMacDataBrowserTableViewControl::IsUsedItemID(DataBrowserItemID) const */
+
+OSStatus wxMacDataBrowserTableViewControl::RemoveItems(DataBrowserItemID container, UInt32 numItems, DataBrowserItemID const* items, DataBrowserPropertyID preSortProperty)
+{
+ return ::RemoveDataBrowserItems(this->m_controlRef,container,numItems,items,preSortProperty);
+}
+
+OSStatus wxMacDataBrowserTableViewControl::RevealItem(DataBrowserItemID item, DataBrowserPropertyID propertyID, DataBrowserRevealOptions options) const
+{
+ return ::RevealDataBrowserItem(this->m_controlRef,item,propertyID,options);
+} /* wxMacDataBrowserTableViewControl::RevealItem(DataBrowserItemID item, DataBrowserPropertyID propertyID, DataBrowserRevealOptions options) const */
+
+OSStatus wxMacDataBrowserTableViewControl::UpdateItems(DataBrowserItemID container, UInt32 numItems, DataBrowserItemID const* items, DataBrowserPropertyID preSortProperty,
+ DataBrowserPropertyID propertyID) const
+{
+ return UpdateDataBrowserItems(this->m_controlRef,container,numItems,items,preSortProperty,propertyID);
+}
+
+//
+// item selection
+//
+size_t wxMacDataBrowserTableViewControl::GetSelectedItemIDs(wxArrayDataBrowserItemID& itemIDs) const
+{
+ DataBrowserItemID* itemIDPtr;
+ Handle handle(::NewHandle(0));
+
+ size_t NoOfItems;
+
+
+ wxCHECK_MSG(this->GetItems(kDataBrowserNoItem,true,kDataBrowserItemIsSelected,handle) == noErr,0,_("Could not get selected items."));
+ NoOfItems = static_cast(::GetHandleSize(handle)/sizeof(DataBrowserItemID));
+ itemIDs.Empty();
+ itemIDs.Alloc(NoOfItems);
+ HLock(handle);
+ itemIDPtr = (DataBrowserItemID*) (*handle);
+ for (size_t i=0; im_controlRef,first,last);
+} /* wxMacDataBrowserTableViewControl::GetSelectionAnchor(DataBrowserItemID*, DataBrowserItemID*) const */
+
+OSStatus wxMacDataBrowserTableViewControl::GetSelectionFlags(DataBrowserSelectionFlags* flags) const
+{
+ return ::GetDataBrowserSelectionFlags(this->m_controlRef,flags);
+} /* wxMacDataBrowserTableViewControl::GetSelectionFlags(DataBrowserSelectionFlags*) const */
+
+bool wxMacDataBrowserTableViewControl::IsItemSelected(DataBrowserItemID item) const
+{
+ return ::IsDataBrowserItemSelected(this->m_controlRef,item);
+} /* wxMacDataBrowserTableViewControl::IsItemSelected(DataBrowserItemID) const */
+
+OSStatus wxMacDataBrowserTableViewControl::SetSelectionFlags(DataBrowserSelectionFlags flags)
+{
+ return ::SetDataBrowserSelectionFlags(this->m_controlRef,flags);
+} /* wxMacDataBrowserTableViewControl::SetSelectionFlags(DataBrowserSelectionFlags) */
+
+OSStatus wxMacDataBrowserTableViewControl::SetSelectedItems(UInt32 numItems, DataBrowserItemID const* items, DataBrowserSetOption operation)
+{
+ return ::SetDataBrowserSelectedItems(this->m_controlRef, numItems, items, operation );
+} /* wxMacDataBrowserTableViewControl::SetSelectedItems(UInt32, DataBrowserItemID const*, DataBrowserSetOption) */
+
+OSStatus wxMacDataBrowserTableViewControl::GetSortOrder(DataBrowserSortOrder* order) const
+{
+ return ::GetDataBrowserSortOrder(this->m_controlRef,order);
+}
+
+OSStatus wxMacDataBrowserTableViewControl::GetSortProperty(DataBrowserPropertyID* propertyID) const
+{
+ return ::GetDataBrowserSortProperty(this->m_controlRef,propertyID);
+}
+
+OSStatus wxMacDataBrowserTableViewControl::Resort(DataBrowserItemID container, Boolean sortChildren)
+{
+ return ::SortDataBrowserContainer(this->m_controlRef,container,sortChildren);
+} /* wxMacDataBrowserTableViewControl::Resort(DataBrowserItemID, Boolean) */
+
+OSStatus wxMacDataBrowserTableViewControl::SetSortOrder(DataBrowserSortOrder order)
+{
+ return ::SetDataBrowserSortOrder(this->m_controlRef,order);
+}
+
+OSStatus wxMacDataBrowserTableViewControl::SetSortProperty(DataBrowserPropertyID propertyID)
+{
+ return ::SetDataBrowserSortProperty(this->m_controlRef,propertyID);
+}
+
+//
+// container handling
+//
+OSStatus wxMacDataBrowserTableViewControl::CloseContainer(DataBrowserItemID containerID)
+{
+ return ::CloseDataBrowserContainer(this->m_controlRef,containerID);
+} /* wxMacDataBrowserTableViewControl::CloseContainer(DataBrowserItemID) */
+
+OSStatus wxMacDataBrowserTableViewControl::OpenContainer(DataBrowserItemID containerID)
+{
+ return ::OpenDataBrowserContainer(this->m_controlRef,containerID);
+} /* wxMacDataBrowserTableViewControl::OpenContainer(DataBrowserItemID) */
+
+IMPLEMENT_ABSTRACT_CLASS(wxMacDataBrowserTableViewControl,wxMacControl)
+
+// ============================================================================
+// wxMacDataBrowserListViewControl
+// ============================================================================
+#pragma mark -
+//
+// column handling
+//
+OSStatus wxMacDataBrowserListViewControl::AddColumn(DataBrowserListViewColumnDesc *columnDesc, DataBrowserTableViewColumnIndex position)
+{
+ return AddDataBrowserListViewColumn(this->m_controlRef,columnDesc,position);
+} /* wxMacDataBrowserListViewControl::AddColumn(DataBrowserListViewColumnDesc*, DataBrowserTableViewColumnIndex) */
+
+// ============================================================================
+// wxMacDataViewDataBrowserListViewControl
+// ============================================================================
+#pragma mark -
+//
+// constructors / destructor
+//
+wxMacDataViewDataBrowserListViewControl::wxMacDataViewDataBrowserListViewControl(wxWindow* peer, wxPoint const& pos, wxSize const& size, long style)
+ :wxMacDataBrowserListViewControl(peer,pos,size,style)
+{
+} /* wxMacDataViewDataBrowserListViewControl::wxMacDataViewDataBrowserListViewControl(wxWindow* , const wxPoint&, const wxSize&, long) */
+
+//
+// callback functions (inherited from wxMacDataBrowserTableViewControl)
+//
+Boolean wxMacDataViewDataBrowserListViewControl::DataBrowserCompareProc(DataBrowserItemID itemOneID, DataBrowserItemID itemTwoID, DataBrowserPropertyID sortProperty)
+{
+ DataBrowserSortOrder sortOrder;
+
+ DataBrowserTableViewColumnIndex modelColumnIndex;
+
+ wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast(this->GetPeer()));
+
+
+ wxCHECK_MSG(dataViewCtrlPtr != NULL, false,_("Pointer to data view control not set correctly."));
+ wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,false,_("Pointer to model not set correctly."));
+ if (sortProperty >= kMinPropertyID)
+ {
+ // variable definition and initialization:
+ wxDataViewColumn* ColumnPtr(dataViewCtrlPtr->GetColumnPtr(sortProperty));
+
+ wxCHECK_MSG(ColumnPtr != NULL,false,_("Could not determine column index."));
+ modelColumnIndex = ColumnPtr->GetModelColumn();
+ } /* if */
+ else
+ modelColumnIndex = 0;
+ this->GetSortOrder(&sortOrder);
+ return static_cast(dataViewCtrlPtr->GetModel()->Compare(wxDataViewItem(reinterpret_cast(itemOneID)),wxDataViewItem(reinterpret_cast(itemTwoID)),
+ modelColumnIndex,sortOrder != kDataBrowserOrderDecreasing) < 0);
+} /* wxMacDataViewDataBrowserListViewControl::DataBrowserCompareProc(DataBrowserItemID, DataBrowserItemID, DataBrowserPropertyID) */
+
+void wxMacDataViewDataBrowserListViewControl::DataBrowserGetContextualMenuProc(MenuRef* menu, UInt32* helpType, CFStringRef* helpItemString, AEDesc* WXUNUSED(selection))
+ // In this method we do not supply a contextual menu handler at all but only send a wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU.
+{
+ wxArrayDataBrowserItemID itemIDs;
+
+ wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast(this->GetPeer()));
+
+
+ wxCHECK_RET(dataViewCtrlPtr != NULL,_("wxWidget control pointer is not a data view pointer"));
+ // initialize parameters so that no context menu will be displayed automatically by the native data browser:
+ *menu = NULL;
+ *helpType = kCMHelpItemNoHelp;
+ *helpItemString = NULL;
+ // create information for a context menu event:
+ wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU,dataViewCtrlPtr->GetId());
+
+ dataViewEvent.SetEventObject(dataViewCtrlPtr);
+ dataViewEvent.SetModel(dataViewCtrlPtr->GetModel());
+ // get the item information;
+ // theoretically more than one ID can be returned but the event can only handle one item, therefore all item related data is using the data of the first item in the array:
+ if (this->GetSelectedItemIDs(itemIDs) > 0)
+ dataViewEvent.SetItem(wxDataViewItem(reinterpret_cast(itemIDs[0])));
+ // finally send the equivalent wxWidget event:
+ dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
+} /* wxMacDataViewDataBrowserListViewControl::DataBrowserGetContextualMenuProc(MenuRef*, UInt32*, CFStringRef*, AEDesc*) */
+
+OSStatus wxMacDataViewDataBrowserListViewControl::DataBrowserGetSetItemDataProc(DataBrowserItemID itemID, DataBrowserPropertyID propertyID, DataBrowserItemDataRef itemData, Boolean getValue)
+{
+ if (getValue)
+ {
+ // variable definitions:
+ wxDataViewCtrl* dataViewCtrlPtr;
+
+ dataViewCtrlPtr = dynamic_cast(this->GetPeer());
+ wxCHECK_MSG(dataViewCtrlPtr != NULL,errDataBrowserNotConfigured,_("Pointer to data view control not set correctly."));
+ if (dataViewCtrlPtr->IsDeleting())
+ return noErr; // if a delete process is running the data of editable fields cannot be saved because the associated model variable may already have been deleted
+ else
+ {
+ // variable definitions:
+ OSStatus errorStatus;
+ wxDataViewColumn* dataViewColumnPtr;
+
+ wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,errDataBrowserNotConfigured,_("Pointer to model not set correctly."));
+ dataViewColumnPtr = dataViewCtrlPtr->GetColumnPtr(propertyID);
+ wxCHECK_MSG((dataViewColumnPtr != NULL) && (dataViewColumnPtr->GetRenderer() != NULL),errDataBrowserNotConfigured,_("There is no column or renderer for the specified column index."));
+
+ wxDataViewItem dvItem(reinterpret_cast(itemID));
+ unsigned int col = dataViewColumnPtr->GetModelColumn();
+
+ switch (dataViewColumnPtr->GetRenderer()->GetPropertyType())
+ {
+ case kDataBrowserCheckboxType:
+ {
+ // variable definition:
+ ThemeButtonValue buttonValue;
+
+ errorStatus = ::GetDataBrowserItemDataButtonValue(itemData,&buttonValue);
+ if (errorStatus == noErr)
+ {
+ if (buttonValue == kThemeButtonOn)
+ {
+ // variable definition and initialization:
+ wxVariant modifiedData(true);
+
+ if (dataViewCtrlPtr->GetModel()->SetValue(modifiedData, dvItem, col) &&
+ dataViewCtrlPtr->GetModel()->ValueChanged(dvItem, col))
+ return noErr;
+ else
+ return errDataBrowserInvalidPropertyData;
+ } /* if */
+ else if (buttonValue == kThemeButtonOff)
+ {
+ // variable definition and initialization:
+ wxVariant modifiedData(false);
+
+ if (dataViewCtrlPtr->GetModel()->SetValue(modifiedData, dvItem, col) &&
+ dataViewCtrlPtr->GetModel()->ValueChanged(dvItem, col))
+ return noErr;
+ else
+ return errDataBrowserInvalidPropertyData;
+ } /* if */
+ else
+ return errDataBrowserInvalidPropertyData;
+ } /* if */
+ else
+ return errorStatus;
+ } /* block */
+ case kDataBrowserTextType:
+ {
+ // variable definitions:
+ CFStringRef stringReference;
+
+ errorStatus = ::GetDataBrowserItemDataText(itemData,&stringReference);
+ if (errorStatus == noErr)
+ {
+ // variable definitions and initializations:
+#if wxCHECK_VERSION(2,9,0)
+ wxCFStringRef modifiedString(stringReference);
+#else
+ wxMacCFStringHolder modifiedString(stringReference);
+#endif
+ wxVariant modifiedData(modifiedString.AsString());
+
+ if (dataViewCtrlPtr->GetModel()->SetValue(modifiedData, dvItem, col) &&
+ dataViewCtrlPtr->GetModel()->ValueChanged(dvItem, col))
+ return noErr;
+ else
+ return errDataBrowserInvalidPropertyData;
+ } /* if */
+ else
+ return errorStatus;
+ } /* block */
+ default:
+ return errDataBrowserPropertyNotSupported;
+ } /* switch */
+ } /* if */
+ } /* if */
+ else
+ {
+ if (propertyID >= kMinPropertyID) // in case data columns set the data
+ {
+ // variable definitions:
+ wxVariant variant;
+ wxDataViewColumn* dataViewColumnPtr;
+ wxDataViewCtrl* dataViewCtrlPtr;
+
+ dataViewCtrlPtr = dynamic_cast(this->GetPeer());
+ wxCHECK_MSG(dataViewCtrlPtr != NULL,errDataBrowserNotConfigured,_("Pointer to data view control not set correctly."));
+ wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,errDataBrowserNotConfigured,_("Pointer to model not set correctly."));
+ dataViewColumnPtr = dataViewCtrlPtr->GetColumnPtr(propertyID);
+ wxCHECK_MSG(dataViewColumnPtr != NULL,errDataBrowserNotConfigured,_("No column for the specified column position existing."));
+ wxCHECK_MSG(dataViewColumnPtr->GetRenderer() != NULL,errDataBrowserNotConfigured,_("No renderer specified for column."));
+ dataViewCtrlPtr->GetModel()->GetValue(variant,wxDataViewItem(reinterpret_cast(itemID)),dataViewColumnPtr->GetModelColumn());
+ if (!(variant.IsNull()))
+ {
+ dataViewColumnPtr->GetRenderer()->SetDataReference(itemData);
+ dataViewColumnPtr->GetRenderer()->SetValue(variant);
+ wxCHECK_MSG(dataViewColumnPtr->GetRenderer()->Render(),errDataBrowserNotConfigured,_("Rendering failed."));
+ } /* if */
+ return noErr;
+ } /* if */
+ else // react on special system requests
+ {
+ switch (propertyID)
+ {
+ case kDataBrowserContainerIsClosableProperty:
+ {
+ // variable definitions:
+ wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast(this->GetPeer()));
+
+ wxCHECK_MSG(dataViewCtrlPtr != NULL,errDataBrowserNotConfigured,_("Pointer to data view control not set correctly."));
+ // initialize wxWidget event:
+ wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSING,dataViewCtrlPtr->GetId()); // variable definition
+
+ dataViewEvent.SetEventObject(dataViewCtrlPtr);
+ dataViewEvent.SetItem (wxDataViewItem(reinterpret_cast(itemID)));
+ dataViewEvent.SetModel (dataViewCtrlPtr->GetModel());
+ // finally send the equivalent wxWidget event:
+ dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
+ // opening the container is allowed if not vetoed:
+ return ::SetDataBrowserItemDataBooleanValue(itemData,dataViewEvent.IsAllowed());
+ } /* block */
+ case kDataBrowserContainerIsOpenableProperty:
+ {
+ // variable definitions:
+ wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast(this->GetPeer()));
+
+ wxCHECK_MSG(dataViewCtrlPtr != NULL,errDataBrowserNotConfigured,_("Pointer to data view control not set correctly."));
+ // initialize wxWidget event:
+ wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDING,dataViewCtrlPtr->GetId()); // variable definition
+
+ dataViewEvent.SetEventObject(dataViewCtrlPtr);
+ dataViewEvent.SetItem (wxDataViewItem(reinterpret_cast(itemID)));
+ dataViewEvent.SetModel (dataViewCtrlPtr->GetModel());
+ // finally send the equivalent wxWidget event:
+ dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
+ // opening the container is allowed if not vetoed:
+ return ::SetDataBrowserItemDataBooleanValue(itemData,dataViewEvent.IsAllowed());
+ } /* block */
+ case kDataBrowserItemIsContainerProperty:
+ {
+ // variable definition:
+ wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast(this->GetPeer()));
+
+ wxCHECK_MSG(dataViewCtrlPtr != NULL,errDataBrowserNotConfigured,_("Pointer to data view control not set correctly."));
+ wxCHECK_MSG(dataViewCtrlPtr->GetModel() != NULL,errDataBrowserNotConfigured,_("Pointer to model not set correctly."));
+ return ::SetDataBrowserItemDataBooleanValue(itemData,dataViewCtrlPtr->GetModel()->IsContainer(wxDataViewItem(reinterpret_cast(itemID))));
+ } /* block */
+ case kDataBrowserItemIsEditableProperty:
+ return ::SetDataBrowserItemDataBooleanValue(itemData,true);
+ } /* switch */
+ } /* if */
+ } /* if */
+ return errDataBrowserPropertyNotSupported;
+} /* wxMacDataViewDataBrowserListViewControl::DataBrowserGetSetItemDataProc(DataBrowserItemID, DataBrowserPropertyID, DataBrowserItemDataRef, Boolean) */
+
+void wxMacDataViewDataBrowserListViewControl::DataBrowserItemNotificationProc(DataBrowserItemID itemID, DataBrowserItemNotification message, DataBrowserItemDataRef itemData)
+{
+ wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast(this->GetPeer()));
+
+
+ // check if the data view control pointer still exists because this call back function can still be called when the control has already been deleted:
+ if (dataViewCtrlPtr != NULL)
+ switch (message)
+ {
+ case kDataBrowserContainerClosed:
+ dataViewCtrlPtr->FinishCustomItemEditing(); // stop editing of a custom item first (if necessary)
+ {
+ // initialize wxWidget event:
+ wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSED,dataViewCtrlPtr->GetId()); // variable definition
+
+ dataViewEvent.SetEventObject(dataViewCtrlPtr);
+ dataViewEvent.SetItem(wxDataViewItem(reinterpret_cast(itemID)));
+ // finally send the equivalent wxWidget event:
+ dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
+ } /* block */
+ break;
+ case kDataBrowserContainerOpened:
+ dataViewCtrlPtr->FinishCustomItemEditing(); // stop editing of a custom item first (if necessary)
+ {
+ // initialize wxWidget event:
+ wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDED,dataViewCtrlPtr->GetId()); // variable definition
+
+ dataViewEvent.SetEventObject(dataViewCtrlPtr);
+ dataViewEvent.SetItem(wxDataViewItem(reinterpret_cast(itemID)));
+ // finally send the equivalent wxWidget event:
+ dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
+ // add children to the expanded container:
+ dataViewCtrlPtr->AddChildrenLevel(wxDataViewItem(reinterpret_cast(itemID)));
+ } /* block */
+ break;
+ case kDataBrowserEditStarted:
+ dataViewCtrlPtr->FinishCustomItemEditing(); // stop editing of a custom item first (if necessary)
+ {
+ // initialize wxWidget event:
+ DataBrowserPropertyID propertyID;
+ wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED,dataViewCtrlPtr->GetId()); // variable definition
+
+ dataViewEvent.SetEventObject(dataViewCtrlPtr);
+ dataViewEvent.SetItem(wxDataViewItem(reinterpret_cast(itemID)));
+ if (this->GetPropertyID(itemData,&propertyID) == noErr)
+ {
+ // variable definition and initialization:
+ DataBrowserTableViewColumnIndex columnIndex;
+
+ wxCHECK_RET(this->GetColumnIndex(propertyID,&columnIndex),_("Column index not found."));
+ dataViewEvent.SetColumn(columnIndex);
+ dataViewEvent.SetDataViewColumn(dataViewCtrlPtr->GetColumnPtr(propertyID));
+ } /* if */
+ // finally send the equivalent wxWidget event:
+ dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
+ } /* block */
+ break;
+ case kDataBrowserEditStopped:
+ {
+ // initialize wxWidget event:
+ DataBrowserPropertyID propertyID;
+ wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE,dataViewCtrlPtr->GetId()); // variable definition
+
+ dataViewEvent.SetEventObject(dataViewCtrlPtr);
+ dataViewEvent.SetItem(wxDataViewItem(reinterpret_cast(itemID)));
+ if (this->GetPropertyID(itemData,&propertyID) == noErr)
+ {
+ // variable definition and initialization:
+ DataBrowserTableViewColumnIndex columnIndex;
+
+ wxCHECK_RET(this->GetColumnIndex(propertyID,&columnIndex),_("Column index not found."));
+ dataViewEvent.SetColumn(columnIndex);
+ dataViewEvent.SetDataViewColumn(dataViewCtrlPtr->GetColumnPtr(propertyID));
+ } /* if */
+ // finally send the equivalent wxWidget event:
+ dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
+ } /* block */
+ break;
+ case kDataBrowserItemAdded:
+ dataViewCtrlPtr->FinishCustomItemEditing();
+ break;
+ case kDataBrowserItemDeselected:
+ dataViewCtrlPtr->FinishCustomItemEditing();
+ break;
+ case kDataBrowserItemDoubleClicked:
+ {
+ // initialize wxWidget event:
+ wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED,dataViewCtrlPtr->GetId()); // variable definition
+
+ dataViewEvent.SetEventObject(dataViewCtrlPtr);
+ dataViewEvent.SetItem(wxDataViewItem(reinterpret_cast(itemID)));
+ // finally send the equivalent wxWidget event:
+ dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
+ } /* block */
+ break;
+ case kDataBrowserItemRemoved:
+ dataViewCtrlPtr->FinishCustomItemEditing(); // stop editing of a custom item first (if necessary)
+ break;
+ case kDataBrowserItemSelected:
+ break; // not implemented by wxWidgets; see kDataBrowserSelectionSetChanged
+ case kDataBrowserSelectionSetChanged:
+ {
+ // initialize wxWidget event:
+ wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED,dataViewCtrlPtr->GetId()); // variable definition
+
+ dataViewEvent.SetEventObject(dataViewCtrlPtr);
+ dataViewEvent.SetModel (dataViewCtrlPtr->GetModel());
+ // finally send the equivalent wxWidget event:
+ dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
+ } /* block */
+ break;
+ case kDataBrowserTargetChanged: // no idea if this notification is ever sent
+ break;
+ case kDataBrowserUserStateChanged:
+ {
+ // finish custom item editing if necessary:
+ dataViewCtrlPtr->FinishCustomItemEditing();
+ // update column widths:
+ for (size_t i=0; iGetColumnCount(); ++i)
+ {
+ // constant definition for abbreviational purposes:
+ wxDataViewColumn* const columnPtr = dataViewCtrlPtr->GetColumn(i);
+ // variable definition:
+ UInt16 columnWidth;
+
+ wxCHECK_RET(this->GetColumnWidth(columnPtr->GetPropertyID(),&columnWidth) == noErr,_("Column width could not be determined"));
+ columnPtr->SetWidthVariable(columnWidth);
+ } /* for */
+ // update sorting orders:
+ DataBrowserPropertyID propertyID; // variable definition
+
+ if ((this->GetSortProperty(&propertyID) == noErr) && (propertyID >= kMinPropertyID))
+ {
+ DataBrowserSortOrder sortOrder;
+ DataBrowserTableViewColumnIndex columnIndex;
+
+ if ((this->GetSortOrder(&sortOrder) == noErr) && (this->GetColumnIndex(propertyID,&columnIndex) == noErr))
+ {
+ // variable definition and initialization:
+ wxDataViewColumn* columnPtr;
+ columnPtr = dataViewCtrlPtr->GetColumn(columnIndex);
+ // check if the sort order has changed:
+ if ( columnPtr->IsSortOrderAscending() && (sortOrder == kDataBrowserOrderDecreasing) ||
+ !(columnPtr->IsSortOrderAscending()) && (sortOrder == kDataBrowserOrderIncreasing))
+ {
+ columnPtr->SetSortOrder(!(columnPtr->IsSortOrderAscending()));
+ // initialize wxWidget event:
+ wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED,dataViewCtrlPtr->GetId()); // variable defintion
+
+ dataViewEvent.SetEventObject(dataViewCtrlPtr);
+ dataViewEvent.SetColumn(columnIndex);
+ dataViewEvent.SetDataViewColumn(columnPtr);
+ // finally send the equivalent wxWidget event:
+ dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
+ } /* if */
+ } /* if */
+ } /* if */
+ } /* block */
+ break;
+ } /* switch */
+} /* wxMacDataViewDataBrowserListViewControl::DataBrowserItemNotificationProc(DataBrowserItemID, DataBrowserItemNotification, DataBrowserItemDataRef) */
+
+void wxMacDataViewDataBrowserListViewControl::DataBrowserDrawItemProc(DataBrowserItemID itemID, DataBrowserPropertyID propertyID, DataBrowserItemState state, Rect const* rectangle, SInt16 bitDepth, Boolean colorDevice)
+{
+ DataBrowserTableViewColumnIndex columnIndex;
+
+ wxDataViewColumn* dataViewColumnPtr;
+
+ wxDataViewCtrl* dataViewCtrlPtr;
+
+ wxDataViewCustomRenderer* dataViewCustomRendererPtr;
+
+ wxVariant dataToRender;
+
+ dataViewCtrlPtr = dynamic_cast(this->GetPeer());
+ wxCHECK_RET(dataViewCtrlPtr != NULL, _("Pointer to data view control not set correctly."));
+ wxCHECK_RET(dataViewCtrlPtr->GetModel() != NULL,_("Pointer to model not set correctly."));
+ wxCHECK_RET(this->GetColumnIndex(propertyID,&columnIndex) == noErr,_("Could not determine column index."));
+ dataViewColumnPtr = dataViewCtrlPtr->GetColumnPtr(propertyID);
+ wxCHECK_RET(dataViewColumnPtr != NULL,_("No column for the specified column index existing."));
+ dataViewCustomRendererPtr = dynamic_cast(dataViewColumnPtr->GetRenderer());
+ wxCHECK_RET(dataViewCustomRendererPtr != NULL,_("No renderer or invalid renderer type specified for custom data column."));
+ dataViewCtrlPtr->GetModel()->GetValue(dataToRender,wxDataViewItem(reinterpret_cast(itemID)),dataViewColumnPtr->GetModelColumn());
+ dataViewCustomRendererPtr->SetValue(dataToRender);
+
+ wxDataViewItem dataitem( reinterpret_cast(itemID) );
+ dataViewCtrlPtr->GetModel()->GetValue(dataToRender,dataitem,dataViewColumnPtr->GetModelColumn());
+ dataViewCustomRendererPtr->SetValue(dataToRender);
+
+ // try to determine the content's size (drawable part):
+ Rect content;
+ RgnHandle rgn(NewRgn());
+ UInt16 headerHeight;
+
+ if (this->GetRegion(kControlContentMetaPart,rgn) == noErr)
+ GetRegionBounds(rgn,&content);
+ else
+ this->GetRect(&content);
+ ::DisposeRgn(rgn);
+ // space for the header
+ this->GetHeaderButtonHeight(&headerHeight);
+ content.top += headerHeight;
+ // extra space for the frame (todo: do not how to determine the space automatically from the control)
+ content.top += 5;
+ content.left += 5;
+ content.right -= 3;
+ content.bottom -= 3;
+ // extra space for the scrollbars:
+ content.bottom -= wxSystemSettings::GetMetric(wxSYS_HSCROLL_Y);
+ content.right -= wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
+
+ wxDC *dc = dataViewCustomRendererPtr->GetDC();
+
+ wxRect cellrect( static_cast(rectangle->left),
+ static_cast(rectangle->top+2),
+ static_cast(1+rectangle->right-rectangle->left),
+ static_cast(rectangle->bottom-rectangle->top) );
+
+ bool is_active = IsControlActive( this->m_controlRef );
+ if (state == kDataBrowserItemIsSelected)
+ {
+
+ wxColour col( wxMacCreateCGColorFromHITheme( (is_active) ?
+ kThemeBrushAlternatePrimaryHighlightColor
+ : kThemeBrushSecondaryHighlightColor ) );
+
+ wxRect rect = cellrect;
+ Rect itemrect;
+ GetDataBrowserItemPartBounds( this->m_controlRef, itemID, propertyID,
+ kDataBrowserPropertyEnclosingPart, &itemrect );
+ rect.x = itemrect.left;
+ rect.width = itemrect.right-itemrect.left+1;
+
+ wxBrush selBrush( col );
+ wxPen oldpen( dc->GetPen() );
+ wxBrush oldbrush( dc->GetBrush() );
+ dc->SetPen( *wxTRANSPARENT_PEN );
+ dc->SetBrush( selBrush );
+ dc->DrawRectangle(rect);
+ dc->SetBrush( oldbrush );
+ dc->SetPen( oldpen );
+ }
+
+ wxDataViewModel *model = dataViewCtrlPtr->GetModel();
+ if ((columnIndex == 0) || !model->IsContainer(dataitem) || model->HasContainerColumns(dataitem))
+ {
+ // make sure that 'Render' can draw only in the allowed area:
+ dc->SetClippingRegion(content.left,content.top,content.right-content.left+1,content.bottom-content.top+1);
+ (void) (dataViewCustomRendererPtr->Render( cellrect, dc,
+ ((state == kDataBrowserItemIsSelected) ? wxDATAVIEW_CELL_SELECTED : 0)));
+ dc->DestroyClippingRegion(); // probably not necessary
+ }
+
+ dataViewCustomRendererPtr->SetDC(NULL);
+} /* wxMacDataViewDataBrowserListViewControl::DataBrowserDrawItemProc(DataBrowserItemID, DataBrowserPropertyID, DataBrowserItemState, Rect const*, SInt16, Boolean) */
+
+Boolean wxMacDataViewDataBrowserListViewControl::DataBrowserEditItemProc(DataBrowserItemID itemID, DataBrowserPropertyID propertyID, CFStringRef theString, Rect* maxEditTextRect, Boolean* shrinkToFit)
+{
+ return false;
+} /* wxMacDataViewDataBrowserListViewControl::DataBrowserEditItemProc(DataBrowserItemID, DataBrowserPropertyID, CFStringRef, Rect*, Boolean*) */
+
+Boolean wxMacDataViewDataBrowserListViewControl::DataBrowserHitTestProc(DataBrowserItemID WXUNUSED(itemID), DataBrowserPropertyID WXUNUSED(property), Rect const* WXUNUSED(theRect), Rect const* WXUNUSED(mouseRect))
+{
+ return true;
+} /* wxMacDataViewDataBrowserListViewControl::DataBrowserHitTestProc(DataBrowserItemID, DataBrowserPropertyID, Rect const*, Rect const*) */
+
+DataBrowserTrackingResult wxMacDataViewDataBrowserListViewControl::DataBrowserTrackingProc(DataBrowserItemID itemID, DataBrowserPropertyID propertyID, Rect const* theRect, Point WXUNUSED(startPt), EventModifiers WXUNUSED(modifiers))
+{
+ wxDataViewColumn* dataViewColumnPtr;
+
+ wxDataViewCtrl* dataViewCtrlPtr;
+
+ wxDataViewCustomRenderer* dataViewCustomRendererPtr;
+
+ wxDataViewItem dataViewCustomRendererItem;
+
+
+ dataViewCustomRendererItem = reinterpret_cast(itemID);
+ wxCHECK_MSG(dataViewCustomRendererItem.IsOk(),kDataBrowserNothingHit,_("Invalid data view item"));
+ dataViewCtrlPtr = dynamic_cast(this->GetPeer());
+ wxCHECK_MSG(dataViewCtrlPtr != NULL,kDataBrowserNothingHit,_("Pointer to data view control not set correctly."));
+ dataViewColumnPtr = dataViewCtrlPtr->GetColumnPtr(propertyID);
+ wxCHECK_MSG(dataViewColumnPtr != NULL,kDataBrowserNothingHit,_("No column existing."));
+ dataViewCustomRendererPtr = dynamic_cast(dataViewColumnPtr->GetRenderer());
+ wxCHECK_MSG(dataViewCustomRendererPtr != NULL,kDataBrowserNothingHit,_("No renderer or invalid renderer type specified for custom data column."));
+ // if the currently edited item is identical to the to be edited nothing is done (this hit should only be handled in the control itself):
+ if (dataViewCtrlPtr->GetCustomRendererItem() == dataViewCustomRendererItem)
+ return kDataBrowserContentHit;
+ // an(other) item is going to be edited and therefore the current editing - if existing - has to be finished:
+ if (dataViewCtrlPtr->GetCustomRendererPtr() != NULL)
+ {
+ dataViewCtrlPtr->GetCustomRendererPtr()->FinishEditing();
+ dataViewCtrlPtr->SetCustomRendererItem(wxDataViewItem());
+ dataViewCtrlPtr->SetCustomRendererPtr (NULL);
+ } /* if */
+ // check if renderer has got a valid editor control for editing; if this is the case start editing of the new item:
+ if (dataViewCustomRendererPtr->HasEditorCtrl())
+ {
+ // variable definition:
+ wxRect wxRectangle;
+
+ ::wxMacNativeToRect(theRect,&wxRectangle);
+ dataViewCustomRendererPtr->StartEditing(dataViewCustomRendererItem,wxRectangle);
+ dataViewCtrlPtr->SetCustomRendererItem(dataViewCustomRendererItem);
+ dataViewCtrlPtr->SetCustomRendererPtr (dataViewCustomRendererPtr);
+ } /* if */
+ return kDataBrowserContentHit;
+} /* wxMacDataViewDataBrowserListViewControl::DataBrowserTrackingProc(DataBrowserItemID, DataBrowserPropertyID, Rect const*, Point, EventModifiers) */
+
+#endif // wxUSE_GENERICDATAVIEWCTRL
+#endif // wxUSE_DATAVIEWCTRL
diff --git a/src/osx/carbon/dataobj.cpp b/src/osx/carbon/dataobj.cpp
new file mode 100644
index 0000000000..cdec68b05d
--- /dev/null
+++ b/src/osx/carbon/dataobj.cpp
@@ -0,0 +1,753 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/dataobj.cpp
+// Purpose: implementation of wxDataObject class
+// Author: Stefan Csomor
+// Modified by:
+// Created: 10/21/99
+// RCS-ID: $Id$
+// Copyright: (c) 1999 Stefan Csomor
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#if wxUSE_DATAOBJ
+
+#include "wx/dataobj.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/intl.h"
+ #include "wx/log.h"
+ #include "wx/dcmemory.h"
+ #include "wx/image.h"
+#endif
+
+#include "wx/mstream.h"
+#include "wx/metafile.h"
+#include "wx/tokenzr.h"
+
+#include "wx/mac/uma.h"
+
+#ifdef __DARWIN__
+ #include
+#endif
+
+
+// ----------------------------------------------------------------------------
+// wxDataFormat
+// ----------------------------------------------------------------------------
+
+wxDataFormat::wxDataFormat()
+{
+ m_type = wxDF_INVALID;
+ m_format = 0;
+}
+
+wxDataFormat::wxDataFormat( wxDataFormatId vType )
+{
+ m_format = 0;
+ m_type = wxDF_INVALID;
+ SetType( vType );
+}
+
+wxDataFormat::wxDataFormat( const wxChar *zId )
+{
+ m_format = 0;
+ m_type = wxDF_INVALID;
+ SetId( zId );
+}
+
+wxDataFormat::wxDataFormat( const wxString& rId )
+{
+ m_format = 0;
+ m_type = wxDF_INVALID;
+ SetId( rId );
+}
+
+wxDataFormat::wxDataFormat(const wxDataFormat& rFormat)
+{
+ if ( rFormat.m_format )
+ m_format = (NativeFormat) CFStringCreateCopy(NULL, (CFStringRef)rFormat.m_format);
+ else
+ m_format = 0;
+ m_type = rFormat.m_type;
+ m_id = rFormat.m_id;
+}
+
+wxDataFormat::wxDataFormat( NativeFormat vFormat )
+{
+ m_format = 0;
+ m_type = wxDF_INVALID;
+ SetId( vFormat );
+}
+
+wxDataFormat::~wxDataFormat()
+{
+ if ( m_format != 0 )
+ {
+ CFRelease( (CFStringRef) m_format );
+ m_format = 0;
+ }
+}
+
+// in order to be correct for 10.3 we restrict to the available types there
+// http://developer.apple.com/qa/qa2005/qa1406.html
+// TODO : Use UTCoreTypes.h constants once we support 10.4+ only
+
+wxDataFormat& wxDataFormat::operator=(const wxDataFormat& rFormat)
+{
+ if ( m_format != 0 )
+ {
+ CFRelease( (CFStringRef) m_format );
+ m_format = 0;
+ }
+ if ( rFormat.m_format )
+ m_format = (NativeFormat) CFStringCreateCopy(NULL, (CFStringRef)rFormat.m_format);
+ m_type = rFormat.m_type;
+ m_id = rFormat.m_id;
+ return *this;
+}
+
+void wxDataFormat::SetType( wxDataFormatId dataType )
+{
+ m_type = dataType;
+ if ( m_format != 0 )
+ {
+ CFRelease( (CFStringRef) m_format );
+ m_format = 0;
+ }
+
+ switch (m_type)
+ {
+ case wxDF_TEXT:
+ m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.plain-text") );
+ break;
+
+ case wxDF_UNICODETEXT:
+ m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.utf16-plain-text") );
+ break;
+
+ case wxDF_BITMAP:
+ m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.tiff") );
+ break;
+ case wxDF_METAFILE:
+ m_format = (long) CFStringCreateCopy( NULL, CFSTR("com.adobe.pdf") );
+ break;
+
+ case wxDF_FILENAME:
+ m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.file-url") );
+ break;
+
+ default:
+ wxFAIL_MSG( wxT("invalid data format") );
+ break;
+ }
+}
+
+wxString wxDataFormat::GetId() const
+{
+ return wxCFStringRef(wxCFRetain((CFStringRef)m_format)).AsString();
+}
+
+void wxDataFormat::SetId( NativeFormat format )
+{
+ if ( m_format != 0 )
+ {
+ CFRelease( (CFStringRef) m_format );
+ m_format = 0;
+ }
+ m_format = (NativeFormat) CFStringCreateCopy(NULL, (CFStringRef)format);
+ if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("public.utf16-plain-text") ) )
+ {
+ m_type = wxDF_UNICODETEXT;
+ }
+ else if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("public.plain-text") ) )
+ {
+ m_type = wxDF_TEXT;
+ }
+ else if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("public.tiff") ) )
+ {
+ m_type = wxDF_BITMAP;
+ }
+ else if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("com.adobe.pdf") ) )
+ {
+ m_type = wxDF_METAFILE;
+ }
+ else if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("public.file-url") ) )
+ {
+ m_type = wxDF_FILENAME;
+ }
+ else
+ {
+ m_type = wxDF_PRIVATE;
+ m_id = wxCFStringRef( (CFStringRef) CFRetain((CFStringRef) format )).AsString();
+ }
+}
+
+void wxDataFormat::SetId( const wxString& zId )
+{
+ m_type = wxDF_PRIVATE;
+ m_id = zId;
+ if ( m_format != 0 )
+ {
+ CFRelease( (CFStringRef) m_format );
+ m_format = 0;
+ }
+ // since it is private, no need to conform to anything ...
+ m_format = (long) wxCFRetain( (CFStringRef) wxCFStringRef(m_id) );
+}
+
+bool wxDataFormat::operator==(const wxDataFormat& format) const
+{
+ if (IsStandard() || format.IsStandard())
+ return (format.m_type == m_type);
+ else
+ return ( UTTypeConformsTo( (CFStringRef) m_format , (CFStringRef) format.m_format ) );
+}
+
+//-------------------------------------------------------------------------
+// wxDataObject
+//-------------------------------------------------------------------------
+
+wxDataObject::wxDataObject()
+{
+}
+
+bool wxDataObject::IsSupportedFormat( const wxDataFormat& rFormat, Direction vDir ) const
+{
+ size_t nFormatCount = GetFormatCount( vDir );
+ bool found = false;
+
+ if (nFormatCount == 1)
+ {
+ found = (rFormat == GetPreferredFormat());
+ }
+ else
+ {
+ wxDataFormat *pFormats = new wxDataFormat[nFormatCount];
+ GetAllFormats( pFormats, vDir );
+
+ for (size_t n = 0; n < nFormatCount; n++)
+ {
+ if (pFormats[n] == rFormat)
+ {
+ found = true;
+ break;
+ }
+ }
+
+ delete [] pFormats;
+ }
+
+ return found;
+}
+
+void wxDataObject::AddToPasteboard( void * pb, int itemID )
+{
+ PasteboardRef pasteboard = (PasteboardRef) pb;
+ // get formats from wxDataObjects
+ wxDataFormat *array = new wxDataFormat[ GetFormatCount() ];
+ GetAllFormats( array );
+
+ for (size_t i = 0; i < GetFormatCount(); i++)
+ {
+ wxDataFormat thisFormat = array[ i ];
+
+ // add four bytes at the end for data objs like text that
+ // have a datasize = strlen but still need a buffer for the
+ // string including trailing zero
+
+ size_t datasize = GetDataSize( thisFormat );
+ size_t sz = datasize + 4;
+ void* buf = malloc( sz );
+ if ( buf != NULL )
+ {
+ // empty the buffer because in some case GetDataHere does not fill buf
+ memset( buf, 0, sz );
+ if ( GetDataHere( array[ i ], buf ) )
+ {
+ int counter = 1 ;
+ if ( thisFormat.GetType() == wxDF_FILENAME )
+ {
+ // the data is D-normalized UTF8 strings of filenames delimited with \n
+ char *fname = strtok((char*) buf,"\n");
+ while (fname != NULL)
+ {
+ // translate the filepath into a fileurl and put that into the pasteobard
+ CFStringRef path = CFStringCreateWithBytes(NULL,(UInt8*)fname,strlen(fname),kCFStringEncodingUTF8,false);
+ CFURLRef url = CFURLCreateWithFileSystemPath(NULL, path , kCFURLPOSIXPathStyle, false);
+ CFRelease(path);
+ CFDataRef data = CFURLCreateData(NULL,url,kCFStringEncodingUTF8,true);
+ CFRelease(url);
+ PasteboardPutItemFlavor( pasteboard, (PasteboardItemID) counter,
+ (CFStringRef) thisFormat.GetFormatId() , data, kPasteboardFlavorNoFlags);
+ CFRelease( data );
+ counter++;
+ fname = strtok (NULL,"\n");
+ }
+
+ }
+ else
+ {
+ CFDataRef data = CFDataCreate( kCFAllocatorDefault, (UInt8*)buf, datasize );
+ if ( thisFormat.GetType() == wxDF_TEXT )
+ PasteboardPutItemFlavor( pasteboard, (PasteboardItemID) itemID,
+ CFSTR("com.apple.traditional-mac-plain-text") , data, kPasteboardFlavorNoFlags);
+ else
+ PasteboardPutItemFlavor( pasteboard, (PasteboardItemID) itemID,
+ (CFStringRef) thisFormat.GetFormatId() , data, kPasteboardFlavorNoFlags);
+ CFRelease( data );
+ }
+ }
+ free( buf );
+ }
+ }
+
+ delete [] array;
+}
+
+bool wxDataObject::IsFormatInPasteboard( void * pb, const wxDataFormat &dataFormat )
+{
+ PasteboardRef pasteboard = (PasteboardRef) pb;
+ bool hasData = false;
+ OSStatus err = noErr;
+ ItemCount itemCount;
+
+ // we synchronize here once again, so we don't mind which flags get returned
+ PasteboardSynchronize( pasteboard );
+
+ err = PasteboardGetItemCount( pasteboard, &itemCount );
+ if ( err == noErr )
+ {
+ for( UInt32 itemIndex = 1; itemIndex <= itemCount && hasData == false ; itemIndex++ )
+ {
+ PasteboardItemID itemID;
+ CFArrayRef flavorTypeArray;
+ CFIndex flavorCount;
+
+ err = PasteboardGetItemIdentifier( pasteboard, itemIndex, &itemID );
+ if ( err != noErr )
+ continue;
+
+ err = PasteboardCopyItemFlavors( pasteboard, itemID, &flavorTypeArray );
+ if ( err != noErr )
+ continue;
+
+ flavorCount = CFArrayGetCount( flavorTypeArray );
+
+ for( CFIndex flavorIndex = 0; flavorIndex < flavorCount && hasData == false ; flavorIndex++ )
+ {
+ CFStringRef flavorType;
+
+ flavorType = (CFStringRef)CFArrayGetValueAtIndex( flavorTypeArray,
+ flavorIndex );
+
+ wxDataFormat flavorFormat( (wxDataFormat::NativeFormat) flavorType );
+ if ( dataFormat == flavorFormat )
+ hasData = true;
+ else if ( dataFormat.GetType() == wxDF_UNICODETEXT && flavorFormat.GetType() == wxDF_TEXT )
+ hasData = true;
+ }
+ CFRelease (flavorTypeArray);
+ }
+ }
+
+ return hasData;
+}
+
+bool wxDataObject::GetFromPasteboard( void * pb )
+{
+ PasteboardRef pasteboard = (PasteboardRef) pb;
+ size_t formatcount = GetFormatCount() + 1;
+ wxDataFormat *array = new wxDataFormat[ formatcount ];
+ array[0] = GetPreferredFormat();
+ GetAllFormats( &array[1] );
+ ItemCount itemCount = 0;
+ wxString filenamesPassed;
+ bool transferred = false;
+
+ // we synchronize here once again, so we don't mind which flags get returned
+ PasteboardSynchronize( pasteboard );
+
+ OSStatus err = PasteboardGetItemCount( pasteboard, &itemCount );
+ if ( err == noErr )
+ {
+ for (size_t i = 0; !transferred && i < formatcount; i++)
+ {
+ // go through the data in our order of preference
+ wxDataFormat dataFormat = array[ i ];
+
+ for( UInt32 itemIndex = 1; itemIndex <= itemCount && transferred == false ; itemIndex++ )
+ {
+ PasteboardItemID itemID = 0;
+ CFArrayRef flavorTypeArray = NULL;
+ CFIndex flavorCount = 0;
+
+ err = PasteboardGetItemIdentifier( pasteboard, itemIndex, &itemID );
+ if ( err != noErr )
+ continue;
+
+ err = PasteboardCopyItemFlavors( pasteboard, itemID, &flavorTypeArray );
+ if ( err != noErr )
+ continue;
+
+ flavorCount = CFArrayGetCount( flavorTypeArray );
+
+ for( CFIndex flavorIndex = 0; !transferred && flavorIndex < flavorCount ; flavorIndex++ )
+ {
+ CFStringRef flavorType;
+ CFDataRef flavorData;
+ CFIndex flavorDataSize;
+
+ flavorType = (CFStringRef)CFArrayGetValueAtIndex( flavorTypeArray,
+ flavorIndex );
+
+ wxDataFormat flavorFormat( (wxDataFormat::NativeFormat) flavorType );
+
+ if ( dataFormat == flavorFormat )
+ {
+ err = PasteboardCopyItemFlavorData( pasteboard, itemID, flavorType , &flavorData );
+ if ( err == noErr )
+ {
+ flavorDataSize = CFDataGetLength( flavorData );
+ if (dataFormat.GetType() == wxDF_FILENAME )
+ {
+ // revert the translation and decomposition to arrive at a proper utf8 string again
+ CFURLRef url = CFURLCreateWithBytes( kCFAllocatorDefault, CFDataGetBytePtr( flavorData ), flavorDataSize, kCFStringEncodingUTF8, NULL );
+ CFStringRef cfString = CFURLCopyFileSystemPath( url, kCFURLPOSIXPathStyle );
+ CFRelease( url );
+ CFMutableStringRef cfMutableString = CFStringCreateMutableCopy(NULL, 0, cfString);
+ CFRelease( cfString );
+ CFStringNormalize(cfMutableString,kCFStringNormalizationFormC);
+ wxString path = wxCFStringRef(cfMutableString).AsString();
+ if (!path.empty())
+ filenamesPassed += path + wxT("\n");
+ }
+ else
+ {
+ // because some data implementation expect trailing a trailing NUL, we add some headroom
+ void *buf = malloc( flavorDataSize + 4 );
+ if ( buf )
+ {
+ memset( buf, 0, flavorDataSize + 4 );
+ memcpy( buf, CFDataGetBytePtr( flavorData ), flavorDataSize );
+
+ if (dataFormat.GetType() == wxDF_TEXT)
+ wxMacConvertNewlines10To13( (char*) buf );
+ SetData( flavorFormat, flavorDataSize, buf );
+ transferred = true;
+ free( buf );
+ }
+ }
+ CFRelease (flavorData);
+ }
+ }
+ else if ( dataFormat.GetType() == wxDF_UNICODETEXT && flavorFormat.GetType() == wxDF_TEXT )
+ {
+ err = PasteboardCopyItemFlavorData( pasteboard, itemID, flavorType, &flavorData );
+ if ( err == noErr )
+ {
+ flavorDataSize = CFDataGetLength( flavorData );
+ void *asciibuf = malloc( flavorDataSize + 1 );
+ if ( asciibuf )
+ {
+ memset( asciibuf, 0, flavorDataSize + 1 );
+ memcpy( asciibuf, CFDataGetBytePtr( flavorData ), flavorDataSize );
+ CFRelease (flavorData);
+
+ SetData( wxDF_TEXT, flavorDataSize, asciibuf );
+ transferred = true;
+ free( asciibuf );
+ }
+ else
+ CFRelease (flavorData);
+ }
+ }
+ }
+ CFRelease( flavorTypeArray );
+ }
+ if (filenamesPassed.length() > 0)
+ {
+ wxCharBuffer buf = filenamesPassed.fn_str();
+ SetData( wxDF_FILENAME, strlen( buf ), (const char*)buf );
+ transferred = true;
+ }
+ }
+ }
+ return transferred;
+}
+
+bool wxDataObject::HasDataInPasteboard( void * pb )
+{
+ PasteboardRef pasteboard = (PasteboardRef) pb;
+ size_t formatcount = GetFormatCount() + 1;
+ wxDataFormat *array = new wxDataFormat[ formatcount ];
+ array[0] = GetPreferredFormat();
+ GetAllFormats( &array[1] );
+ ItemCount itemCount = 0;
+ bool hasData = false;
+
+ // we synchronize here once again, so we don't mind which flags get returned
+ PasteboardSynchronize( pasteboard );
+
+ OSStatus err = PasteboardGetItemCount( pasteboard, &itemCount );
+ if ( err == noErr )
+ {
+ for (size_t i = 0; !hasData && i < formatcount; i++)
+ {
+ // go through the data in our order of preference
+ wxDataFormat dataFormat = array[ i ];
+
+ for( UInt32 itemIndex = 1; itemIndex <= itemCount && hasData == false ; itemIndex++ )
+ {
+ PasteboardItemID itemID = 0;
+ CFArrayRef flavorTypeArray = NULL;
+ CFIndex flavorCount = 0;
+
+ err = PasteboardGetItemIdentifier( pasteboard, itemIndex, &itemID );
+ if ( err != noErr )
+ continue;
+
+ err = PasteboardCopyItemFlavors( pasteboard, itemID, &flavorTypeArray );
+ if ( err != noErr )
+ continue;
+
+ flavorCount = CFArrayGetCount( flavorTypeArray );
+
+ for( CFIndex flavorIndex = 0; !hasData && flavorIndex < flavorCount ; flavorIndex++ )
+ {
+ CFStringRef flavorType;
+
+ flavorType = (CFStringRef)CFArrayGetValueAtIndex( flavorTypeArray,
+ flavorIndex );
+
+ wxDataFormat flavorFormat( (wxDataFormat::NativeFormat) flavorType );
+
+ if ( dataFormat == flavorFormat ||
+ dataFormat.GetType() == wxDF_UNICODETEXT && flavorFormat.GetType() == wxDF_TEXT )
+ {
+ hasData = true;
+ }
+ }
+ CFRelease( flavorTypeArray );
+ }
+ }
+ }
+ return hasData;
+}
+
+// ----------------------------------------------------------------------------
+// wxTextDataObject
+// ----------------------------------------------------------------------------
+
+#if wxUSE_UNICODE
+void wxTextDataObject::GetAllFormats(wxDataFormat *formats,
+ wxDataObjectBase::Direction WXUNUSED(dir)) const
+{
+ *formats++ = wxDataFormat( wxDF_TEXT );
+ *formats = wxDataFormat( wxDF_UNICODETEXT );
+}
+#endif
+
+// ----------------------------------------------------------------------------
+// wxFileDataObject
+// ----------------------------------------------------------------------------
+
+void wxFileDataObject::GetFileNames( wxCharBuffer &buf ) const
+{
+ wxString filenames;
+
+ for (size_t i = 0; i < m_filenames.GetCount(); i++)
+ {
+ filenames += m_filenames[i];
+ filenames += wxT('\n');
+ }
+
+ buf = filenames.fn_str();
+}
+
+bool wxFileDataObject::GetDataHere( void *pBuf ) const
+{
+ if (pBuf == NULL)
+ return false;
+
+ wxCharBuffer buf;
+ size_t buffLength;
+
+ GetFileNames( buf );
+ buffLength = strlen( buf );
+ memcpy( pBuf, (const char*)buf, buffLength + 1 );
+
+ return true;
+}
+
+size_t wxFileDataObject::GetDataSize() const
+{
+ wxCharBuffer buf;
+ size_t buffLength;
+
+ GetFileNames( buf );
+ buffLength = strlen( buf );
+ // terminating 0
+ return buffLength + 1;
+}
+
+bool wxFileDataObject::SetData( size_t WXUNUSED(nSize), const void *pBuf )
+{
+ wxString filenames;
+
+#if wxUSE_UNICODE
+ filenames = wxString( (const char*)pBuf, *wxConvFileName );
+#else
+ filenames = wxString (wxConvLocal.cWC2WX(wxConvFileName->cMB2WC( (const char*)pBuf)));
+#endif
+
+ m_filenames = wxStringTokenize( filenames, wxT("\n"), wxTOKEN_STRTOK );
+
+ return true;
+}
+
+void wxFileDataObject::AddFile( const wxString& rFilename )
+{
+ m_filenames.Add( rFilename );
+}
+
+// ----------------------------------------------------------------------------
+// wxBitmapDataObject
+// ----------------------------------------------------------------------------
+
+wxBitmapDataObject::wxBitmapDataObject()
+{
+ Init();
+}
+
+wxBitmapDataObject::wxBitmapDataObject( const wxBitmap& rBitmap )
+: wxBitmapDataObjectBase( rBitmap )
+{
+ Init();
+
+ if (m_bitmap.Ok())
+ {
+ SetBitmap( rBitmap );
+ }
+}
+
+wxBitmapDataObject::~wxBitmapDataObject()
+{
+ Clear();
+}
+
+void wxBitmapDataObject::SetBitmap( const wxBitmap& rBitmap )
+{
+ Clear();
+ wxBitmapDataObjectBase::SetBitmap( rBitmap );
+ if (m_bitmap.Ok())
+ {
+ CGImageRef cgImageRef = (CGImageRef) m_bitmap.CreateCGImage();
+
+ CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, 0);
+ CGImageDestinationRef destination = CGImageDestinationCreateWithData( data , kUTTypeTIFF , 1 , NULL );
+ if ( destination )
+ {
+ CGImageDestinationAddImage( destination, cgImageRef, NULL );
+ CGImageDestinationFinalize( destination );
+ CFRelease( destination );
+ }
+ m_pictHandle = NewHandle(CFDataGetLength(data));
+ if ( m_pictHandle )
+ {
+ memcpy( *(Handle)m_pictHandle, (const char *)CFDataGetBytePtr(data), CFDataGetLength(data) );
+ }
+ CFRelease( data );
+
+ CGImageRelease(cgImageRef);
+ }
+}
+
+void wxBitmapDataObject::Init()
+{
+ m_pictHandle = NULL;
+ m_pictCreated = false;
+}
+
+void wxBitmapDataObject::Clear()
+{
+ if (m_pictHandle != NULL)
+ {
+ DisposeHandle( (Handle) m_pictHandle );
+ m_pictHandle = NULL;
+ }
+ m_pictCreated = false;
+}
+
+bool wxBitmapDataObject::GetDataHere( void *pBuf ) const
+{
+ if (m_pictHandle == NULL)
+ {
+ wxFAIL_MSG( wxT("attempt to copy empty bitmap failed") );
+ return false;
+ }
+
+ if (pBuf == NULL)
+ return false;
+
+ memcpy( pBuf, *(Handle)m_pictHandle, GetHandleSize( (Handle)m_pictHandle ) );
+
+ return true;
+}
+
+size_t wxBitmapDataObject::GetDataSize() const
+{
+ if (m_pictHandle != NULL)
+ return GetHandleSize( (Handle)m_pictHandle );
+ else
+ return 0;
+}
+
+Handle MacCreateDataReferenceHandle(Handle theDataHandle)
+{
+ Handle dataRef = NULL;
+ OSErr err = noErr;
+
+ // Create a data reference handle for our data.
+ err = PtrToHand( &theDataHandle, &dataRef, sizeof(Handle));
+
+ return dataRef;
+}
+
+bool wxBitmapDataObject::SetData( size_t nSize, const void *pBuf )
+{
+ Clear();
+
+ if ((pBuf == NULL) || (nSize == 0))
+ return false;
+
+ Handle picHandle = NewHandle( nSize );
+ memcpy( *picHandle, pBuf, nSize );
+ m_pictHandle = picHandle;
+ CGImageRef cgImageRef = 0;
+
+ CFDataRef data = CFDataCreateWithBytesNoCopy( kCFAllocatorDefault, (const UInt8*) pBuf, nSize, kCFAllocatorNull);
+ CGImageSourceRef source = CGImageSourceCreateWithData( data, NULL );
+ if ( source )
+ {
+ cgImageRef = CGImageSourceCreateImageAtIndex(source, 0, NULL);
+ }
+ CFRelease( source );
+ CFRelease( data );
+
+ if ( cgImageRef )
+ {
+ m_bitmap.Create( CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) );
+ CGRect r = CGRectMake( 0 , 0 , CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) );
+ // since our context is upside down we dont use CGContextDrawImage
+ wxMacDrawCGImage( (CGContextRef) m_bitmap.GetHBITMAP() , &r, cgImageRef ) ;
+ CGImageRelease(cgImageRef);
+ cgImageRef = NULL;
+ }
+
+ return m_bitmap.Ok();
+}
+
+#endif
diff --git a/src/osx/carbon/dataview.cpp b/src/osx/carbon/dataview.cpp
new file mode 100644
index 0000000000..5dd666c1ca
--- /dev/null
+++ b/src/osx/carbon/dataview.cpp
@@ -0,0 +1,1575 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/datavgen.cpp
+// Purpose: wxDataViewCtrl native mac implementation
+// Author:
+// Id: $Id$
+// Copyright: (c) 2007
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#if wxUSE_DATAVIEWCTRL
+
+#include "wx/dataview.h"
+
+#if !defined(wxUSE_GENERICDATAVIEWCTRL) || (wxUSE_GENERICDATAVIEWCTRL == 0)
+
+#include
+
+#include "wx/mac/carbon/databrow.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/timer.h"
+ #include "wx/settings.h"
+ #include "wx/dcclient.h"
+ #include "wx/icon.h"
+#endif
+
+#include "wx/renderer.h"
+
+//-----------------------------------------------------------------------------
+// local constants
+//-----------------------------------------------------------------------------
+
+// a list of all catchable events:
+static EventTypeSpec const eventList[] =
+{
+ {kEventClassControl, kEventControlDraw},
+ {kEventClassControl, kEventControlHit}
+};
+
+//-----------------------------------------------------------------------------
+// local functions
+//-----------------------------------------------------------------------------
+
+static pascal OSStatus wxMacDataViewCtrlEventHandler(EventHandlerCallRef handler, EventRef EventReference, void* Data)
+{
+ wxDataViewCtrl* DataViewCtrlPtr((wxDataViewCtrl*) Data); // the 'Data' variable always contains a pointer to the data view control that installed the handler
+
+ wxMacCarbonEvent CarbonEvent(EventReference) ;
+
+
+ switch (GetEventKind(EventReference))
+ {
+ case kEventControlDraw:
+ {
+ OSStatus status;
+
+ DataViewCtrlPtr->MacSetDrawingContext(CarbonEvent.GetParameter(kEventParamCGContextRef,typeCGContextRef));
+ status = ::CallNextEventHandler(handler,EventReference);
+ DataViewCtrlPtr->MacSetDrawingContext(NULL);
+ return status;
+ } /* block */
+ case kEventControlHit :
+ if (CarbonEvent.GetParameter(kEventParamControlPart,typeControlPartCode) == kControlButtonPart) // we only care about the header
+ {
+ ControlRef controlReference;
+ DataBrowserPropertyID columnPropertyID;
+ unsigned long columnIndex;
+ OSStatus status;
+ wxDataViewEvent DataViewEvent(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK,DataViewCtrlPtr->GetId());
+
+ CarbonEvent.GetParameter(kEventParamDirectObject,&controlReference);
+ // determine the column that triggered the event (this is the column that is responsible for sorting the data view):
+ status = ::GetDataBrowserSortProperty(controlReference,&columnPropertyID);
+ wxCHECK(status == noErr,status);
+ status = ::GetDataBrowserTableViewColumnPosition(controlReference,columnPropertyID,&columnIndex);
+ if (status == errDataBrowserPropertyNotFound) // user clicked into part of the header that does not have a property
+ return ::CallNextEventHandler(handler,EventReference);
+ wxCHECK(status == noErr,status);
+ // initialize wxWidget event handler:
+ DataViewEvent.SetEventObject(DataViewCtrlPtr);
+ DataViewEvent.SetColumn(columnIndex);
+ DataViewEvent.SetDataViewColumn(DataViewCtrlPtr->GetColumn(columnIndex));
+ // finally sent the equivalent wxWidget event:
+#if wxCHECK_VERSION(2,9,0)
+ DataViewCtrlPtr->HandleWindowEvent(DataViewEvent);
+#else
+ DataViewCtrlPtr->GetEventHandler()->ProcessEvent(DataViewEvent);
+#endif
+ return ::CallNextEventHandler(handler,EventReference);
+ } /* if */
+ else
+ return eventNotHandledErr;
+ } /* switch */
+
+ return eventNotHandledErr;
+} /* wxMacDataViewCtrlEventHandler(EventHandlerCallRef, EventRef, void*) */
+
+static DataBrowserItemID* CreateDataBrowserItemIDArray(size_t& noOfEntries, wxDataViewItemArray const& items) // returns a newly allocated pointer to valid data browser item IDs
+{
+ size_t const noOfItems = items.GetCount();
+
+ DataBrowserItemID* itemIDs(new DataBrowserItemID[noOfItems]);
+
+
+ // convert all valid data view items to data browser items
+ noOfEntries = 0;
+ for (size_t i=0; i(items[i].GetID());
+ ++noOfEntries;
+ } /* if */
+ // done:
+ return itemIDs;
+} /* CreateDataBrowserItemIDArray(size_t&, wxDataViewItemArray const&) */
+
+#if wxCHECK_VERSION(2,9,0)
+static bool InitializeColumnDescription(DataBrowserListViewColumnDesc& columnDescription, wxDataViewColumn const* columnPtr, DataBrowserPropertyID columnPropertyID, wxCFStringRef const& title)
+#else
+static bool InitializeColumnDescription(DataBrowserListViewColumnDesc& columnDescription, wxDataViewColumn const* columnPtr, DataBrowserPropertyID columnPropertyID, wxMacCFStringHolder const& title)
+#endif
+{
+ // set properties for the column:
+ columnDescription.propertyDesc.propertyID = columnPropertyID;
+ columnDescription.propertyDesc.propertyType = columnPtr->GetRenderer()->GetPropertyType();
+ columnDescription.propertyDesc.propertyFlags = kDataBrowserListViewSelectionColumn; // make the column selectable
+ if (columnPtr->IsReorderable())
+ columnDescription.propertyDesc.propertyFlags |= kDataBrowserListViewMovableColumn;
+ if (columnPtr->IsResizeable())
+ {
+ columnDescription.headerBtnDesc.minimumWidth = 0;
+ columnDescription.headerBtnDesc.maximumWidth = 30000; // 32767 is the theoretical maximum though but 30000 looks nicer
+ } /* if */
+ else
+ {
+ columnDescription.headerBtnDesc.minimumWidth = columnPtr->GetWidth();
+ columnDescription.headerBtnDesc.maximumWidth = columnPtr->GetWidth();
+ } /* if */
+ if (columnPtr->IsSortable())
+ columnDescription.propertyDesc.propertyFlags |= kDataBrowserListViewSortableColumn;
+ if (columnPtr->GetRenderer()->GetMode() == wxDATAVIEW_CELL_EDITABLE)
+ columnDescription.propertyDesc.propertyFlags |= kDataBrowserPropertyIsEditable;
+ if ((columnDescription.propertyDesc.propertyType == kDataBrowserCustomType) ||
+ (columnDescription.propertyDesc.propertyType == kDataBrowserDateTimeType) ||
+ (columnDescription.propertyDesc.propertyType == kDataBrowserIconAndTextType) ||
+ (columnDescription.propertyDesc.propertyType == kDataBrowserTextType))
+ columnDescription.propertyDesc.propertyFlags |= kDataBrowserListViewTypeSelectColumn; // enables generally the possibility to have user input for the mentioned types
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ columnDescription.propertyDesc.propertyFlags |= kDataBrowserListViewNoGapForIconInHeaderButton;
+#endif
+ // set header's properties:
+ columnDescription.headerBtnDesc.version = kDataBrowserListViewLatestHeaderDesc;
+ columnDescription.headerBtnDesc.titleOffset = 0;
+ columnDescription.headerBtnDesc.titleString = ::CFStringCreateCopy(kCFAllocatorDefault,title);
+ columnDescription.headerBtnDesc.initialOrder = kDataBrowserOrderIncreasing; // choose one of the orders as "undefined" is not supported anyway (s. ControlDefs.h in the HIToolbox framework)
+ columnDescription.headerBtnDesc.btnFontStyle.flags = kControlUseFontMask | kControlUseJustMask;
+ switch (columnPtr->GetAlignment())
+ {
+ case wxALIGN_CENTER:
+ case wxALIGN_CENTER_HORIZONTAL:
+ columnDescription.headerBtnDesc.btnFontStyle.just = teCenter;
+ break;
+ case wxALIGN_LEFT:
+ columnDescription.headerBtnDesc.btnFontStyle.just = teFlushLeft;
+ break;
+ case wxALIGN_RIGHT:
+ columnDescription.headerBtnDesc.btnFontStyle.just = teFlushRight;
+ break;
+ default:
+ columnDescription.headerBtnDesc.btnFontStyle.just = teFlushDefault;
+ } /* switch */
+ columnDescription.headerBtnDesc.btnFontStyle.font = kControlFontViewSystemFont;
+ columnDescription.headerBtnDesc.btnFontStyle.style = normal;
+ if (columnPtr->GetBitmap().IsOk())
+ {
+ columnDescription.headerBtnDesc.btnContentInfo.contentType = kControlContentIconRef;
+#if wxCHECK_VERSION(2,9,0)
+ columnDescription.headerBtnDesc.btnContentInfo.u.iconRef = columnPtr->GetBitmap().GetIconRef();
+#else
+ columnDescription.headerBtnDesc.btnContentInfo.u.iconRef = columnPtr->GetBitmap().GetBitmapData()->GetIconRef();
+#endif
+ }
+ else
+ {
+ // not text only as we otherwise could not add a bitmap later
+ // columnDescription.headerBtnDesc.btnContentInfo.contentType = kControlContentTextOnly;
+ columnDescription.headerBtnDesc.btnContentInfo.contentType = kControlContentIconRef;
+ columnDescription.headerBtnDesc.btnContentInfo.u.iconRef = NULL;
+ }
+
+ // done:
+ return true;
+} /* InitializeColumnDescription(DataBrowserListViewColumnDesc&, wxDataViewColumn const*, DataBrowserPropertyID, wxMacCFStringHolder const&) */
+
+//-----------------------------------------------------------------------------
+// local function pointers
+//-----------------------------------------------------------------------------
+
+DEFINE_ONE_SHOT_HANDLER_GETTER(wxMacDataViewCtrlEventHandler)
+
+// ---------------------------------------------------------
+// wxMacDataViewModelNotifier
+// ---------------------------------------------------------
+#pragma mark -
+class wxMacDataViewModelNotifier : public wxDataViewModelNotifier
+{
+public:
+ wxMacDataViewModelNotifier(wxMacDataViewDataBrowserListViewControl* initDataViewControlPtr) : m_dataViewControlPtr(initDataViewControlPtr)
+ {
+ }
+
+ virtual bool ItemAdded(const wxDataViewItem &parent, const wxDataViewItem &item)
+ {
+ DataBrowserItemID itemID(reinterpret_cast(item.GetID()));
+
+ wxCHECK_MSG(item.IsOk(),false,_("Added item is invalid."));
+ bool noFailureFlag = (!(parent.IsOk()) && (this->m_dataViewControlPtr->AddItem(kDataBrowserNoItem,&itemID) == noErr) ||
+ parent.IsOk() && (this->m_dataViewControlPtr->AddItem(reinterpret_cast(parent.GetID()),&itemID) == noErr));
+
+ wxDataViewCtrl *dvc = (wxDataViewCtrl*) this->m_dataViewControlPtr->GetPeer();
+ if (dvc->GetWindowStyle() & wxDV_VARIABLE_LINE_HEIGHT)
+ {
+ wxDataViewModel *model = GetOwner();
+
+ int height = 20; // TODO find out standard height
+ unsigned int num = dvc->GetColumnCount();
+ unsigned int col;
+ for (col = 0; col < num; col++)
+ {
+ wxDataViewColumn *column = dvc->GetColumn( col );
+ if (column->IsHidden())
+ continue;
+
+ wxDataViewCustomRenderer *renderer = wxDynamicCast( column->GetRenderer(), wxDataViewCustomRenderer );
+ if (renderer)
+ {
+ wxVariant value;
+ model->GetValue( value, item, column->GetModelColumn() );
+ renderer->SetValue( value );
+ height = wxMax( height, renderer->GetSize().y );
+ }
+
+ }
+
+ if (height > 20)
+ this->m_dataViewControlPtr->SetRowHeight( itemID, height );
+ }
+
+ return noFailureFlag;
+ } /* ItemAdded(wxDataViewItem const&, wxDataViewItem const&) */
+
+ virtual bool ItemsAdded(wxDataViewItem const& parent, wxDataViewItemArray const& items)
+ {
+ bool noFailureFlag;
+
+ DataBrowserItemID* itemIDs;
+
+ size_t noOfEntries;
+
+
+ // convert all valid data view items to data browser items:
+ itemIDs = ::CreateDataBrowserItemIDArray(noOfEntries,items);
+ // insert all valid items into control:
+ noFailureFlag = ((noOfEntries == 0) ||
+ !(parent.IsOk()) && (this->m_dataViewControlPtr->AddItems(kDataBrowserNoItem,noOfEntries,itemIDs,kDataBrowserItemNoProperty) == noErr) ||
+ parent.IsOk() && (this->m_dataViewControlPtr->AddItems(reinterpret_cast(parent.GetID()),noOfEntries,itemIDs,kDataBrowserItemNoProperty) == noErr));
+ // give allocated array space free again:
+ delete[] itemIDs;
+
+ wxDataViewCtrl *dvc = (wxDataViewCtrl*) this->m_dataViewControlPtr->GetPeer();
+ if (dvc->GetWindowStyle() & wxDV_VARIABLE_LINE_HEIGHT)
+ {
+ wxDataViewModel *model = GetOwner();
+ unsigned int colnum = dvc->GetColumnCount();
+
+ size_t i;
+ size_t count = items.GetCount();
+ for (i = 0; i < count; i++)
+ {
+ wxDataViewItem item = items[i];
+ DataBrowserItemID itemID(reinterpret_cast(item.GetID()));
+
+ int height = 20; // TODO find out standard height
+ unsigned int col;
+ for (col = 0; col < colnum; col++)
+ {
+ wxDataViewColumn *column = dvc->GetColumn( col );
+ if (column->IsHidden())
+ continue; // skip it!
+
+ if ((col != 0) && model->IsContainer(item) && !model->HasContainerColumns(item))
+ continue; // skip it!
+
+ wxDataViewCustomRenderer *renderer = wxDynamicCast( column->GetRenderer(), wxDataViewCustomRenderer );
+ if (renderer)
+ {
+ wxVariant value;
+ model->GetValue( value, item, column->GetModelColumn() );
+ renderer->SetValue( value );
+ height = wxMax( height, renderer->GetSize().y );
+ }
+ }
+
+ if (height > 20)
+ this->m_dataViewControlPtr->SetRowHeight( itemID, height );
+ }
+ }
+
+ // done:
+ return noFailureFlag;
+ } /* ItemsAdded(wxDataViewItem const&, wxDataViewItemArray const&) */
+
+ virtual bool ItemChanged(wxDataViewItem const& item)
+ {
+ DataBrowserItemID itemID(reinterpret_cast(item.GetID()));
+
+
+ wxCHECK_MSG(item.IsOk(),false,_("Changed item is invalid."));
+ if (this->m_dataViewControlPtr->UpdateItems(&itemID) == noErr)
+ {
+ wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast(this->m_dataViewControlPtr->GetPeer()));
+
+ // sent the equivalent wxWidget event:
+ wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED,dataViewCtrlPtr->GetId()); // variable defintion
+
+ dataViewEvent.SetEventObject(dataViewCtrlPtr);
+ dataViewEvent.SetItem(item);
+ // sent the equivalent wxWidget event:
+#if wxCHECK_VERSION(2,9,0)
+ dataViewCtrlPtr->HandleWindowEvent(dataViewEvent);
+#else
+ dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
+#endif
+ // done
+ return true;
+ } /* if */
+ else
+ return false;
+ } /* ItemChanged(wxDataViewItem const&) */
+
+ virtual bool ItemsChanged(wxDataViewItemArray const& items)
+ {
+ bool noFailureFlag;
+
+ DataBrowserItemID* itemIDs;
+
+ size_t noOfEntries;
+
+
+ // convert all valid data view items to data browser items:
+ itemIDs = ::CreateDataBrowserItemIDArray(noOfEntries,items);
+ // change items (ATTENTION: ONLY ITEMS OF THE ROOT ARE CHANGED BECAUSE THE PARENT PARAMETER IS MISSING):
+ noFailureFlag = (this->m_dataViewControlPtr->UpdateItems(kDataBrowserNoItem,noOfEntries,itemIDs,kDataBrowserItemNoProperty,kDataBrowserItemNoProperty) == noErr);
+ if (noFailureFlag)
+ {
+ wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast(this->m_dataViewControlPtr->GetPeer()));
+
+ // send for all changed items a wxWidget event:
+ wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED,dataViewCtrlPtr->GetId()); // variable defintion
+
+ dataViewEvent.SetEventObject(dataViewCtrlPtr);
+ for (size_t i=0; i(itemIDs[i]));
+#if wxCHECK_VERSION(2,9,0)
+ dataViewCtrlPtr->HandleWindowEvent(dataViewEvent);
+#else
+ dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
+#endif
+ } /* for */
+ } /* if */
+ // release allocated array space:
+ delete[] itemIDs;
+ // done:
+ return noFailureFlag;
+ } /* ItemsChanged(wxDataViewItem const&) */
+
+ virtual bool ItemDeleted(wxDataViewItem const& parent, wxDataViewItem const& item)
+ {
+ if (item.IsOk())
+ {
+ // variable definition and initialization:
+ DataBrowserItemID itemID(reinterpret_cast(item.GetID()));
+ OSStatus errorStatus;
+ wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast(this->m_dataViewControlPtr->GetPeer()));
+
+ // when this method is called and currently an item is being edited this item may have already been deleted in the model (the passed item and the being edited item have
+ // not to be identical because the being edited item might be below the passed item in the hierarchy);
+ // to prevent the control trying to ask the model to update an already deleted item the control is informed that currently a deleting process
+ // has been started and that variables can currently not be updated even when requested by the system:
+ dataViewCtrlPtr->SetDeleting(true);
+ errorStatus = this->m_dataViewControlPtr->RemoveItem(reinterpret_cast(parent.GetID()),&itemID);
+ // enable automatic updating again:
+ dataViewCtrlPtr->SetDeleting(false);
+ return (errorStatus == noErr);
+ } /* if */
+ else
+ return false;
+ } /* ItemDeleted(wxDataViewItem const&, wxDataViewItem const&) */
+
+ virtual bool ItemsDeleted(wxDataViewItem const& parent, wxDataViewItemArray const& items)
+ {
+ bool noFailureFlag;
+
+ DataBrowserItemID* itemIDs;
+
+ wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast(this->m_dataViewControlPtr->GetPeer()));
+
+ size_t noOfEntries;
+
+
+ wxCHECK_MSG(dataViewCtrlPtr != NULL,false,_("Data view control is not correctly initialized"));
+ // convert all valid data view items to data browser items:
+ itemIDs = ::CreateDataBrowserItemIDArray(noOfEntries,items);
+ // when this method is called and currently an item is being edited this item may have already been deleted in the model (the passed item and the being edited item have
+ // not to be identical because the being edited item might be below the passed item in the hierarchy);
+ // to prevent the control trying to ask the model to update an already deleted item the control is informed that currently a deleting process
+ // has been started and that variables can currently not be updated even when requested by the system:
+ dataViewCtrlPtr->SetDeleting(true);
+ // insert all valid items into control:
+ noFailureFlag = ((noOfEntries == 0) ||
+ !(parent.IsOk()) && (this->m_dataViewControlPtr->RemoveItems(kDataBrowserNoItem,noOfEntries,itemIDs,kDataBrowserItemNoProperty) == noErr) ||
+ parent.IsOk() && (this->m_dataViewControlPtr->RemoveItems(reinterpret_cast(parent.GetID()),noOfEntries,itemIDs,kDataBrowserItemNoProperty) == noErr));
+ // enable automatic updating again:
+ dataViewCtrlPtr->SetDeleting(false);
+ // give allocated array space free again:
+ delete[] itemIDs;
+ // done:
+ return noFailureFlag;
+ } /* ItemsDeleted(wxDataViewItem const&, wxDataViewItemArray const&) */
+
+ virtual bool ValueChanged(wxDataViewItem const& item, unsigned int col)
+ {
+ DataBrowserItemID itemID(reinterpret_cast(item.GetID()));
+ DataBrowserItemID parentID;
+
+ DataBrowserPropertyID propertyID;
+
+ wxDataViewCtrl* dataViewCtrlPtr(dynamic_cast(this->m_dataViewControlPtr->GetPeer()));
+
+
+ wxCHECK_MSG(item.IsOk(), false,_("Passed item is invalid."));
+ wxCHECK_MSG(this->GetOwner() != NULL,false,_("Owner not initialized."));
+ wxCHECK_MSG(dataViewCtrlPtr != NULL, false,_("Control is wrongly initialized."));
+ parentID = reinterpret_cast(this->GetOwner()->GetParent(item).GetID());
+ if ((this->m_dataViewControlPtr->GetPropertyID(col,&propertyID) == noErr) &&
+ (this->m_dataViewControlPtr->UpdateItems(parentID,1,&itemID,dataViewCtrlPtr->GetColumn(col)->GetPropertyID(),propertyID) == noErr))
+ {
+ // variable definition and initialization:
+ wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED,dataViewCtrlPtr->GetId());
+
+ dataViewEvent.SetEventObject(dataViewCtrlPtr);
+ dataViewEvent.SetColumn(col);
+ dataViewEvent.SetItem(item);
+ // send the equivalent wxWidget event:
+#if wxCHECK_VERSION(2,9,0)
+ dataViewCtrlPtr->HandleWindowEvent(dataViewEvent);
+#else
+ dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
+#endif
+ // done
+ return true;
+ } /* if */
+ else
+ return false;
+ } /* ValueChanged(wxDataViewItem const&, unsigned int) */
+
+ virtual bool Cleared()
+ {
+ bool noFailureFlag = (this->m_dataViewControlPtr->RemoveItems() == noErr);
+ wxDataViewItem item;
+ wxDataViewItemArray array;
+ GetOwner()->GetChildren( item, array );
+ ItemsAdded( item, array );
+ return noFailureFlag;
+ } /* Cleared() */
+
+ virtual void Resort()
+ {
+ this->m_dataViewControlPtr->Resort();
+ }
+
+protected:
+private:
+//
+// variables
+//
+ wxMacDataViewDataBrowserListViewControl* m_dataViewControlPtr;
+};
+
+// ---------------------------------------------------------
+// wxDataViewRenderer
+// ---------------------------------------------------------
+#pragma mark -
+wxDataViewRenderer::wxDataViewRenderer(wxString const& varianttype, wxDataViewCellMode mode, int align)
+ :wxDataViewRendererBase(varianttype,mode,align), m_alignment(align), m_mode(mode)
+{
+} /* wxDataViewRenderer::wxDataViewRenderer(wxString const&, wxDataViewCellMode) */
+
+void wxDataViewRenderer::SetMode(wxDataViewCellMode mode)
+{
+ wxDataViewColumn* dataViewColumnPtr;
+
+
+ this->m_mode = mode;
+ dataViewColumnPtr = this->GetOwner();
+ if (dataViewColumnPtr != NULL)
+ {
+ // variable definition and initialization:
+ wxDataViewCtrl* dataViewCtrlPtr(dataViewColumnPtr->GetOwner());
+
+ if (dataViewCtrlPtr != NULL)
+ {
+ // variable definition and initialization:
+ wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast(dataViewCtrlPtr->GetPeer()));
+
+ if (macDataViewListCtrlPtr != NULL)
+ {
+ // variable definition and initialization:
+ DataBrowserPropertyFlags flags;
+
+ verify_noerr(macDataViewListCtrlPtr->GetPropertyFlags(dataViewColumnPtr->GetPropertyID(),&flags));
+ if (mode == wxDATAVIEW_CELL_EDITABLE)
+ flags |= kDataBrowserPropertyIsEditable;
+ else
+ flags &= ~kDataBrowserPropertyIsEditable;
+ verify_noerr(macDataViewListCtrlPtr->SetPropertyFlags(dataViewColumnPtr->GetPropertyID(),flags));
+ } /* if */
+ } /* if */
+ } /* if */
+} /* wxDataViewRenderer::SetMode(wxDataViewCellMode) */
+
+IMPLEMENT_ABSTRACT_CLASS(wxDataViewRenderer,wxDataViewRendererBase)
+
+// ---------------------------------------------------------
+// wxDataViewCustomRenderer
+// ---------------------------------------------------------
+#pragma mark -
+wxDataViewCustomRenderer::wxDataViewCustomRenderer(wxString const& varianttype, wxDataViewCellMode mode, int align)
+ :wxDataViewRenderer(varianttype,mode,align), m_editorCtrlPtr(NULL), m_DCPtr(NULL)
+{
+} /* wxDataViewCustomRenderer::wxDataViewCustomRenderer(wxString const&, wxDataViewCellMode) */
+
+wxDataViewCustomRenderer::~wxDataViewCustomRenderer()
+{
+ if (this->m_DCPtr != NULL)
+ delete this->m_DCPtr;
+} /* wxDataViewCustomRenderer::~wxDataViewCustomRenderer() */
+
+void wxDataViewCustomRenderer::RenderText( const wxString &text, int xoffset, wxRect cell, wxDC *dc, int state )
+{
+ wxDataViewCtrl *view = GetOwner()->GetOwner();
+// wxColour col = (state & wxDATAVIEW_CELL_SELECTED) ? wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT) : view->GetForegroundColour();
+ wxColour col = (state & wxDATAVIEW_CELL_SELECTED) ? *wxWHITE : view->GetForegroundColour();
+ dc->SetTextForeground(col);
+ dc->DrawText( text, cell.x + xoffset, cell.y + ((cell.height - dc->GetCharHeight()) / 2));
+}
+
+wxDC* wxDataViewCustomRenderer::GetDC()
+{
+ if (this->m_DCPtr == NULL)
+ {
+ if ((GetOwner() == NULL) || (GetOwner()->GetOwner() == NULL))
+ return NULL;
+ this->m_DCPtr = new wxWindowDC(this->GetOwner()->GetOwner());
+ } /* if */
+ return this->m_DCPtr;
+} /* wxDataViewCustomRenderer::GetDC() */
+
+bool wxDataViewCustomRenderer::Render()
+{
+ return true;
+} /* wxDataViewCustomRenderer::Render() */
+
+void wxDataViewCustomRenderer::SetDC(wxDC* newDCPtr)
+{
+ delete this->m_DCPtr;
+ this->m_DCPtr = newDCPtr;
+} /* wxDataViewCustomRenderer::SetDC(wxDC*) */
+
+WXDataBrowserPropertyType wxDataViewCustomRenderer::GetPropertyType() const
+{
+ return kDataBrowserCustomType;
+} /* wxDataViewCustomRenderer::GetPropertyType() const */
+
+IMPLEMENT_ABSTRACT_CLASS(wxDataViewCustomRenderer, wxDataViewRenderer)
+
+// ---------------------------------------------------------
+// wxDataViewTextRenderer
+// ---------------------------------------------------------
+#pragma mark -
+wxDataViewTextRenderer::wxDataViewTextRenderer(wxString const& varianttype, wxDataViewCellMode mode, int align)
+ :wxDataViewRenderer(varianttype,mode,align)
+{
+} /* wxDataViewTextRenderer::wxDataViewTextRenderer(wxString const&, wxDataViewCellMode, int) */
+
+bool wxDataViewTextRenderer::Render()
+{
+ wxCHECK_MSG(this->GetValue().GetType() == this->GetVariantType(),false,wxString(_("Text renderer cannot render value; value type: ")) << this->GetValue().GetType());
+
+ // variable definition:
+#if wxCHECK_VERSION(2,9,0)
+ wxCFStringRef cfString(this->GetValue().GetString(),(this->GetView()->GetFont().Ok() ? this->GetView()->GetFont().GetEncoding() : wxLocale::GetSystemEncoding()));
+#else
+ wxMacCFStringHolder cfString(this->GetValue().GetString(),(this->GetView()->GetFont().Ok() ? this->GetView()->GetFont().GetEncoding() : wxLocale::GetSystemEncoding()));
+#endif
+ return (::SetDataBrowserItemDataText(this->GetDataReference(),cfString) == noErr);
+} /* wxDataViewTextRenderer::Render() */
+
+WXDataBrowserPropertyType wxDataViewTextRenderer::GetPropertyType() const
+{
+ return kDataBrowserTextType;
+} /* wxDataViewTextRenderer::GetPropertyType() const */
+
+IMPLEMENT_CLASS(wxDataViewTextRenderer,wxDataViewRenderer)
+
+// ---------------------------------------------------------
+// wxDataViewTextRendererAttr
+// ---------------------------------------------------------
+#pragma mark -
+wxDataViewTextRendererAttr::wxDataViewTextRendererAttr(wxString const& varianttype, wxDataViewCellMode mode, int align)
+ :wxDataViewTextRenderer(varianttype,mode,align)
+{
+} /* wxDataViewTextRendererAttr::wxDataViewTextRendererAttr(wxString const&, wxDataViewCellMode, int) */
+
+IMPLEMENT_CLASS(wxDataViewTextRendererAttr,wxDataViewTextRenderer)
+
+// ---------------------------------------------------------
+// wxDataViewBitmapRenderer
+// ---------------------------------------------------------
+#pragma mark -
+wxDataViewBitmapRenderer::wxDataViewBitmapRenderer(wxString const& varianttype, wxDataViewCellMode mode, int align)
+ :wxDataViewRenderer(varianttype,mode,align)
+{
+}
+
+bool wxDataViewBitmapRenderer::Render()
+ // This method returns 'true' if
+ // - the passed bitmap is valid and it could be assigned to the native data browser;
+ // - the passed bitmap is invalid (or is not initialized); this case simulates a non-existing bitmap.
+ // In all other cases the method returns 'false'.
+{
+ wxCHECK_MSG(this->GetValue().GetType() == this->GetVariantType(),false,wxString(_("Bitmap renderer cannot render value; value type: ")) << this->GetValue().GetType());
+
+ // variable definition:
+ wxBitmap bitmap;
+
+ bitmap << this->GetValue();
+ if (bitmap.Ok())
+#if wxCHECK_VERSION(2,9,0)
+ return (::SetDataBrowserItemDataIcon(this->GetDataReference(),bitmap.GetIconRef()) == noErr);
+#else
+ return (::SetDataBrowserItemDataIcon(this->GetDataReference(),bitmap.GetBitmapData()->GetIconRef()) == noErr);
+#endif
+ else
+ return true;
+} /* wxDataViewBitmapRenderer::Render() */
+
+WXDataBrowserPropertyType wxDataViewBitmapRenderer::GetPropertyType() const
+{
+ return kDataBrowserIconType;
+} /* wxDataViewBitmapRenderer::GetPropertyType() const */
+
+IMPLEMENT_CLASS(wxDataViewBitmapRenderer,wxDataViewRenderer)
+
+// ---------------------------------------------------------
+// wxDataViewIconTextRenderer
+// ---------------------------------------------------------
+#pragma mark -
+wxDataViewIconTextRenderer::wxDataViewIconTextRenderer(wxString const& varianttype, wxDataViewCellMode mode, int align)
+ :wxDataViewRenderer(varianttype,mode)
+{
+}
+
+bool wxDataViewIconTextRenderer::Render()
+{
+ wxCHECK_MSG(this->GetValue().GetType() == this->GetVariantType(),false,wxString(_("Icon & text renderer cannot render value; value type: ")) << this->GetValue().GetType());
+
+ // variable definition:
+ wxDataViewIconText iconText;
+
+ iconText << this->GetValue();
+
+ // variable definition:
+#if wxCHECK_VERSION(2,9,0)
+ wxCFStringRef cfString(iconText.GetText(),(this->GetView()->GetFont().Ok() ? this->GetView()->GetFont().GetEncoding() : wxLocale::GetSystemEncoding()));
+#else
+ wxMacCFStringHolder cfString(iconText.GetText(),(this->GetView()->GetFont().Ok() ? this->GetView()->GetFont().GetEncoding() : wxLocale::GetSystemEncoding()));
+#endif
+
+ if (iconText.GetIcon().IsOk())
+ if (::SetDataBrowserItemDataIcon(this->GetDataReference(),MAC_WXHICON(iconText.GetIcon().GetHICON())) != noErr)
+ return false;
+ return (::SetDataBrowserItemDataText(this->GetDataReference(),cfString) == noErr);
+} /* wxDataViewIconTextRenderer::Render() */
+
+WXDataBrowserPropertyType wxDataViewIconTextRenderer::GetPropertyType() const
+{
+ return kDataBrowserIconAndTextType;
+} /* wxDataViewIconTextRenderer::GetPropertyType() const */
+
+IMPLEMENT_ABSTRACT_CLASS(wxDataViewIconTextRenderer,wxDataViewRenderer)
+
+
+// ---------------------------------------------------------
+// wxDataViewToggleRenderer
+// ---------------------------------------------------------
+#pragma mark -
+wxDataViewToggleRenderer::wxDataViewToggleRenderer(wxString const& varianttype, wxDataViewCellMode mode, int align)
+ :wxDataViewRenderer(varianttype,mode)
+{
+}
+
+bool wxDataViewToggleRenderer::Render()
+{
+ wxCHECK_MSG(this->GetValue().GetType() == this->GetVariantType(),false,wxString(_("Toggle renderer cannot render value; value type: ")) << this->GetValue().GetType());
+ return (::SetDataBrowserItemDataButtonValue(this->GetDataReference(),this->GetValue().GetBool()) == noErr);
+} /* wxDataViewToggleRenderer::Render() */
+
+WXDataBrowserPropertyType wxDataViewToggleRenderer::GetPropertyType() const
+{
+ return kDataBrowserCheckboxType;
+} /* wxDataViewToggleRenderer::GetPropertyType() const */
+
+IMPLEMENT_ABSTRACT_CLASS(wxDataViewToggleRenderer,wxDataViewRenderer)
+
+// ---------------------------------------------------------
+// wxDataViewProgressRenderer
+// ---------------------------------------------------------
+#pragma mark -
+wxDataViewProgressRenderer::wxDataViewProgressRenderer(wxString const& label, wxString const& varianttype, wxDataViewCellMode mode, int align)
+ :wxDataViewRenderer(varianttype,mode,align)
+{
+}
+
+bool wxDataViewProgressRenderer::Render()
+{
+ wxCHECK_MSG(this->GetValue().GetType() == this->GetVariantType(),false,wxString(_("Progress renderer cannot render value type; value type: ")) << this->GetValue().GetType());
+ return ((::SetDataBrowserItemDataMinimum(this->GetDataReference(), 0) == noErr) &&
+ (::SetDataBrowserItemDataMaximum(this->GetDataReference(),100) == noErr) &&
+ (::SetDataBrowserItemDataValue (this->GetDataReference(),this->GetValue().GetLong()) == noErr));
+} /* wxDataViewProgressRenderer::Render() */
+
+WXDataBrowserPropertyType wxDataViewProgressRenderer::GetPropertyType() const
+{
+ return kDataBrowserProgressBarType;
+} /* wxDataViewProgressRenderer::GetPropertyType() const */
+
+IMPLEMENT_ABSTRACT_CLASS(wxDataViewProgressRenderer,wxDataViewRenderer)
+
+// ---------------------------------------------------------
+// wxDataViewDateRenderer
+// ---------------------------------------------------------
+#pragma mark -
+wxDataViewDateRenderer::wxDataViewDateRenderer(wxString const& varianttype, wxDataViewCellMode mode, int align)
+ :wxDataViewRenderer(varianttype,mode,align)
+{
+}
+
+bool wxDataViewDateRenderer::Render()
+{
+ wxCHECK_MSG(this->GetValue().GetType() == this->GetVariantType(),false,wxString(_("Date renderer cannot render value; value type: ")) << this->GetValue().GetType());
+ return (::SetDataBrowserItemDataDateTime(this->GetDataReference(),this->GetValue().GetDateTime().Subtract(wxDateTime(1,wxDateTime::Jan,1904)).GetSeconds().GetLo()) == noErr);
+} /* wxDataViewDateRenderer::Render() */
+
+WXDataBrowserPropertyType wxDataViewDateRenderer::GetPropertyType() const
+{
+ return kDataBrowserDateTimeType;
+} /* wxDataViewDateRenderer::GetPropertyType() const */
+
+IMPLEMENT_ABSTRACT_CLASS(wxDataViewDateRenderer,wxDataViewRenderer)
+
+// ---------------------------------------------------------
+// wxDataViewColumn
+// ---------------------------------------------------------
+#pragma mark -
+wxDataViewColumn::wxDataViewColumn(wxString const &title, wxDataViewRenderer *cell, unsigned int model_column, int width, wxAlignment align, int flags)
+ :wxDataViewColumnBase(title,cell,model_column,width,align,flags), m_ascending(true),
+ m_flags(flags & ~(wxDATAVIEW_COL_HIDDEN)), m_maxWidth(30000), m_minWidth(0), m_width(width >= 0 ? width : wxDVC_DEFAULT_WIDTH),
+ m_alignment(align), m_title(title)
+{
+} /* wxDataViewColumn::wxDataViewColumn(wxString const &title, wxDataViewRenderer*, unsigned int, int, wxAlignment, int) */
+
+wxDataViewColumn::wxDataViewColumn(wxBitmap const& bitmap, wxDataViewRenderer *cell, unsigned int model_column, int width, wxAlignment align, int flags)
+ :wxDataViewColumnBase(bitmap,cell,model_column,width,align,flags), m_ascending(true),
+ m_flags(flags & ~(wxDATAVIEW_COL_HIDDEN)), m_maxWidth(30000), m_minWidth(0), m_width(width >= 0 ? width : wxDVC_DEFAULT_WIDTH),
+ m_alignment(align)
+{
+} /* wxDataViewColumn::wxDataViewColumn(wxBitmap const&, wxDataViewRenderer*, unsigned int, int, wxAlignment, int) */
+
+void wxDataViewColumn::SetAlignment(wxAlignment align)
+{
+ wxDataViewCtrl* dataViewCtrlPtr(this->GetOwner());
+
+
+ this->m_alignment = align;
+ if (dataViewCtrlPtr != NULL)
+ {
+ // variable definition and initialization:
+ wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast(dataViewCtrlPtr->GetPeer()));
+
+ if (macDataViewListCtrlPtr != NULL)
+ {
+ // variable definition and initialization:
+ DataBrowserListViewHeaderDesc headerDescription;
+
+ wxCHECK_RET(macDataViewListCtrlPtr->GetHeaderDesc(this->GetPropertyID(),&headerDescription) == noErr,_("Could not get header description."));
+ switch (align)
+ {
+ case wxALIGN_CENTER:
+ case wxALIGN_CENTER_HORIZONTAL:
+ headerDescription.btnFontStyle.just = teCenter;
+ break;
+ case wxALIGN_LEFT:
+ headerDescription.btnFontStyle.just = teFlushLeft;
+ break;
+ case wxALIGN_RIGHT:
+ headerDescription.btnFontStyle.just = teFlushRight;
+ break;
+ default:
+ headerDescription.btnFontStyle.just = teFlushDefault;
+ } /* switch */
+ wxCHECK_RET(macDataViewListCtrlPtr->SetHeaderDesc(this->GetPropertyID(),&headerDescription) == noErr,_("Could not set alignment."));
+ } /* if */
+ } /* if */
+} /* wxDataViewColumn::SetAlignment(wxAlignment) */
+
+void wxDataViewColumn::SetBitmap(wxBitmap const& bitmap)
+{
+ wxDataViewCtrl* dataViewCtrlPtr(this->GetOwner());
+
+
+ wxDataViewColumnBase::SetBitmap(bitmap);
+ if (dataViewCtrlPtr != NULL)
+ {
+ // variable definition and initialization:
+ wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast(dataViewCtrlPtr->GetPeer()));
+
+ if (macDataViewListCtrlPtr != NULL)
+ {
+ // variable definition and initialization:
+ DataBrowserListViewHeaderDesc headerDescription;
+
+ wxCHECK_RET(macDataViewListCtrlPtr->GetHeaderDesc(this->GetPropertyID(),&headerDescription) == noErr,_("Could not get header description."));
+ if (this->GetBitmap().Ok())
+#if wxCHECK_VERSION(2,9,0)
+ headerDescription.btnContentInfo.u.iconRef = this->GetBitmap().GetIconRef();
+#else
+ headerDescription.btnContentInfo.u.iconRef = this->GetBitmap().GetBitmapData()->GetIconRef();
+#endif
+ else
+ headerDescription.btnContentInfo.u.iconRef = NULL;
+ wxCHECK_RET(macDataViewListCtrlPtr->SetHeaderDesc(this->GetPropertyID(),&headerDescription) == noErr,_("Could not set icon."));
+ } /* if */
+ } /* if */
+} /* wxDataViewColumn::SetBitmap(wxBitmap const&) */
+
+void wxDataViewColumn::SetFlags(int flags)
+{
+ this->SetHidden ((flags & wxDATAVIEW_COL_HIDDEN) != 0);
+ this->SetReorderable((flags & wxDATAVIEW_COL_REORDERABLE) != 0);
+ this->SetResizeable ((flags & wxDATAVIEW_COL_RESIZABLE) != 0);
+ this->SetSortable ((flags & wxDATAVIEW_COL_SORTABLE) != 0);
+} /* wxDataViewColumn::SetFlags(int) */
+
+void wxDataViewColumn::SetMaxWidth(int maxWidth)
+{
+ wxDataViewCtrl* dataViewCtrlPtr(this->GetOwner());
+
+
+ this->m_maxWidth = maxWidth;
+ if (dataViewCtrlPtr != NULL)
+ {
+ // variable definition and initialization:
+ wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast(dataViewCtrlPtr->GetPeer()));
+
+ if (macDataViewListCtrlPtr != NULL)
+ {
+ // variable definition and initialization:
+ DataBrowserListViewHeaderDesc headerDescription;
+
+ wxCHECK_RET(macDataViewListCtrlPtr->GetHeaderDesc(this->GetPropertyID(),&headerDescription) == noErr,_("Could not get header description."));
+ headerDescription.maximumWidth = static_cast(maxWidth);
+ wxCHECK_RET(macDataViewListCtrlPtr->SetHeaderDesc(this->GetPropertyID(),&headerDescription) == noErr,_("Could not set maximum width."));
+ } /* if */
+ } /* if */
+} /* wxDataViewColumn::SetMaxWidth(int) */
+
+void wxDataViewColumn::SetMinWidth(int minWidth)
+{
+ wxDataViewCtrl* dataViewCtrlPtr(this->GetOwner());
+
+
+ this->m_minWidth = minWidth;
+ if (dataViewCtrlPtr != NULL)
+ {
+ // variable definition and initialization:
+ wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast(dataViewCtrlPtr->GetPeer()));
+
+ if (macDataViewListCtrlPtr != NULL)
+ {
+ // variable definition and initialization:
+ DataBrowserListViewHeaderDesc headerDescription;
+
+ wxCHECK_RET(macDataViewListCtrlPtr->GetHeaderDesc(this->GetPropertyID(),&headerDescription) == noErr,_("Could not get header description."));
+ headerDescription.minimumWidth = static_cast(minWidth);
+ wxCHECK_RET(macDataViewListCtrlPtr->SetHeaderDesc(this->GetPropertyID(),&headerDescription) == noErr,_("Could not set minimum width."));
+ } /* if */
+ } /* if */
+} /* wxDataViewColumn::SetMaxWidth(int) */
+
+void wxDataViewColumn::SetReorderable(bool reorderable)
+{
+ // first set the internal flag of the column:
+ if (reorderable)
+ this->m_flags |= wxDATAVIEW_COL_REORDERABLE;
+ else
+ this->m_flags &= ~wxDATAVIEW_COL_REORDERABLE;
+ // if the column is associated with a control change also immediately the flags of the control:
+ wxDataViewCtrl* dataViewCtrlPtr(this->GetOwner()); // variable definition and initialization
+
+ if (dataViewCtrlPtr != NULL)
+ {
+ // variable definition and initialization:
+ DataBrowserPropertyFlags flags;
+ wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast(dataViewCtrlPtr->GetPeer()));
+
+ wxCHECK_RET(macDataViewListCtrlPtr != NULL, _("Valid pointer to native data view control does not exist"));
+ wxCHECK_RET(macDataViewListCtrlPtr->GetPropertyFlags(this->GetPropertyID(),&flags) == noErr,_("Could not get property flags."));
+ if (reorderable)
+ flags |= kDataBrowserListViewMovableColumn;
+ else
+ flags &= ~kDataBrowserListViewMovableColumn;
+ wxCHECK_RET(macDataViewListCtrlPtr->SetPropertyFlags(this->GetPropertyID(),flags) == noErr,_("Could not set property flags."));
+ } /* if */
+} /* wxDataViewColumn::SetReorderable(bool) */
+
+void wxDataViewColumn::SetResizeable(bool resizeable)
+{
+ // first set the internal flag of the column:
+ if (resizeable)
+ this->m_flags |= wxDATAVIEW_COL_RESIZABLE;
+ else
+ this->m_flags &= ~wxDATAVIEW_COL_RESIZABLE;
+ // if the column is associated with a control change also immediately the flags of the control:
+ wxDataViewCtrl* dataViewCtrlPtr(this->GetOwner()); // variable definition and initialization
+
+ if (dataViewCtrlPtr != NULL)
+ {
+ // variable definition and initialization:
+ wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast(dataViewCtrlPtr->GetPeer()));
+
+ if (macDataViewListCtrlPtr != NULL)
+ {
+ // variable definition and initialization:
+ DataBrowserListViewHeaderDesc headerDescription;
+
+ verify_noerr(macDataViewListCtrlPtr->GetHeaderDesc(this->GetPropertyID(),&headerDescription));
+ if (resizeable) {
+ headerDescription.minimumWidth = 0;
+ headerDescription.maximumWidth = 30000;
+ }
+ else {
+ headerDescription.minimumWidth = this->m_width;
+ headerDescription.maximumWidth = this->m_width;
+ }
+ verify_noerr(macDataViewListCtrlPtr->SetHeaderDesc(this->GetPropertyID(),&headerDescription));
+ macDataViewListCtrlPtr->SetSortProperty(this->GetPropertyID());
+ } /* if */
+ } /* if */
+} /* wxDataViewColumn::SetResizeable(bool) */
+
+void wxDataViewColumn::SetSortable(bool sortable)
+{
+ // first set the internal flag of the column:
+ if (sortable)
+ this->m_flags |= wxDATAVIEW_COL_SORTABLE;
+ else
+ this->m_flags &= ~wxDATAVIEW_COL_SORTABLE;
+ // if the column is associated with a control change also immediately the flags of the control:
+ wxDataViewCtrl* dataViewCtrlPtr(this->GetOwner()); // variable definition and initialization
+
+ if (dataViewCtrlPtr != NULL)
+ {
+ // variable definition and initialization:
+ DataBrowserPropertyFlags flags;
+ wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast(dataViewCtrlPtr->GetPeer()));
+
+ wxCHECK_RET(macDataViewListCtrlPtr != NULL, _("Valid pointer to native data view control does not exist"));
+ wxCHECK_RET(macDataViewListCtrlPtr->GetPropertyFlags(this->GetPropertyID(),&flags) == noErr,_("Could not get property flags."));
+ if (sortable)
+ flags |= kDataBrowserListViewSortableColumn;
+ else
+ flags &= ~kDataBrowserListViewSortableColumn;
+ wxCHECK_RET(macDataViewListCtrlPtr->SetPropertyFlags(this->GetPropertyID(),flags) == noErr,_("Could not set property flags."));
+ } /* if */
+} /* wxDataViewColumn::SetSortable(bool) */
+
+void wxDataViewColumn::SetSortOrder(bool ascending)
+{
+ wxDataViewCtrl* dataViewCtrlPtr(this->GetOwner());
+
+
+ this->m_ascending = ascending;
+ if (dataViewCtrlPtr != NULL)
+ {
+ // variable definition and initialization:
+ wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast(dataViewCtrlPtr->GetPeer()));
+
+ if (macDataViewListCtrlPtr != NULL)
+ {
+ // variable definition and initialization:
+ DataBrowserListViewHeaderDesc headerDescription;
+
+ verify_noerr(macDataViewListCtrlPtr->GetHeaderDesc(this->GetPropertyID(),&headerDescription));
+ if (ascending)
+ headerDescription.initialOrder = kDataBrowserOrderIncreasing;
+ else
+ headerDescription.initialOrder = kDataBrowserOrderDecreasing;
+ verify_noerr(macDataViewListCtrlPtr->SetHeaderDesc(this->GetPropertyID(),&headerDescription));
+ macDataViewListCtrlPtr->SetSortProperty(this->GetPropertyID());
+ } /* if */
+ } /* if */
+} /* wxDataViewColumn::SetSortOrder(bool) */
+
+void wxDataViewColumn::SetTitle(wxString const& title)
+{
+ wxDataViewCtrl* dataViewCtrlPtr(this->GetOwner());
+
+
+ this->m_title = title;
+ if (dataViewCtrlPtr != NULL)
+ {
+ // variable definition and initialization:
+ wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast(dataViewCtrlPtr->GetPeer()));
+
+ if (macDataViewListCtrlPtr != NULL)
+ {
+ // variable definition and initialization:
+ DataBrowserListViewHeaderDesc headerDescription;
+#if wxCHECK_VERSION(2,9,0)
+ wxCFStringRef cfTitle(title,(dataViewCtrlPtr->GetFont().Ok() ? dataViewCtrlPtr->GetFont().GetEncoding() : wxLocale::GetSystemEncoding()));
+#else
+ wxMacCFStringHolder cfTitle(title,(dataViewCtrlPtr->GetFont().Ok() ? dataViewCtrlPtr->GetFont().GetEncoding() : wxLocale::GetSystemEncoding()));
+#endif
+
+ wxCHECK_RET(macDataViewListCtrlPtr->GetHeaderDesc(this->GetPropertyID(),&headerDescription) == noErr,_("Could not get header description."));
+ headerDescription.titleString = cfTitle;
+ wxCHECK_RET(macDataViewListCtrlPtr->SetHeaderDesc(this->GetPropertyID(),&headerDescription) == noErr,_("Could not set header description."));
+ } /* if */
+ } /* if */
+} /* wxDataViewColumn::SetTitle(wxString const&) */
+
+void wxDataViewColumn::SetWidth(int width)
+{
+ wxDataViewCtrl* dataViewCtrlPtr(this->GetOwner());
+
+
+ if ((width >= this->m_minWidth) && (width <= this->m_maxWidth))
+ {
+ this->m_width = width;
+ if (dataViewCtrlPtr != NULL)
+ {
+ // variable definition and initialization:
+ wxMacDataViewDataBrowserListViewControlPointer macDataViewListCtrlPtr(dynamic_cast(dataViewCtrlPtr->GetPeer()));
+
+ if (macDataViewListCtrlPtr != NULL)
+ wxCHECK_RET(macDataViewListCtrlPtr->SetColumnWidth(this->GetPropertyID(),static_cast(width)) == noErr,_("Could not set column width."));
+ } /* if */
+ } /* if */
+} /* wxDataViewColumn::SetWidth(int) */
+
+IMPLEMENT_ABSTRACT_CLASS(wxDataViewColumn,wxDataViewColumnBase)
+
+//-----------------------------------------------------------------------------
+// wxDataViewCtrl
+//-----------------------------------------------------------------------------
+
+
+wxDataViewCtrl::~wxDataViewCtrl()
+{
+ ClearColumns();
+}
+
+#pragma mark -
+void wxDataViewCtrl::Init()
+{
+ this->m_CustomRendererPtr = NULL;
+ this->m_Deleting = false;
+ this->m_macIsUserPane = false;
+ this->m_cgContext = NULL;
+} /* wxDataViewCtrl::Init() */
+
+bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxValidator& validator )
+{
+ if (!(this->wxControl::Create(parent,id,pos,size,(style | wxSUNKEN_BORDER) & ~(wxHSCROLL | wxVSCROLL),validator)))
+ return false;
+
+#ifdef __WXMAC__
+ MacSetClipChildren(true) ;
+#endif
+
+ this->m_peer = new wxMacDataViewDataBrowserListViewControl(this,pos,size,style);
+ this->MacPostControlCreate(pos,size);
+ ::SetAutomaticControlDragTrackingEnabledForWindow(::GetControlOwner(this->m_peer->GetControlRef()),true);
+
+ InstallControlEventHandler(this->m_peer->GetControlRef(),GetwxMacDataViewCtrlEventHandlerUPP(),GetEventTypeCount(eventList),eventList,this,NULL);
+
+ ::SetDataBrowserTableViewHiliteStyle( this->m_peer->GetControlRef(), kDataBrowserTableViewFillHilite );
+
+ return true;
+} /* wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxValidator& validator) */
+
+/*static*/
+wxVisualAttributes wxDataViewCtrl::GetClassDefaultAttributes(wxWindowVariant variant)
+{
+ wxVisualAttributes attr;
+
+ attr.colFg = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT );
+ attr.colBg = wxSystemSettings::GetColour( wxSYS_COLOUR_LISTBOX );
+ attr.font.MacCreateFromThemeFont(kThemeViewsFont);
+
+ return attr;
+}
+
+bool wxDataViewCtrl::AssociateModel(wxDataViewModel* model)
+{
+ if (!wxDataViewCtrlBase::AssociateModel(model))
+ return false;
+
+ model->AddNotifier(new wxMacDataViewModelNotifier(dynamic_cast(this->m_peer)));
+
+ return true;
+}
+
+bool wxDataViewCtrl::AppendColumn(wxDataViewColumn* columnPtr)
+{
+ return InsertColumn( kDataBrowserListViewAppendColumn, columnPtr );
+}
+
+bool wxDataViewCtrl::PrependColumn(wxDataViewColumn* columnPtr)
+{
+ return InsertColumn( 0, columnPtr );
+}
+
+bool wxDataViewCtrl::InsertColumn(unsigned int pos, wxDataViewColumn* columnPtr)
+{
+ DataBrowserListViewColumnDesc columnDescription;
+
+ DataBrowserPropertyID NewPropertyID;
+
+ wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast(this->m_peer));
+
+#if wxCHECK_VERSION(2,9,0)
+ wxCFStringRef title(columnPtr->GetTitle(),this->m_font.Ok() ? this->GetFont().GetEncoding() : wxLocale::GetSystemEncoding());
+#else
+ wxMacCFStringHolder title(columnPtr->GetTitle(),this->m_font.Ok() ? this->GetFont().GetEncoding() : wxLocale::GetSystemEncoding());
+#endif
+
+
+ // first, some error checking:
+ wxCHECK_MSG(MacDataViewListCtrlPtr != NULL, false,_("m_peer is not or incorrectly initialized"));
+ wxCHECK_MSG(columnPtr != NULL, false,_("Column pointer must not be NULL."));
+ wxCHECK_MSG(columnPtr->GetRenderer() != NULL, false,_("Column does not have a renderer."));
+ wxCHECK_MSG(this->GetModel() != NULL, false,_("No model associated with control."));
+ wxCHECK_MSG((columnPtr->GetModelColumn() >= 0) &&
+ (columnPtr->GetModelColumn() < this->GetModel()->GetColumnCount()),false,_("Column's model column has no equivalent in the associated model."));
+
+ // try to get new ID for the column:
+ wxCHECK_MSG(MacDataViewListCtrlPtr->GetFreePropertyID(&NewPropertyID) == noErr,false,_("Cannot create new column's ID. Probably max. number of columns reached."));
+ // full column variable initialization:
+ columnPtr->SetPropertyID(NewPropertyID);
+ // add column to wxWidget's internal structure:
+ wxCHECK_MSG(this->wxDataViewCtrlBase::AppendColumn(columnPtr) &&
+ this->m_ColumnPointers.insert(ColumnPointerHashMapType::value_type(NewPropertyID,columnPtr)).second,false,_("Could not add column to internal structures."));
+ // create a column description and add column to the native control:
+ wxCHECK_MSG(::InitializeColumnDescription(columnDescription,columnPtr,NewPropertyID,title), false,_("Column description could not be initialized."));
+ wxCHECK_MSG(MacDataViewListCtrlPtr->AddColumn(&columnDescription,pos) == noErr,false,_("Column could not be added."));
+
+ // final adjustments for the layout:
+ wxCHECK_MSG(MacDataViewListCtrlPtr->SetColumnWidth(NewPropertyID,columnPtr->GetWidth()) == noErr,false,_("Column width could not be set."));
+
+ // make sure that the data is up-to-date...
+ // if the newly appended column is the first column add the initial data to the control and mark the column as an expander column,
+ // otherwise ask the control to 'update' the data in the newly appended column:
+ if (this->GetColumnCount() == 1)
+ {
+ this->SetExpanderColumn(columnPtr);
+ this->AddChildrenLevel(wxDataViewItem());
+ } /* if */
+ else
+ MacDataViewListCtrlPtr->UpdateItems(kDataBrowserNoItem,0,NULL,kDataBrowserItemNoProperty,NewPropertyID);
+ // done:
+ return true;
+}
+
+bool wxDataViewCtrl::ClearColumns()
+{
+ wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast(this->m_peer));
+
+
+ while (this->m_ColumnPointers.begin() != this->m_ColumnPointers.end())
+ {
+ wxCHECK_MSG(MacDataViewListCtrlPtr->RemoveColumnByProperty(this->m_ColumnPointers.begin()->first) == noErr,false,_("Could not remove column."));
+ delete this->m_ColumnPointers.begin()->second;
+ this->m_ColumnPointers.erase(this->m_ColumnPointers.begin());
+ } /* while */
+ return true;
+}
+
+bool wxDataViewCtrl::DeleteColumn(wxDataViewColumn* columnPtr)
+{
+ wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast(this->m_peer));
+
+
+ if ((MacDataViewListCtrlPtr->RemoveColumnByProperty(columnPtr->GetPropertyID()) == noErr) && (this->m_ColumnPointers.erase(columnPtr->GetPropertyID()) > 0))
+ {
+ delete columnPtr;
+ return true;
+ } /* if */
+ else
+ return false;
+} /* wxDataViewCtrl::DeleteColumn(wxDataViewColumn*) */
+
+wxDataViewColumn* wxDataViewCtrl::GetColumn(unsigned int pos) const
+{
+ DataBrowserPropertyID propertyID;
+
+ wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast(this->m_peer));
+
+
+ if (MacDataViewListCtrlPtr->GetPropertyID(pos,&propertyID) == noErr)
+ {
+ // variable definition:
+ ColumnPointerHashMapType::const_iterator Result(this->m_ColumnPointers.find(propertyID));
+
+ if (Result != this->m_ColumnPointers.end())
+ return Result->second;
+ else
+ return NULL;
+ } /* if */
+ else
+ return NULL;
+} /* wxDataViewCtrl::GetColumn(unsigned int pos) const */
+
+unsigned int wxDataViewCtrl::GetColumnCount() const
+{
+ return this->m_ColumnPointers.size();
+} /* wxDataViewCtrl::GetColumnCount() const */
+
+int wxDataViewCtrl::GetColumnPosition(wxDataViewColumn const* columnPtr) const
+{
+ if (columnPtr != NULL)
+ {
+ // variable definition and initialization:
+ DataBrowserTableViewColumnIndex Position;
+ wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast(this->m_peer));
+
+ wxCHECK_MSG(MacDataViewListCtrlPtr->GetColumnIndex(columnPtr->GetPropertyID(),&Position) == noErr,-1,_("Could not determine column's position"));
+ return static_cast(Position);
+ } /* if */
+ else
+ return wxNOT_FOUND;
+} /* wxDataViewCtrl::GetColumnPosition(wxDataViewColumn const*) const */
+
+void wxDataViewCtrl::Collapse(wxDataViewItem const& item)
+{
+ wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast(this->m_peer));
+
+
+ MacDataViewListCtrlPtr->CloseContainer(reinterpret_cast(item.GetID()));
+} /* wxDataViewCtrl::Collapse(wxDataViewItem const&) */
+
+void wxDataViewCtrl::EnsureVisible(wxDataViewItem const& item, wxDataViewColumn const* columnPtr)
+{
+ if (item.IsOk())
+ {
+ // variable definition and initialization:
+ DataBrowserPropertyID propertyID;
+ wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast(this->m_peer));
+
+ if (columnPtr != NULL)
+ propertyID = columnPtr->GetPropertyID();
+ else
+ propertyID = kDataBrowserNoItem;
+ MacDataViewListCtrlPtr->RevealItem(reinterpret_cast(item.GetID()),propertyID,kDataBrowserRevealOnly);
+ } /* if */
+} /* wxDataViewCtrl::EnsureVisible(wxDataViewItem const&, wxDataViewColumn const*) */
+
+void wxDataViewCtrl::Expand(wxDataViewItem const& item)
+{
+ wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast(this->m_peer));
+
+
+ MacDataViewListCtrlPtr->OpenContainer(reinterpret_cast(item.GetID()));
+} /* wxDataViewCtrl::Expand(wxDataViewItem const&) */
+
+wxDataViewColumn* wxDataViewCtrl::GetSortingColumn() const
+{
+ DataBrowserPropertyID propertyID;
+
+ wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast(this->m_peer));
+
+
+ if (MacDataViewListCtrlPtr->GetSortProperty(&propertyID) == noErr)
+ return this->GetColumnPtr(propertyID);
+ else
+ return NULL;
+} /* wxDataViewCtrl::GetSortingColumn() const */
+
+unsigned int wxDataViewCtrl::GetCount() const
+{
+ ItemCount noOfItems;
+
+
+ wxCHECK_MSG(dynamic_cast(this->m_peer)->GetItemCount(&noOfItems) == noErr,0,_("Could not determine number of items"));
+ return noOfItems;
+} /* wxDataViewCtrl::GetCount() const */
+
+wxRect wxDataViewCtrl::GetItemRect(wxDataViewItem const& item, wxDataViewColumn const* columnPtr) const
+{
+ if (item.IsOk() && (columnPtr != NULL))
+ {
+ // variable definition:
+ Rect MacRectangle;
+ wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast(this->m_peer));
+
+ if (MacDataViewListCtrlPtr->GetPartBounds(reinterpret_cast(item.GetID()),columnPtr->GetPropertyID(),kDataBrowserPropertyContentPart,&MacRectangle) == noErr)
+ {
+ // variable definition:
+ wxRect rectangle;
+
+ ::wxMacNativeToRect(&MacRectangle,&rectangle);
+ return rectangle;
+ } /* if */
+ else
+ return wxRect();
+ } /* if */
+ else
+ return wxRect();
+} /* wxDataViewCtrl::GetItemRect(wxDataViewItem const&, unsigned int) const */
+
+wxDataViewItem wxDataViewCtrl::GetSelection() const
+{
+ wxArrayDataBrowserItemID itemIDs;
+
+ wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast(this->m_peer));
+
+
+ if (MacDataViewListCtrlPtr->GetSelectedItemIDs(itemIDs) > 0)
+ return wxDataViewItem(reinterpret_cast(itemIDs[0]));
+ else
+ return wxDataViewItem();
+} /* wxDataViewCtrl::GetSelection() const */
+
+int wxDataViewCtrl::GetSelections(wxDataViewItemArray& sel) const
+{
+ size_t NoOfSelectedItems;
+
+ wxArrayDataBrowserItemID itemIDs;
+
+ wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast(this->m_peer));
+
+
+ NoOfSelectedItems = MacDataViewListCtrlPtr->GetSelectedItemIDs(itemIDs);
+ sel.Empty();
+ sel.SetCount(NoOfSelectedItems);
+ for (size_t i=0; i(itemIDs[i]));
+ return static_cast(NoOfSelectedItems);
+} /* wxDataViewCtrl::GetSelections(wxDataViewItemArray&) const */
+
+void wxDataViewCtrl::HitTest(wxPoint const& point, wxDataViewItem& item, wxDataViewColumn*& columnPtr) const
+{
+ item = wxDataViewItem();
+ columnPtr = NULL;
+} /* wxDataViewCtrl::HitTest(wxPoint const&, wxDataViewItem&, wxDataViewColumn*&) const */
+
+bool wxDataViewCtrl::IsSelected(wxDataViewItem const& item) const
+{
+ wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast(this->m_peer));
+
+
+ return MacDataViewListCtrlPtr->IsItemSelected(reinterpret_cast(item.GetID()));
+} /* wxDataViewCtrl::IsSelected(wxDataViewItem const&) const */
+
+void wxDataViewCtrl::SelectAll()
+{
+ DataBrowserItemID* itemIDPtr;
+
+ Handle handle(::NewHandle(0));
+
+ size_t NoOfItems;
+
+ wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast(this->m_peer));
+
+
+ wxCHECK_RET(MacDataViewListCtrlPtr->GetItems(kDataBrowserNoItem,true,kDataBrowserItemAnyState,handle) == noErr,_("Could not get items."));
+ NoOfItems = static_cast(::GetHandleSize(handle)/sizeof(DataBrowserItemID));
+ HLock(handle);
+ itemIDPtr = (DataBrowserItemID*) (*handle);
+ MacDataViewListCtrlPtr->SetSelectedItems(NoOfItems,itemIDPtr,kDataBrowserItemsAssign);
+ HUnlock(handle);
+ DisposeHandle(handle);
+} /* wxDataViewCtrl::SelectAll() */
+
+void wxDataViewCtrl::Select(wxDataViewItem const& item)
+{
+ if (item.IsOk())
+ {
+ // variable definition and initialization:
+ DataBrowserItemID itemID(reinterpret_cast(item.GetID()));
+ wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast(this->m_peer));
+
+ MacDataViewListCtrlPtr->SetSelectedItems(1,&itemID,kDataBrowserItemsAdd);
+ } /* if */
+} /* wxDataViewCtrl::Select(wxDataViewItem const&) */
+
+void wxDataViewCtrl::SetSelections(wxDataViewItemArray const& sel)
+{
+ size_t const NoOfSelections = sel.GetCount();
+
+ DataBrowserItemID* itemIDs;
+
+ wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast(this->m_peer));
+
+
+ itemIDs = new DataBrowserItemID[NoOfSelections];
+ for (size_t i=0; i(sel[i].GetID());
+ MacDataViewListCtrlPtr->SetSelectedItems(NoOfSelections,itemIDs,kDataBrowserItemsAssign);
+ delete[] itemIDs;
+} /* wxDataViewCtrl::SetSelections(wxDataViewItemArray const&) */
+
+void wxDataViewCtrl::Unselect(wxDataViewItem const& item)
+{
+ if (item.IsOk())
+ {
+ // variable definition and initialization:
+ DataBrowserItemID itemID(reinterpret_cast(item.GetID()));
+ wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast(this->m_peer));
+
+ MacDataViewListCtrlPtr->SetSelectedItems(1,&itemID,kDataBrowserItemsRemove);
+ } /* if */
+} /* wxDataViewCtrl::Unselect(wxDataViewItem const&) */
+
+void wxDataViewCtrl::UnselectAll()
+{
+ DataBrowserItemID* itemIDPtr;
+
+ Handle handle(::NewHandle(0));
+
+ size_t NoOfItems;
+
+ wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast(this->m_peer));
+
+
+ wxCHECK_RET(MacDataViewListCtrlPtr->GetItems(kDataBrowserNoItem,true,kDataBrowserItemAnyState,handle) == noErr,_("Could not get items."));
+ NoOfItems = static_cast(::GetHandleSize(handle)/sizeof(DataBrowserItemID));
+ HLock(handle);
+ itemIDPtr = (DataBrowserItemID*) (*handle);
+ MacDataViewListCtrlPtr->SetSelectedItems(NoOfItems,itemIDPtr,kDataBrowserItemsRemove);
+ HUnlock(handle);
+ DisposeHandle(handle);
+} /* wxDataViewCtrl::UnselectAll() */
+
+// data handling:
+void wxDataViewCtrl::AddChildrenLevel(wxDataViewItem const& parentItem)
+{
+ int NoOfChildren;
+
+ wxDataViewItemArray items;
+
+
+ wxCHECK_RET(this->GetModel() != NULL,_("Model pointer not initialized."));
+ NoOfChildren = this->GetModel()->GetChildren(parentItem,items);
+#if 0
+ for (int i=0; iGetModel()->ItemAdded(parentItem,items[i]);
+#else
+ (void) this->GetModel()->ItemsAdded(parentItem,items);
+#endif
+}
+
+void wxDataViewCtrl::FinishCustomItemEditing()
+{
+ if (this->GetCustomRendererItem().IsOk())
+ {
+ this->GetCustomRendererPtr()->FinishEditing();
+ this->SetCustomRendererItem(wxDataViewItem());
+ this->SetCustomRendererPtr (NULL);
+ }
+}
+
+wxDataViewColumn* wxDataViewCtrl::GetColumnPtr(WXDataBrowserPropertyID propertyID) const
+{
+ // variable definition:
+ ColumnPointerHashMapType::const_iterator Result(this->m_ColumnPointers.find(propertyID));
+
+ if (Result != this->m_ColumnPointers.end())
+ return Result->second;
+ else
+ return NULL;
+}
+
+// inherited methods from wxDataViewCtrlBase
+void wxDataViewCtrl::DoSetExpanderColumn()
+{
+ if (this->GetExpanderColumn() != NULL)
+ {
+ // variable definition and initialization:
+ wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast(this->m_peer));
+
+ (void) MacDataViewListCtrlPtr->SetDisclosureColumn(this->GetExpanderColumn()->GetPropertyID(),false); // second parameter explicitely passed to ensure that arrow is centered
+ }
+}
+
+void wxDataViewCtrl::DoSetIndent()
+{
+ wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast(this->m_peer));
+
+ (void) MacDataViewListCtrlPtr->SetIndent(static_cast(this->GetIndent()));
+}
+
+// event handling:
+void wxDataViewCtrl::OnSize(wxSizeEvent& event)
+{
+ unsigned int const NoOfColumns = this->GetColumnCount();
+
+
+ for (unsigned int i=0; iGetColumn(i));
+
+ if (dataViewColumnPtr != NULL)
+ {
+ // variable definition and initialization:
+ wxDataViewCustomRenderer* dataViewCustomRendererPtr(dynamic_cast(dataViewColumnPtr->GetRenderer()));
+
+ if (dataViewCustomRendererPtr != NULL)
+ dataViewCustomRendererPtr->SetDC(NULL); // reset DC because DC has changed
+ } /* if */
+ } /* for */
+
+ wxMacDataViewDataBrowserListViewControlPointer MacDataViewListCtrlPtr(dynamic_cast(this->m_peer));
+ ControlRef ref = MacDataViewListCtrlPtr->GetControlRef();
+ if (NoOfColumns == 1)
+ {
+ ::SetDataBrowserHasScrollBars( ref, false, true );
+ ::AutoSizeDataBrowserListViewColumns( ref );
+ }
+ if (NoOfColumns > 1)
+ {
+ ::SetDataBrowserHasScrollBars( ref, true, true );
+ }
+
+ event.Skip();
+} /* wxDataViewCtrl::OnSize(wxSizeEvent&) */
+
+IMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl,wxDataViewCtrlBase)
+
+BEGIN_EVENT_TABLE(wxDataViewCtrl,wxDataViewCtrlBase)
+ EVT_SIZE(wxDataViewCtrl::OnSize)
+END_EVENT_TABLE()
+
+#endif
+ // !wxUSE_GENERICDATAVIEWCTRL
+
+#endif
+ // wxUSE_DATAVIEWCTRL
+
diff --git a/src/osx/carbon/dcclient.cpp b/src/osx/carbon/dcclient.cpp
new file mode 100644
index 0000000000..a7f4cb2536
--- /dev/null
+++ b/src/osx/carbon/dcclient.cpp
@@ -0,0 +1,194 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/dcclient.cpp
+// Purpose: wxClientDCImpl class
+// Author: Stefan Csomor
+// Modified by:
+// Created: 01/02/97
+// RCS-ID: $Id$
+// Copyright: (c) Stefan Csomor
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/wxprec.h"
+
+#include "wx/dcclient.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/log.h"
+ #include "wx/window.h"
+ #include "wx/dcmemory.h"
+ #include "wx/settings.h"
+ #include "wx/toplevel.h"
+ #include "wx/math.h"
+ #include "wx/region.h"
+#endif
+
+#include "wx/graphics.h"
+#include "wx/rawbmp.h"
+#include "wx/mac/private.h"
+
+//-----------------------------------------------------------------------------
+// wxWindowDCImpl
+//-----------------------------------------------------------------------------
+
+IMPLEMENT_ABSTRACT_CLASS(wxWindowDCImpl, wxGCDCImpl)
+
+wxWindowDCImpl::wxWindowDCImpl( wxDC *owner )
+ : wxGCDCImpl( owner )
+{
+ m_release = false;
+}
+
+wxWindowDCImpl::wxWindowDCImpl( wxDC *owner, wxWindow *window )
+ : wxGCDCImpl( owner )
+{
+ m_window = window;
+
+ WindowRef rootwindow = (WindowRef) window->MacGetTopLevelWindowRef() ;
+ if (!rootwindow)
+ return;
+
+ m_ok = true ;
+
+ m_window->GetSize( &m_width , &m_height);
+ if ( !m_window->IsShownOnScreen() )
+ m_width = m_height = 0;
+ CGContextRef cg = (CGContextRef) window->MacGetCGContextRef();
+ m_release = false;
+ if ( cg == NULL )
+ {
+ SetGraphicsContext( wxGraphicsContext::Create( window ) ) ;
+ }
+ else
+ {
+ CGContextSaveGState( cg );
+ m_release = true ;
+ // make sure the context is having its origin at the wx-window coordinates of the
+ // view (read at the top of window.cpp about the differences)
+ if ( window->MacGetLeftBorderSize() != 0 || window->MacGetTopBorderSize() != 0 )
+ CGContextTranslateCTM( cg , -window->MacGetLeftBorderSize() , -window->MacGetTopBorderSize() );
+
+ SetGraphicsContext( wxGraphicsContext::CreateFromNative( cg ) );
+ }
+ DoSetClippingRegion( 0 , 0 , m_width , m_height ) ;
+
+ SetBackground(wxBrush(window->GetBackgroundColour(),wxSOLID));
+
+ SetFont( window->GetFont() ) ;
+}
+
+wxWindowDCImpl::~wxWindowDCImpl()
+{
+ if ( m_release )
+ {
+ // this must not necessarily be the current context, we must restore the state of the
+ // cg we started with above (before the CGContextTranslateCTM call)
+ CGContextRef cg = (CGContextRef) m_window->MacGetCGContextRef();
+ CGContextRestoreGState(cg);
+ }
+}
+
+void wxWindowDCImpl::DoGetSize( int* width, int* height ) const
+{
+ if ( width )
+ *width = m_width;
+ if ( height )
+ *height = m_height;
+}
+
+wxBitmap wxWindowDCImpl::DoGetAsBitmap(const wxRect *subrect) const
+{
+ // wxScreenDC is derived from wxWindowDC, so a screen dc will
+ // call this method when a Blit is performed with it as a source.
+ if (!m_window)
+ return wxNullBitmap;
+
+#ifdef __LP64__
+ return wxNullBitmap;
+#else
+ ControlRef handle = (ControlRef) m_window->GetHandle();
+ if ( !handle )
+ return wxNullBitmap;
+
+ HIRect rect;
+ CGImageRef image;
+ CGContextRef context;
+ void* data;
+
+ size_t bytesPerRow;
+
+ HIViewCreateOffscreenImage( handle, 0, &rect, &image);
+
+
+ int width = subrect != NULL ? subrect->width : (int)rect.size.width;
+ int height = subrect != NULL ? subrect->height : (int)rect.size.height ;
+
+ wxBitmap bmp = wxBitmap(width, height, 32);
+
+ context = (CGContextRef)bmp.GetHBITMAP();
+
+ CGContextSaveGState(context);
+
+ CGContextTranslateCTM( context, 0, height );
+ CGContextScaleCTM( context, 1, -1 );
+
+ if ( subrect )
+ rect = CGRectOffset( rect, -subrect->x, -subrect->y ) ;
+ CGContextDrawImage( context, rect, image );
+
+ CGContextRestoreGState(context);
+
+ return bmp;
+#endif
+}
+
+/*
+ * wxClientDCImpl
+ */
+
+IMPLEMENT_ABSTRACT_CLASS(wxClientDCImpl, wxWindowDCImpl)
+
+wxClientDCImpl::wxClientDCImpl( wxDC *owner )
+ : wxWindowDCImpl( owner )
+{
+}
+
+wxClientDCImpl::wxClientDCImpl( wxDC *owner, wxWindow *window ) :
+ wxWindowDCImpl( owner, window )
+{
+ wxCHECK_RET( window, _T("invalid window in wxClientDCImpl") );
+ wxPoint origin = window->GetClientAreaOrigin() ;
+ m_window->GetClientSize( &m_width , &m_height);
+ if ( !m_window->IsShownOnScreen() )
+ m_width = m_height = 0;
+ SetDeviceOrigin( origin.x, origin.y );
+ DoSetClippingRegion( 0 , 0 , m_width , m_height ) ;
+}
+
+wxClientDCImpl::~wxClientDCImpl()
+{
+}
+
+/*
+ * wxPaintDCImpl
+ */
+
+IMPLEMENT_ABSTRACT_CLASS(wxPaintDCImpl, wxWindowDCImpl)
+
+wxPaintDCImpl::wxPaintDCImpl( wxDC *owner )
+ : wxWindowDCImpl( owner )
+{
+}
+
+wxPaintDCImpl::wxPaintDCImpl( wxDC *owner, wxWindow *window ) :
+ wxWindowDCImpl( owner, window )
+{
+ wxPoint origin = window->GetClientAreaOrigin() ;
+ m_window->GetClientSize( &m_width , &m_height);
+ SetDeviceOrigin( origin.x, origin.y );
+ DoSetClippingRegion( 0 , 0 , m_width , m_height ) ;
+}
+
+wxPaintDCImpl::~wxPaintDCImpl()
+{
+}
diff --git a/src/osx/carbon/dcmemory.cpp b/src/osx/carbon/dcmemory.cpp
new file mode 100644
index 0000000000..4567352d94
--- /dev/null
+++ b/src/osx/carbon/dcmemory.cpp
@@ -0,0 +1,116 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/dcmemory.cpp
+// Purpose: wxMemoryDC class
+// Author: Stefan Csomor
+// Modified by:
+// Created: 01/02/97
+// RCS-ID: $Id$
+// Copyright: (c) Stefan Csomor
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/wxprec.h"
+
+#include "wx/dcmemory.h"
+#include "wx/graphics.h"
+#include "wx/mac/dcmemory.h"
+
+#include "wx/mac/private.h"
+
+//-----------------------------------------------------------------------------
+// wxMemoryDCImpl
+//-----------------------------------------------------------------------------
+
+IMPLEMENT_ABSTRACT_CLASS(wxMemoryDCImpl,wxPaintDCImpl)
+
+
+wxMemoryDCImpl::wxMemoryDCImpl( wxMemoryDC *owner )
+ : wxPaintDCImpl( owner )
+{
+ Init();
+}
+
+wxMemoryDCImpl::wxMemoryDCImpl( wxMemoryDC *owner, wxBitmap& bitmap )
+ : wxPaintDCImpl( owner )
+{
+ Init();
+ DoSelect(bitmap);
+}
+
+wxMemoryDCImpl::wxMemoryDCImpl( wxMemoryDC *owner, wxDC * WXUNUSED(dc) )
+ : wxPaintDCImpl( owner )
+{
+ Init();
+}
+
+void wxMemoryDCImpl::Init()
+{
+ m_ok = true;
+ SetBackground(*wxWHITE_BRUSH);
+ SetBrush(*wxWHITE_BRUSH);
+ SetPen(*wxBLACK_PEN);
+ SetFont(*wxNORMAL_FONT);
+ m_ok = false;
+}
+
+wxMemoryDCImpl::~wxMemoryDCImpl()
+{
+ if ( m_selected.Ok() )
+ {
+ m_selected.EndRawAccess() ;
+ delete m_graphicContext ;
+ m_graphicContext = NULL ;
+ }
+}
+
+void wxMemoryDCImpl::DoSelect( const wxBitmap& bitmap )
+{
+ if ( m_selected.Ok() )
+ {
+ m_selected.EndRawAccess() ;
+ delete m_graphicContext ;
+ m_graphicContext = NULL ;
+ }
+
+ m_selected = bitmap;
+ if (m_selected.Ok())
+ {
+ if ( m_selected.GetDepth() != 1 )
+ m_selected.UseAlpha() ;
+ m_selected.BeginRawAccess() ;
+ m_width = bitmap.GetWidth();
+ m_height = bitmap.GetHeight();
+ CGColorSpaceRef genericColorSpace = wxMacGetGenericRGBColorSpace();
+ CGContextRef bmCtx = (CGContextRef) m_selected.GetHBITMAP();
+
+ if ( bmCtx )
+ {
+ CGContextSetFillColorSpace( bmCtx, genericColorSpace );
+ CGContextSetStrokeColorSpace( bmCtx, genericColorSpace );
+ SetGraphicsContext( wxGraphicsContext::CreateFromNative( bmCtx ) );
+ }
+ m_ok = (m_graphicContext != NULL) ;
+ }
+ else
+ {
+ m_ok = false;
+ }
+}
+
+void wxMemoryDCImpl::DoGetSize( int *width, int *height ) const
+{
+ if (m_selected.Ok())
+ {
+ if (width)
+ (*width) = m_selected.GetWidth();
+ if (height)
+ (*height) = m_selected.GetHeight();
+ }
+ else
+ {
+ if (width)
+ (*width) = 0;
+ if (height)
+ (*height) = 0;
+ }
+}
diff --git a/src/osx/carbon/dcprint.cpp b/src/osx/carbon/dcprint.cpp
new file mode 100644
index 0000000000..ccc58d99ff
--- /dev/null
+++ b/src/osx/carbon/dcprint.cpp
@@ -0,0 +1,393 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/dcprint.cpp
+// Purpose: wxPrinterDC class
+// Author: Julian Smart
+// Modified by:
+// Created: 01/02/97
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#if wxUSE_PRINTING_ARCHITECTURE
+
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+
+#include "wx/dcprint.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/msgdlg.h"
+ #include "wx/math.h"
+#endif
+
+#include "wx/mac/uma.h"
+#include "wx/mac/private/print.h"
+#include "wx/mac/carbon/dcprint.h"
+#include "wx/graphics.h"
+
+IMPLEMENT_ABSTRACT_CLASS(wxPrinterDCImpl, wxGCDCImpl)
+
+class wxNativePrinterDC
+{
+public :
+ wxNativePrinterDC() {}
+ virtual ~wxNativePrinterDC() {}
+ virtual bool StartDoc( wxPrinterDC* dc , const wxString& message ) = 0;
+ virtual void EndDoc( wxPrinterDC* dc ) = 0;
+ virtual void StartPage( wxPrinterDC* dc ) = 0;
+ virtual void EndPage( wxPrinterDC* dc ) = 0;
+ virtual void GetSize( int *w , int *h) const = 0 ;
+ virtual wxSize GetPPI() const = 0 ;
+
+ // returns 0 in case of no Error, otherwise platform specific error codes
+ virtual wxUint32 GetStatus() const = 0 ;
+ bool Ok() { return GetStatus() == 0 ; }
+
+ static wxNativePrinterDC* Create(wxPrintData* data) ;
+} ;
+
+class wxMacCarbonPrinterDC : public wxNativePrinterDC
+{
+public :
+ wxMacCarbonPrinterDC( wxPrintData* data ) ;
+ virtual ~wxMacCarbonPrinterDC() ;
+ virtual bool StartDoc( wxPrinterDC* dc , const wxString& message ) ;
+ virtual void EndDoc( wxPrinterDC* dc ) ;
+ virtual void StartPage( wxPrinterDC* dc ) ;
+ virtual void EndPage( wxPrinterDC* dc ) ;
+ virtual wxUint32 GetStatus() const { return m_err ; }
+ virtual void GetSize( int *w , int *h) const ;
+ virtual wxSize GetPPI() const ;
+private :
+ wxCoord m_maxX ;
+ wxCoord m_maxY ;
+ wxSize m_ppi ;
+ OSStatus m_err ;
+} ;
+
+wxMacCarbonPrinterDC::wxMacCarbonPrinterDC( wxPrintData* data )
+{
+ m_err = noErr ;
+ wxMacCarbonPrintData *native = (wxMacCarbonPrintData*) data->GetNativeData() ;
+
+ PMRect rPage;
+ m_err = PMGetAdjustedPageRect(native->m_macPageFormat, &rPage);
+ if ( m_err != noErr )
+ return;
+
+ m_maxX = wxCoord(rPage.right - rPage.left) ;
+ m_maxY = wxCoord(rPage.bottom - rPage.top);
+
+ PMResolution res;
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+ if ( PMPrinterGetOutputResolution != NULL )
+ {
+ PMPrinter printer;
+ m_err = PMSessionGetCurrentPrinter(native->m_macPrintSession, &printer);
+ if ( m_err == noErr )
+ {
+ m_err = PMPrinterGetOutputResolution( printer, native->m_macPrintSettings, &res) ;
+ if ( m_err == -9589 /* kPMKeyNotFound */ )
+ {
+ m_err = noErr ;
+ res.hRes = res.vRes = 300;
+ }
+ }
+ }
+ else
+#endif
+ {
+#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
+ m_err = PMGetResolution((PMPageFormat) (native->m_macPageFormat), &res);
+#endif
+ }
+
+ m_ppi = wxSize(int(res.hRes), int(res.vRes));
+}
+
+wxMacCarbonPrinterDC::~wxMacCarbonPrinterDC()
+{
+}
+
+wxNativePrinterDC* wxNativePrinterDC::Create(wxPrintData* data)
+{
+ return new wxMacCarbonPrinterDC(data) ;
+}
+
+bool wxMacCarbonPrinterDC::StartDoc( wxPrinterDC* dc , const wxString& WXUNUSED(message) )
+{
+ if ( m_err )
+ return false ;
+
+ wxPrinterDCImpl *impl = (wxPrinterDCImpl*) dc->GetImpl();
+ wxMacCarbonPrintData *native = (wxMacCarbonPrintData*) impl->GetPrintData().GetNativeData() ;
+
+ m_err = PMSessionBeginCGDocumentNoDialog(native->m_macPrintSession,
+ native->m_macPrintSettings,
+ native->m_macPageFormat);
+ if ( m_err != noErr )
+ return false;
+
+ PMRect rPage;
+ m_err = PMGetAdjustedPageRect(native->m_macPageFormat, &rPage);
+ if ( m_err != noErr )
+ return false ;
+
+ m_maxX = wxCoord(rPage.right - rPage.left) ;
+ m_maxY = wxCoord(rPage.bottom - rPage.top);
+
+ PMResolution res;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+ if ( PMPrinterGetOutputResolution != NULL )
+ {
+ PMPrinter printer;
+ m_err = PMSessionGetCurrentPrinter(native->m_macPrintSession, &printer);
+ if ( m_err == noErr )
+ {
+ m_err = PMPrinterGetOutputResolution( printer, native->m_macPrintSettings, &res) ;
+ if ( m_err == -9589 /* kPMKeyNotFound */ )
+ {
+ m_err = noErr ;
+ res.hRes = res.vRes = 300;
+ }
+ }
+ }
+ else
+#endif
+ {
+#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
+ m_err = PMGetResolution((PMPageFormat) (native->m_macPageFormat), &res);
+#endif
+ }
+
+ m_ppi = wxSize(int(res.hRes), int(res.vRes));
+ return true ;
+}
+
+void wxMacCarbonPrinterDC::EndDoc( wxPrinterDC* dc )
+{
+ if ( m_err )
+ return ;
+
+ wxPrinterDCImpl *impl = (wxPrinterDCImpl*) dc->GetImpl();
+ wxMacCarbonPrintData *native = (wxMacCarbonPrintData*) impl->GetPrintData().GetNativeData() ;
+
+ m_err = PMSessionEndDocumentNoDialog(native->m_macPrintSession);
+}
+
+void wxMacCarbonPrinterDC::StartPage( wxPrinterDC* dc )
+{
+ if ( m_err )
+ return ;
+
+ wxPrinterDCImpl *impl = (wxPrinterDCImpl*) dc->GetImpl();
+ wxMacCarbonPrintData *native = (wxMacCarbonPrintData*) impl->GetPrintData().GetNativeData() ;
+
+ m_err = PMSessionBeginPageNoDialog(native->m_macPrintSession,
+ native->m_macPageFormat,
+ nil);
+
+ CGContextRef pageContext;
+
+ if ( m_err == noErr )
+ {
+ m_err = PMSessionGetCGGraphicsContext(native->m_macPrintSession,
+ &pageContext );
+ }
+
+ if ( m_err != noErr )
+ {
+ PMSessionEndPageNoDialog(native->m_macPrintSession);
+ PMSessionEndDocumentNoDialog(native->m_macPrintSession);
+ }
+ else
+ {
+ PMRect rPage;
+
+ m_err = PMGetAdjustedPageRect(native->m_macPageFormat, &rPage);
+ if ( !m_err )
+ {
+ PMRect paperRect ;
+ PMGetAdjustedPaperRect( native->m_macPageFormat , &paperRect ) ;
+ // make sure (0,0) is at the upper left of the printable area (wx conventions)
+ // Core Graphics initially has the lower left of the paper as 0,0
+ CGContextTranslateCTM( pageContext , (CGFloat) -paperRect.left , (CGFloat) paperRect.bottom ) ;
+ CGContextScaleCTM( pageContext , 1 , -1 ) ;
+ }
+ // since this is a non-critical error, we set the flag back
+ m_err = noErr ;
+ }
+ impl->SetGraphicsContext( wxGraphicsContext::CreateFromNative( pageContext ) );
+}
+
+void wxMacCarbonPrinterDC::EndPage( wxPrinterDC* dc )
+{
+ if ( m_err )
+ return ;
+
+ wxPrinterDCImpl *impl = (wxPrinterDCImpl*) dc->GetImpl();
+ wxMacCarbonPrintData *native = (wxMacCarbonPrintData*) impl->GetPrintData().GetNativeData() ;
+
+ m_err = PMSessionEndPageNoDialog(native->m_macPrintSession);
+ if ( m_err != noErr )
+ {
+ PMSessionEndDocumentNoDialog(native->m_macPrintSession);
+ }
+ // the cg context we got when starting the page isn't valid anymore, so replace it
+ impl->SetGraphicsContext( wxGraphicsContext::Create() );
+}
+
+void wxMacCarbonPrinterDC::GetSize( int *w , int *h) const
+{
+ if ( w )
+ *w = m_maxX ;
+ if ( h )
+ *h = m_maxY ;
+}
+
+wxSize wxMacCarbonPrinterDC::GetPPI() const
+{
+ return m_ppi ;
+};
+
+//
+//
+//
+
+wxPrinterDCImpl::wxPrinterDCImpl( wxPrinterDC *owner, const wxPrintData& printdata )
+ : wxGCDCImpl( owner )
+{
+ m_ok = false ;
+ m_printData = printdata ;
+ m_printData.ConvertToNative() ;
+ m_nativePrinterDC = wxNativePrinterDC::Create( &m_printData ) ;
+ if ( m_nativePrinterDC )
+ {
+ m_ok = m_nativePrinterDC->Ok() ;
+ if ( !m_ok )
+ {
+ wxString message ;
+ message.Printf( wxT("Print Error %u"), m_nativePrinterDC->GetStatus() ) ;
+ wxMessageDialog dialog( NULL , message , wxEmptyString, wxICON_HAND | wxOK) ;
+ dialog.ShowModal();
+ }
+ else
+ {
+ wxSize sz = GetPPI();
+ m_mm_to_pix_x = mm2inches * sz.x;
+ m_mm_to_pix_y = mm2inches * sz.y;
+ }
+ // we need at least a measuring context because people start measuring before a page
+ // gets printed at all
+ SetGraphicsContext( wxGraphicsContext::Create() );
+ }
+}
+
+wxSize wxPrinterDCImpl::GetPPI() const
+{
+ return m_nativePrinterDC->GetPPI() ;
+}
+
+wxPrinterDCImpl::~wxPrinterDCImpl()
+{
+ delete m_nativePrinterDC ;
+}
+
+bool wxPrinterDCImpl::StartDoc( const wxString& message )
+{
+ wxASSERT_MSG( IsOk() , wxT("Called wxPrinterDC::StartDoc from an invalid object") ) ;
+
+ if ( !m_ok )
+ return false ;
+
+ if ( m_nativePrinterDC->StartDoc( (wxPrinterDC*) GetOwner(), message ) )
+ {
+ // in case we have to do additional things when successful
+ }
+ m_ok = m_nativePrinterDC->Ok() ;
+ if ( !m_ok )
+ {
+ wxString message ;
+ message.Printf( wxT("Print Error %u"), m_nativePrinterDC->GetStatus() ) ;
+ wxMessageDialog dialog( NULL , message , wxEmptyString, wxICON_HAND | wxOK) ;
+ dialog.ShowModal();
+ }
+
+ return m_ok ;
+}
+
+void wxPrinterDCImpl::EndDoc(void)
+{
+ if ( !m_ok )
+ return ;
+
+ m_nativePrinterDC->EndDoc( (wxPrinterDC*) GetOwner() ) ;
+ m_ok = m_nativePrinterDC->Ok() ;
+
+ if ( !m_ok )
+ {
+ wxString message ;
+ message.Printf( wxT("Print Error %u"), m_nativePrinterDC->GetStatus() ) ;
+ wxMessageDialog dialog( NULL , message , wxEmptyString, wxICON_HAND | wxOK) ;
+ dialog.ShowModal();
+ }
+}
+
+wxRect wxPrinterDCImpl::GetPaperRect()
+{
+ wxCoord w, h;
+ GetOwner()->GetSize(&w, &h);
+ wxRect pageRect(0, 0, w, h);
+ wxMacCarbonPrintData *native = (wxMacCarbonPrintData*) m_printData.GetNativeData() ;
+ OSStatus err = noErr ;
+ PMRect rPaper;
+ err = PMGetAdjustedPaperRect(native->m_macPageFormat, &rPaper);
+ if ( err != noErr )
+ return pageRect;
+ return wxRect(wxCoord(rPaper.left), wxCoord(rPaper.top),
+ wxCoord(rPaper.right - rPaper.left), wxCoord(rPaper.bottom - rPaper.top));
+}
+
+void wxPrinterDCImpl::StartPage()
+{
+ if ( !m_ok )
+ return ;
+
+ m_logicalFunction = wxCOPY;
+ // m_textAlignment = wxALIGN_TOP_LEFT;
+ m_backgroundMode = wxTRANSPARENT;
+
+ m_textForegroundColour = *wxBLACK;
+ m_textBackgroundColour = *wxWHITE;
+ m_pen = *wxBLACK_PEN;
+ m_font = *wxNORMAL_FONT;
+ m_brush = *wxTRANSPARENT_BRUSH;
+ m_backgroundBrush = *wxWHITE_BRUSH;
+
+ m_nativePrinterDC->StartPage( (wxPrinterDC*) GetOwner() ) ;
+ m_ok = m_nativePrinterDC->Ok() ;
+
+}
+
+void wxPrinterDCImpl::EndPage()
+{
+ if ( !m_ok )
+ return ;
+
+ m_nativePrinterDC->EndPage( (wxPrinterDC*) GetOwner() );
+ m_ok = m_nativePrinterDC->Ok() ;
+}
+
+void wxPrinterDCImpl::DoGetSize(int *width, int *height) const
+{
+ wxCHECK_RET( m_ok , _T("GetSize() doesn't work without a valid wxPrinterDC") );
+ m_nativePrinterDC->GetSize(width, height ) ;
+}
+
+#endif
diff --git a/src/osx/carbon/dcscreen.cpp b/src/osx/carbon/dcscreen.cpp
new file mode 100644
index 0000000000..ad8ac0be4a
--- /dev/null
+++ b/src/osx/carbon/dcscreen.cpp
@@ -0,0 +1,59 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/dcscreen.cpp
+// Purpose: wxScreenDC class
+// Author: Stefan Csomor
+// Modified by:
+// Created: 1998-01-01
+// RCS-ID: $Id$
+// Copyright: (c) Stefan Csomor
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/wxprec.h"
+
+#include "wx/dcscreen.h"
+#include "wx/mac/carbon/dcscreen.h"
+
+#include "wx/mac/uma.h"
+#include "wx/graphics.h"
+
+IMPLEMENT_ABSTRACT_CLASS(wxScreenDCImpl, wxWindowDCImpl)
+
+// TODO : for the Screenshot use case, which doesn't work in Quartz
+// we should do a GetAsBitmap using something like
+// http://www.cocoabuilder.com/archive/message/cocoa/2005/8/13/144256
+
+// Create a DC representing the whole screen
+wxScreenDCImpl::wxScreenDCImpl( wxDC *owner ) :
+ wxWindowDCImpl( owner )
+{
+#ifdef __LP64__
+ m_graphicContext = NULL;
+ m_ok = false ;
+#else
+ CGRect cgbounds ;
+ cgbounds = CGDisplayBounds(CGMainDisplayID());
+ Rect bounds;
+ bounds.top = (short)cgbounds.origin.y;
+ bounds.left = (short)cgbounds.origin.x;
+ bounds.bottom = bounds.top + (short)cgbounds.size.height;
+ bounds.right = bounds.left + (short)cgbounds.size.width;
+ WindowAttributes overlayAttributes = kWindowIgnoreClicksAttribute;
+ CreateNewWindow( kOverlayWindowClass, overlayAttributes, &bounds, (WindowRef*) &m_overlayWindow );
+ ShowWindow((WindowRef)m_overlayWindow);
+ SetGraphicsContext( wxGraphicsContext::CreateFromNativeWindow( m_overlayWindow ) );
+ m_width = (wxCoord)cgbounds.size.width;
+ m_height = (wxCoord)cgbounds.size.height;
+ m_ok = true ;
+#endif
+}
+
+wxScreenDCImpl::~wxScreenDCImpl()
+{
+ delete m_graphicContext;
+ m_graphicContext = NULL;
+#ifdef __LP64__
+#else
+ DisposeWindow((WindowRef) m_overlayWindow );
+#endif
+}
diff --git a/src/osx/carbon/dialog.cpp b/src/osx/carbon/dialog.cpp
new file mode 100644
index 0000000000..8743e10547
--- /dev/null
+++ b/src/osx/carbon/dialog.cpp
@@ -0,0 +1,185 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/dialog.cpp
+// Purpose: wxDialog class
+// Author: Stefan Csomor
+// Modified by:
+// Created: 1998-01-01
+// RCS-ID: $Id$
+// Copyright: (c) Stefan Csomor
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/wxprec.h"
+
+#include "wx/dialog.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/app.h"
+ #include "wx/utils.h"
+ #include "wx/frame.h"
+ #include "wx/settings.h"
+#endif // WX_PRECOMP
+
+#include "wx/mac/uma.h"
+
+
+// Lists to keep track of windows, so we can disable/enable them
+// for modal dialogs
+wxList wxModalDialogs;
+
+IMPLEMENT_DYNAMIC_CLASS(wxDialog, wxTopLevelWindow)
+
+void wxDialog::Init()
+{
+ m_isModalStyle = false;
+}
+
+bool wxDialog::Create( wxWindow *parent,
+ wxWindowID id,
+ const wxString& title,
+ const wxPoint& pos,
+ const wxSize& size,
+ long style,
+ const wxString& name )
+{
+ SetExtraStyle( GetExtraStyle() | wxTOPLEVEL_EX_DIALOG );
+
+ // All dialogs should really have this style...
+ style |= wxTAB_TRAVERSAL;
+
+ // ...but not these styles
+ style &= ~(wxYES | wxOK | wxNO); // | wxCANCEL
+
+ if ( !wxTopLevelWindow::Create( parent, id, title, pos, size, style, name ) )
+ return false;
+
+ return true;
+}
+
+void wxDialog::SetModal( bool flag )
+{
+ if ( flag )
+ {
+ m_isModalStyle = true;
+
+ SetWindowModality( (WindowRef)MacGetWindowRef(), kWindowModalityAppModal, NULL ) ;
+ }
+ else
+ {
+ m_isModalStyle = false;
+ }
+}
+
+wxDialog::~wxDialog()
+{
+ m_isBeingDeleted = true;
+
+ // if the dialog is modal, this will end its event loop
+ Show(false);
+}
+
+// On mac command-stop does the same thing as Esc, let the base class know
+// about it
+bool wxDialog::IsEscapeKey(const wxKeyEvent& event)
+{
+ if ( event.GetKeyCode() == '.' && event.GetModifiers() == wxMOD_CMD )
+ return true;
+
+ return wxDialogBase::IsEscapeKey(event);
+}
+
+bool wxDialog::IsModal() const
+{
+ return wxModalDialogs.Find((wxDialog *)this) != NULL; // const_cast
+ // return m_isModalStyle;
+}
+
+
+bool wxDialog::Show(bool show)
+{
+ if ( !wxDialogBase::Show(show) )
+ // nothing to do
+ return false;
+
+ if (show && CanDoLayoutAdaptation())
+ DoLayoutAdaptation();
+
+ if ( show )
+ // usually will result in TransferDataToWindow() being called
+ InitDialog();
+
+ HiliteMenu(0);
+
+ if ( m_isModalStyle )
+ {
+ if ( show )
+ {
+ DoShowModal();
+ }
+ else // end of modal dialog
+ {
+ // this will cause IsModalShowing() return false and our local
+ // message loop will terminate
+ wxModalDialogs.DeleteObject(this);
+ }
+ }
+
+ return true;
+}
+
+void wxDialog::DoShowModal()
+{
+ wxCHECK_RET( !IsModal(), wxT("DoShowModal() called twice") );
+
+ wxModalDialogs.Append(this);
+
+ SetFocus() ;
+
+ WindowRef windowRef = (WindowRef) MacGetWindowRef();
+ WindowGroupRef windowGroup;
+ WindowGroupRef formerParentGroup;
+ bool resetGroupParent = false;
+
+ if ( GetParent() == NULL )
+ {
+ windowGroup = GetWindowGroup(windowRef) ;
+ formerParentGroup = GetWindowGroupParent( windowGroup );
+ SetWindowGroupParent( windowGroup, GetWindowGroupOfClass( kMovableModalWindowClass ) );
+ resetGroupParent = true;
+ }
+ BeginAppModalStateForWindow(windowRef) ;
+
+ while ( IsModal() )
+ {
+ wxTheApp->MacDoOneEvent() ;
+ // calls process idle itself
+ }
+
+ EndAppModalStateForWindow(windowRef) ;
+ if ( resetGroupParent )
+ {
+ SetWindowGroupParent( windowGroup , formerParentGroup );
+ }
+}
+
+
+// Replacement for Show(true) for modal dialogs - returns return code
+int wxDialog::ShowModal()
+{
+ if ( !m_isModalStyle )
+ SetModal(true);
+
+ Show(true);
+
+ return GetReturnCode();
+}
+
+// NB: this function (surprizingly) may be called for both modal and modeless
+// dialogs and should work for both of them
+void wxDialog::EndModal(int retCode)
+{
+ SetReturnCode(retCode);
+ Show(false);
+ SetModal(false);
+}
+
diff --git a/src/osx/carbon/dirdlg.cpp b/src/osx/carbon/dirdlg.cpp
new file mode 100644
index 0000000000..5caa7f6b4b
--- /dev/null
+++ b/src/osx/carbon/dirdlg.cpp
@@ -0,0 +1,145 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/dirdlg.cpp
+// Purpose: wxDirDialog
+// Author: Stefan Csomor
+// Modified by:
+// Created: 1998-01-01
+// RCS-ID: $Id$
+// Copyright: (c) Stefan Csomor
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/wxprec.h"
+
+#if wxUSE_DIRDLG
+
+#include "wx/dirdlg.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/utils.h"
+ #include "wx/dialog.h"
+ #include "wx/cmndata.h"
+#endif // WX_PRECOMP
+
+#include "wx/filename.h"
+
+#include "wx/mac/private.h"
+
+#ifdef __DARWIN__
+ #include
+#else
+ #include
+#endif
+
+IMPLEMENT_CLASS(wxDirDialog, wxDialog)
+
+static pascal void NavEventProc(
+ NavEventCallbackMessage inSelector,
+ NavCBRecPtr ioParams,
+ NavCallBackUserData ioUserData );
+
+static NavEventUPP sStandardNavEventFilter = NewNavEventUPP(NavEventProc);
+
+static pascal void NavEventProc(
+ NavEventCallbackMessage inSelector,
+ NavCBRecPtr ioParams,
+ NavCallBackUserData ioUserData )
+{
+ wxDirDialog * data = ( wxDirDialog *) ioUserData ;
+ if ( inSelector == kNavCBStart )
+ {
+ if (data && !data->GetPath().empty() )
+ {
+ // Set default location for the modern Navigation APIs
+ // Apple Technical Q&A 1151
+ FSRef theFile;
+ wxMacPathToFSRef(data->GetPath(), &theFile);
+ AEDesc theLocation = { typeNull, NULL };
+ if (noErr == ::AECreateDesc(typeFSRef, &theFile, sizeof(FSRef), &theLocation))
+ ::NavCustomControl(ioParams->context, kNavCtlSetLocation, (void *) &theLocation);
+ }
+ }
+}
+
+wxDirDialog::wxDirDialog(wxWindow *parent,
+ const wxString& message,
+ const wxString& defaultPath,
+ long WXUNUSED(style),
+ const wxPoint& WXUNUSED(pos),
+ const wxSize& WXUNUSED(size),
+ const wxString& WXUNUSED(name))
+{
+ wxASSERT_MSG( NavServicesAvailable() , wxT("Navigation Services are not running") ) ;
+ m_message = message;
+ m_parent = parent;
+ m_path = defaultPath;
+}
+
+int wxDirDialog::ShowModal()
+{
+ NavDialogRef dialog = NULL;
+ NavDialogCreationOptions options;
+ NavReplyRecord reply ;
+ bool disposeReply = false ;
+ OSStatus err = noErr;
+
+ err = NavGetDefaultDialogCreationOptions(&options);
+ options.optionFlags &= ~kNavAllowMultipleFiles;
+ if (err == noErr)
+ {
+ wxCFStringRef message(m_message, GetFont().GetEncoding());
+ options.message = message;
+ err = NavCreateChooseFolderDialog(&options, sStandardNavEventFilter , NULL, this , &dialog);
+ if (err == noErr)
+ {
+ err = NavDialogRun(dialog);
+ if ( err == noErr )
+ {
+ err = NavDialogGetReply(dialog, &reply);
+ disposeReply = true ;
+ }
+ }
+ }
+
+ if ( err == noErr )
+ {
+ if ( reply.validRecord )
+ {
+ FSRef folderInfo;
+ AEDesc specDesc ;
+
+ OSErr err = ::AECoerceDesc( &reply.selection , typeFSRef, &specDesc);
+ if ( err != noErr )
+ {
+ m_path = wxEmptyString ;
+ }
+ else
+ {
+ folderInfo = **(FSRef**) specDesc.dataHandle;
+ m_path = wxMacFSRefToPath( &folderInfo ) ;
+ if (specDesc.dataHandle != nil)
+ {
+ ::AEDisposeDesc(&specDesc);
+ }
+ }
+ }
+ else
+ {
+ err = paramErr ; // could be any error, only used for giving back wxID_CANCEL
+ }
+ }
+
+ if ( disposeReply )
+ ::NavDisposeReply(&reply);
+
+ // apparently cancelling shouldn't change m_path
+ if ( err != noErr && err != userCanceledErr )
+ m_path = wxEmptyString ;
+
+ if ( dialog )
+ ::NavDialogDispose(dialog);
+
+ return (err == noErr) ? wxID_OK : wxID_CANCEL ;
+}
+
+#endif
diff --git a/src/osx/carbon/dirmac.cpp b/src/osx/carbon/dirmac.cpp
new file mode 100644
index 0000000000..52e9a61e0f
--- /dev/null
+++ b/src/osx/carbon/dirmac.cpp
@@ -0,0 +1,269 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: mac/dirmac.cpp
+// Purpose: wxDir implementation for Mac
+// Author: Stefan Csomor
+// Modified by:
+// Created: 08.12.99
+// RCS-ID: $Id$
+// Copyright: (c) 1999 Stefan Csomor
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+
+#include "wx/dir.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/intl.h"
+ #include "wx/log.h"
+#endif // PCH
+
+#include "wx/filefn.h" // for wxDirExists()
+#include "wx/filename.h"
+#include "wx/mac/private.h"
+
+// ----------------------------------------------------------------------------
+// private classes
+// ----------------------------------------------------------------------------
+
+// this class stores everything we need to enumerate the files
+class wxDirData
+{
+public:
+ wxDirData(const wxString& dirname);
+ ~wxDirData();
+
+ void Close() ;
+ void SetFileSpec(const wxString& filespec) { m_filespec = filespec; }
+ void SetFlags(int flags) { m_flags = flags; }
+
+ bool Read(wxString *filename); // reads the next
+ void Rewind() ;
+
+ const wxString& GetName() const { return m_dirname; }
+
+private:
+ FSIterator m_iterator ;
+
+ wxString m_dirname;
+ wxString m_filespec;
+
+ int m_flags;
+};
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// wxDirData
+// ----------------------------------------------------------------------------
+
+wxDirData::wxDirData(const wxString& dirname)
+ : m_dirname(dirname)
+{
+ // throw away the trailing slashes
+ size_t n = m_dirname.length();
+ wxCHECK_RET( n, _T("empty dir name in wxDir") );
+
+ while ( n > 0 && wxIsPathSeparator(m_dirname[--n]) )
+ ;
+
+ m_dirname.Truncate(n + 1);
+ m_iterator = NULL ;
+}
+
+wxDirData::~wxDirData()
+{
+ Close() ;
+}
+
+void wxDirData::Close()
+{
+ if ( m_iterator )
+ {
+ FSCloseIterator( m_iterator ) ;
+ m_iterator = NULL ;
+ }
+}
+
+void wxDirData::Rewind()
+{
+ Close() ;
+}
+
+bool wxDirData::Read(wxString *filename)
+{
+ wxString result;
+ OSStatus err = noErr ;
+ if ( NULL == m_iterator )
+ {
+ FSRef dirRef;
+ err = wxMacPathToFSRef( m_dirname , &dirRef ) ;
+ if ( err == noErr )
+ {
+ err = FSOpenIterator(&dirRef, kFSIterateFlat, &m_iterator);
+ }
+ if ( err )
+ {
+ Close() ;
+ return false ;
+ }
+ }
+
+ wxString name ;
+ wxString lowerfilespec = m_filespec.Lower();
+
+ while( noErr == err )
+ {
+ HFSUniStr255 uniname ;
+ FSRef fileRef;
+ FSCatalogInfo catalogInfo;
+ ItemCount fetched = 0;
+
+ err = FSGetCatalogInfoBulk( m_iterator, 1, &fetched, NULL, kFSCatInfoNodeFlags | kFSCatInfoFinderInfo , &catalogInfo , &fileRef, NULL, &uniname );
+
+ // expected error codes
+
+ if ( errFSNoMoreItems == err )
+ return false ;
+ if ( afpAccessDenied == err )
+ return false ;
+
+ if ( noErr != err )
+ break ;
+
+ name = wxMacHFSUniStrToString( &uniname ) ;
+ wxString lowername = name.Lower();
+
+ if ( ( name == wxT(".") || name == wxT("..") ) && !(m_flags & wxDIR_DOTDOT) )
+ continue;
+
+ if ( ( name[0U] == '.' ) && !(m_flags & wxDIR_HIDDEN ) )
+ continue ;
+
+ if ( (((FileInfo*)&catalogInfo.finderInfo)->finderFlags & kIsInvisible ) && !(m_flags & wxDIR_HIDDEN ) )
+ continue ;
+
+ // its a dir and we don't want it
+ if ( (catalogInfo.nodeFlags & kFSNodeIsDirectoryMask) && !(m_flags & wxDIR_DIRS) )
+ continue ;
+
+ // its a file but we don't want it
+ if ( (catalogInfo.nodeFlags & kFSNodeIsDirectoryMask) == 0 && !(m_flags & wxDIR_FILES ) )
+ continue ;
+
+ if ( m_filespec.empty() || m_filespec == wxT("*.*") || m_filespec == wxT("*") )
+ {
+ }
+ else if ( !wxMatchWild(lowerfilespec, lowername , false) )
+ {
+ continue ;
+ }
+
+ break ;
+ }
+ if ( err != noErr )
+ {
+ return false ;
+ }
+
+ *filename = name ;
+ return true;
+}
+
+// ----------------------------------------------------------------------------
+// wxDir helpers
+// ----------------------------------------------------------------------------
+
+/* static */
+bool wxDir::Exists(const wxString& dir)
+{
+ return wxDirExists(dir);
+}
+
+// ----------------------------------------------------------------------------
+// wxDir construction/destruction
+// ----------------------------------------------------------------------------
+
+wxDir::wxDir(const wxString& dirname)
+{
+ m_data = NULL;
+
+ (void)Open(dirname);
+}
+
+bool wxDir::Open(const wxString& dirname)
+{
+ delete m_data;
+ m_data = new wxDirData(dirname);
+
+ return true;
+}
+
+bool wxDir::IsOpened() const
+{
+ return m_data != NULL;
+}
+
+wxString wxDir::GetName() const
+{
+ wxString name;
+ if ( m_data )
+ {
+ name = m_data->GetName();
+ if ( !name.empty() && (name.Last() == _T('/')) )
+ {
+ // chop off the last (back)slash
+ name.Truncate(name.length() - 1);
+ }
+ }
+
+ return name;
+}
+
+wxDir::~wxDir()
+{
+ delete m_data;
+ m_data = NULL;
+}
+
+// ----------------------------------------------------------------------------
+// wxDir enumerating
+// ----------------------------------------------------------------------------
+
+bool wxDir::GetFirst(wxString *filename,
+ const wxString& filespec,
+ int flags) const
+{
+ wxCHECK_MSG( IsOpened(), false, _T("must wxDir::Open() first") );
+
+ m_data->Rewind();
+
+ m_data->SetFileSpec(filespec);
+ m_data->SetFlags(flags);
+
+ return GetNext(filename);
+}
+
+bool wxDir::GetNext(wxString *filename) const
+{
+ wxCHECK_MSG( IsOpened(), false, _T("must wxDir::Open() first") );
+
+ wxCHECK_MSG( filename, false, _T("bad pointer in wxDir::GetNext()") );
+
+ return m_data->Read(filename);
+}
diff --git a/src/osx/carbon/display.cpp b/src/osx/carbon/display.cpp
new file mode 100644
index 0000000000..d8159cb352
--- /dev/null
+++ b/src/osx/carbon/display.cpp
@@ -0,0 +1,255 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/display.cpp
+// Purpose: Mac implementation of wxDisplay class
+// Author: Ryan Norton & Brian Victor
+// Modified by: Royce Mitchell III, Vadim Zeitlin
+// Created: 06/21/02
+// RCS-ID: $Id$
+// Copyright: (c) wxWidgets team
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+
+#if wxUSE_DISPLAY
+
+#include "wx/display.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/dynarray.h"
+ #include "wx/log.h"
+ #include "wx/string.h"
+ #include "wx/gdicmn.h"
+#endif
+
+#include
+
+#include "wx/display_impl.h"
+
+// ----------------------------------------------------------------------------
+// display classes implementation
+// ----------------------------------------------------------------------------
+
+class wxDisplayImplMacOSX : public wxDisplayImpl
+{
+public:
+ wxDisplayImplMacOSX(unsigned n, CGDirectDisplayID id)
+ : wxDisplayImpl(n),
+ m_id(id)
+ {
+ }
+
+ virtual wxRect GetGeometry() const;
+ virtual wxRect GetClientArea() const;
+ virtual wxString GetName() const { return wxString(); }
+
+ virtual wxArrayVideoModes GetModes(const wxVideoMode& mode) const;
+ virtual wxVideoMode GetCurrentMode() const;
+ virtual bool ChangeMode(const wxVideoMode& mode);
+
+private:
+ CGDirectDisplayID m_id;
+
+ DECLARE_NO_COPY_CLASS(wxDisplayImplMacOSX)
+};
+
+class wxDisplayFactoryMacOSX : public wxDisplayFactory
+{
+public:
+ wxDisplayFactoryMacOSX() {}
+
+ virtual wxDisplayImpl *CreateDisplay(unsigned n);
+ virtual unsigned GetCount();
+ virtual int GetFromPoint(const wxPoint& pt);
+
+protected:
+ DECLARE_NO_COPY_CLASS(wxDisplayFactoryMacOSX)
+};
+
+// ============================================================================
+// wxDisplayFactoryMacOSX implementation
+// ============================================================================
+
+unsigned wxDisplayFactoryMacOSX::GetCount()
+{
+ CGDisplayCount count;
+#ifdef __WXDEBUG__
+ CGDisplayErr err =
+#endif
+ CGGetActiveDisplayList(0, NULL, &count);
+
+ wxASSERT(err == CGDisplayNoErr);
+
+ return count;
+}
+
+int wxDisplayFactoryMacOSX::GetFromPoint(const wxPoint& p)
+{
+ CGPoint thePoint = {(float)p.x, (float)p.y};
+ CGDirectDisplayID theID;
+ CGDisplayCount theCount;
+ CGDisplayErr err = CGGetDisplaysWithPoint(thePoint, 1, &theID, &theCount);
+ wxASSERT(err == CGDisplayNoErr);
+
+ int nWhich = wxNOT_FOUND;
+
+ if (theCount)
+ {
+ theCount = GetCount();
+ CGDirectDisplayID* theIDs = new CGDirectDisplayID[theCount];
+ err = CGGetActiveDisplayList(theCount, theIDs, &theCount);
+ wxASSERT(err == CGDisplayNoErr);
+
+ for (nWhich = 0; nWhich < (int) theCount; ++nWhich)
+ {
+ if (theIDs[nWhich] == theID)
+ break;
+ }
+
+ delete [] theIDs;
+
+ if (nWhich == (int) theCount)
+ {
+ wxFAIL_MSG(wxT("Failed to find display in display list"));
+ nWhich = wxNOT_FOUND;
+ }
+ }
+
+ return nWhich;
+}
+
+wxDisplayImpl *wxDisplayFactoryMacOSX::CreateDisplay(unsigned n)
+{
+ CGDisplayCount theCount = GetCount();
+ CGDirectDisplayID* theIDs = new CGDirectDisplayID[theCount];
+
+#ifdef __WXDEBUG__
+ CGDisplayErr err =
+#endif
+ CGGetActiveDisplayList(theCount, theIDs, &theCount);
+
+ wxASSERT( err == CGDisplayNoErr );
+ wxASSERT( n < theCount );
+
+ wxDisplayImplMacOSX *display = new wxDisplayImplMacOSX(n, theIDs[n]);
+
+ delete [] theIDs;
+
+ return display;
+}
+
+// ============================================================================
+// wxDisplayImplMacOSX implementation
+// ============================================================================
+
+wxRect wxDisplayImplMacOSX::GetGeometry() const
+{
+ CGRect theRect = CGDisplayBounds(m_id);
+ return wxRect( (int)theRect.origin.x,
+ (int)theRect.origin.y,
+ (int)theRect.size.width,
+ (int)theRect.size.height ); //floats
+}
+
+wxRect wxDisplayImplMacOSX::GetClientArea() const
+{
+ // VZ: I don't know how to get client area for arbitrary display but
+ // wxGetClientDisplayRect() does work correctly for at least the main
+ // one (TODO: do it correctly for the other displays too)
+ if ( IsPrimary() )
+ return wxGetClientDisplayRect();
+
+ return wxDisplayImpl::GetClientArea();
+}
+
+static int wxCFDictKeyToInt( CFDictionaryRef desc, CFStringRef key )
+{
+ CFNumberRef value = (CFNumberRef) CFDictionaryGetValue( desc, key );
+ if (value == NULL)
+ return 0;
+
+ int num = 0;
+ CFNumberGetValue( value, kCFNumberIntType, &num );
+
+ return num;
+}
+
+wxArrayVideoModes wxDisplayImplMacOSX::GetModes(const wxVideoMode& mode) const
+{
+ wxArrayVideoModes resultModes;
+
+ CFArrayRef theArray = CGDisplayAvailableModes( m_id );
+
+ for (CFIndex i = 0; i < CFArrayGetCount(theArray); ++i)
+ {
+ CFDictionaryRef theValue = (CFDictionaryRef) CFArrayGetValueAtIndex( theArray, i );
+
+ wxVideoMode theMode(
+ wxCFDictKeyToInt( theValue, kCGDisplayWidth ),
+ wxCFDictKeyToInt( theValue, kCGDisplayHeight ),
+ wxCFDictKeyToInt( theValue, kCGDisplayBitsPerPixel ),
+ wxCFDictKeyToInt( theValue, kCGDisplayRefreshRate ));
+
+ if (theMode.Matches( mode ))
+ resultModes.Add( theMode );
+ }
+
+ return resultModes;
+}
+
+wxVideoMode wxDisplayImplMacOSX::GetCurrentMode() const
+{
+ CFDictionaryRef theValue = CGDisplayCurrentMode( m_id );
+
+ return wxVideoMode(
+ wxCFDictKeyToInt( theValue, kCGDisplayWidth ),
+ wxCFDictKeyToInt( theValue, kCGDisplayHeight ),
+ wxCFDictKeyToInt( theValue, kCGDisplayBitsPerPixel ),
+ wxCFDictKeyToInt( theValue, kCGDisplayRefreshRate ));
+}
+
+bool wxDisplayImplMacOSX::ChangeMode( const wxVideoMode& mode )
+{
+ // Changing to default mode (wxDefaultVideoMode) doesn't
+ // work because we don't have access to the system's 'scrn'
+ // resource which holds the user's mode which the system
+ // will return to after this app is done
+ boolean_t bExactMatch;
+ CFDictionaryRef theCGMode = CGDisplayBestModeForParametersAndRefreshRate(
+ m_id,
+ (size_t)mode.GetDepth(),
+ (size_t)mode.GetWidth(),
+ (size_t)mode.GetHeight(),
+ (double)mode.GetRefresh(),
+ &bExactMatch );
+
+ bool bOK = bExactMatch;
+
+ if (bOK)
+ bOK = CGDisplaySwitchToMode( m_id, theCGMode ) == CGDisplayNoErr;
+
+ return bOK;
+}
+
+// ============================================================================
+// wxDisplay::CreateFactory()
+// ============================================================================
+
+/* static */ wxDisplayFactory *wxDisplay::CreateFactory()
+{
+ return new wxDisplayFactoryMacOSX;
+}
+
+#endif // wxUSE_DISPLAY
diff --git a/src/osx/carbon/dnd.cpp b/src/osx/carbon/dnd.cpp
new file mode 100644
index 0000000000..11709e12ce
--- /dev/null
+++ b/src/osx/carbon/dnd.cpp
@@ -0,0 +1,562 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/dnd.cpp
+// Purpose: wxDropTarget, wxDropSource implementations
+// Author: Stefan Csomor
+// Modified by:
+// Created: 1998-01-01
+// RCS-ID: $Id$
+// Copyright: (c) 1998 Stefan Csomor
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+#include "wx/wxprec.h"
+
+#if wxUSE_DRAG_AND_DROP
+
+#include "wx/dnd.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/app.h"
+ #include "wx/toplevel.h"
+ #include "wx/gdicmn.h"
+#endif // WX_PRECOMP
+
+#include "wx/mac/private.h"
+
+// ----------------------------------------------------------------------------
+// globals
+// ----------------------------------------------------------------------------
+
+typedef struct
+{
+ wxWindow *m_currentTargetWindow;
+ wxDropTarget *m_currentTarget;
+ wxDropSource *m_currentSource;
+ wxDragResult m_result;
+ int m_flags;
+} MacTrackingGlobals;
+
+MacTrackingGlobals gTrackingGlobals;
+
+void wxMacEnsureTrackingHandlersInstalled();
+
+//----------------------------------------------------------------------------
+// wxDropTarget
+//----------------------------------------------------------------------------
+
+wxDropTarget::wxDropTarget( wxDataObject *data )
+ : wxDropTargetBase( data )
+{
+ wxMacEnsureTrackingHandlersInstalled();
+}
+
+wxDragResult wxDropTarget::OnDragOver(
+ wxCoord WXUNUSED(x), wxCoord WXUNUSED(y),
+ wxDragResult def )
+{
+ return CurrentDragHasSupportedFormat() ? def : wxDragNone;
+}
+
+bool wxDropTarget::OnDrop( wxCoord WXUNUSED(x), wxCoord WXUNUSED(y) )
+{
+ if (m_dataObject == NULL)
+ return false;
+
+ return CurrentDragHasSupportedFormat();
+}
+
+wxDragResult wxDropTarget::OnData(
+ wxCoord WXUNUSED(x), wxCoord WXUNUSED(y),
+ wxDragResult def )
+{
+ if (m_dataObject == NULL)
+ return wxDragNone;
+
+ if (!CurrentDragHasSupportedFormat())
+ return wxDragNone;
+
+ return GetData() ? def : wxDragNone;
+}
+
+bool wxDropTarget::CurrentDragHasSupportedFormat()
+{
+ bool supported = false;
+ if (m_dataObject == NULL)
+ return false;
+
+ if ( gTrackingGlobals.m_currentSource != NULL )
+ {
+ wxDataObject* data = gTrackingGlobals.m_currentSource->GetDataObject();
+
+ if ( data )
+ {
+ size_t formatcount = data->GetFormatCount();
+ wxDataFormat *array = new wxDataFormat[formatcount];
+ data->GetAllFormats( array );
+ for (size_t i = 0; !supported && i < formatcount; i++)
+ {
+ wxDataFormat format = array[i];
+ if ( m_dataObject->IsSupported( format ) )
+ {
+ supported = true;
+ break;
+ }
+ }
+
+ delete [] array;
+ }
+ }
+
+ if ( !supported )
+ {
+ PasteboardRef pasteboard;
+
+ if ( GetDragPasteboard( (DragReference)m_currentDrag, &pasteboard ) == noErr )
+ {
+ supported = m_dataObject->HasDataInPasteboard( pasteboard );
+ }
+ }
+
+ return supported;
+}
+
+bool wxDropTarget::GetData()
+{
+ if (m_dataObject == NULL)
+ return false;
+
+ if ( !CurrentDragHasSupportedFormat() )
+ return false;
+
+ bool transferred = false;
+ if ( gTrackingGlobals.m_currentSource != NULL )
+ {
+ wxDataObject* data = gTrackingGlobals.m_currentSource->GetDataObject();
+
+ if (data != NULL)
+ {
+ size_t formatcount = data->GetFormatCount();
+ wxDataFormat *array = new wxDataFormat[formatcount];
+ data->GetAllFormats( array );
+ for (size_t i = 0; !transferred && i < formatcount; i++)
+ {
+ wxDataFormat format = array[i];
+ if ( m_dataObject->IsSupported( format ) )
+ {
+ int size = data->GetDataSize( format );
+ transferred = true;
+
+ if (size == 0)
+ {
+ m_dataObject->SetData( format, 0, 0 );
+ }
+ else
+ {
+ char *d = new char[size];
+ data->GetDataHere( format, (void*)d );
+ m_dataObject->SetData( format, size, d );
+ delete [] d;
+ }
+ }
+ }
+
+ delete [] array;
+ }
+ }
+
+ if ( !transferred )
+ {
+ PasteboardRef pasteboard;
+
+ if ( GetDragPasteboard( (DragReference)m_currentDrag, &pasteboard ) == noErr )
+ {
+ transferred = m_dataObject->GetFromPasteboard( pasteboard );
+ }
+ }
+
+ return transferred;
+}
+
+//-------------------------------------------------------------------------
+// wxDropSource
+//-------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// drag request
+
+wxDropSource::wxDropSource(wxWindow *win,
+ const wxCursor &cursorCopy,
+ const wxCursor &cursorMove,
+ const wxCursor &cursorStop)
+ : wxDropSourceBase(cursorCopy, cursorMove, cursorStop)
+{
+ wxMacEnsureTrackingHandlersInstalled();
+
+ m_window = win;
+}
+
+wxDropSource::wxDropSource(wxDataObject& data,
+ wxWindow *win,
+ const wxCursor &cursorCopy,
+ const wxCursor &cursorMove,
+ const wxCursor &cursorStop)
+ : wxDropSourceBase(cursorCopy, cursorMove, cursorStop)
+{
+ wxMacEnsureTrackingHandlersInstalled();
+
+ SetData( data );
+ m_window = win;
+}
+
+wxDropSource::~wxDropSource()
+{
+}
+
+OSStatus wxMacPromiseKeeper(PasteboardRef WXUNUSED(inPasteboard),
+ PasteboardItemID WXUNUSED(inItem),
+ CFStringRef WXUNUSED(inFlavorType),
+ void * WXUNUSED(inContext))
+{
+ OSStatus err = noErr;
+
+ // we might add promises here later, inContext is the wxDropSource*
+
+ return err;
+}
+
+wxDragResult wxDropSource::DoDragDrop(int flags)
+{
+ wxASSERT_MSG( m_data, wxT("Drop source: no data") );
+
+ if ((m_data == NULL) || (m_data->GetFormatCount() == 0))
+ return (wxDragResult)wxDragNone;
+
+ DragReference theDrag;
+ RgnHandle dragRegion;
+ OSStatus err = noErr;
+ PasteboardRef pasteboard;
+
+ // add data to drag
+
+ err = PasteboardCreate( kPasteboardUniqueName, &pasteboard );
+ if ( err != noErr )
+ return wxDragNone;
+
+ // we add a dummy promise keeper because of strange messages when linking against carbon debug
+ err = PasteboardSetPromiseKeeper( pasteboard, wxMacPromiseKeeper, this );
+ if ( err != noErr )
+ {
+ CFRelease( pasteboard );
+ return wxDragNone;
+ }
+
+ err = PasteboardClear( pasteboard );
+ if ( err != noErr )
+ {
+ CFRelease( pasteboard );
+ return wxDragNone;
+ }
+ PasteboardSynchronize( pasteboard );
+
+ m_data->AddToPasteboard( pasteboard, 1 );
+
+ if (NewDragWithPasteboard( pasteboard , &theDrag) != noErr)
+ {
+ CFRelease( pasteboard );
+ return wxDragNone;
+ }
+
+ dragRegion = NewRgn();
+ RgnHandle tempRgn = NewRgn();
+
+ EventRecord rec;
+ ConvertEventRefToEventRecord( (EventRef) wxTheApp->MacGetCurrentEvent(), &rec );
+
+ const short dragRegionOuterBoundary = 10;
+ const short dragRegionInnerBoundary = 9;
+
+ SetRectRgn(
+ dragRegion,
+ rec.where.h - dragRegionOuterBoundary,
+ rec.where.v - dragRegionOuterBoundary,
+ rec.where.h + dragRegionOuterBoundary,
+ rec.where.v + dragRegionOuterBoundary );
+
+ SetRectRgn(
+ tempRgn,
+ rec.where.h - dragRegionInnerBoundary,
+ rec.where.v - dragRegionInnerBoundary,
+ rec.where.h + dragRegionInnerBoundary,
+ rec.where.v + dragRegionInnerBoundary );
+
+ DiffRgn( dragRegion, tempRgn, dragRegion );
+ DisposeRgn( tempRgn );
+
+ // TODO: work with promises in order to return data
+ // only when drag was successfully completed
+
+ gTrackingGlobals.m_currentSource = this;
+ gTrackingGlobals.m_result = wxDragNone;
+ gTrackingGlobals.m_flags = flags;
+
+ err = TrackDrag( theDrag, &rec, dragRegion );
+
+ DisposeRgn( dragRegion );
+ DisposeDrag( theDrag );
+ CFRelease( pasteboard );
+ gTrackingGlobals.m_currentSource = NULL;
+
+ return gTrackingGlobals.m_result;
+}
+
+bool wxDropSource::MacInstallDefaultCursor(wxDragResult effect)
+{
+ const wxCursor& cursor = GetCursor(effect);
+ bool result = cursor.Ok();
+
+ if ( result )
+ cursor.MacInstall();
+
+ return result;
+}
+
+bool gTrackingGlobalsInstalled = false;
+
+// passing the globals via refcon is not needed by the CFM and later architectures anymore
+// but I'll leave it in there, just in case...
+
+pascal OSErr wxMacWindowDragTrackingHandler(
+ DragTrackingMessage theMessage, WindowPtr theWindow,
+ void *handlerRefCon, DragReference theDrag );
+pascal OSErr wxMacWindowDragReceiveHandler(
+ WindowPtr theWindow, void *handlerRefCon,
+ DragReference theDrag );
+
+void wxMacEnsureTrackingHandlersInstalled()
+{
+ if ( !gTrackingGlobalsInstalled )
+ {
+ OSStatus err;
+
+ err = InstallTrackingHandler( NewDragTrackingHandlerUPP(wxMacWindowDragTrackingHandler), 0L, &gTrackingGlobals );
+ verify_noerr( err );
+
+ err = InstallReceiveHandler( NewDragReceiveHandlerUPP(wxMacWindowDragReceiveHandler), 0L, &gTrackingGlobals );
+ verify_noerr( err );
+
+ gTrackingGlobalsInstalled = true;
+ }
+}
+
+pascal OSErr wxMacWindowDragTrackingHandler(
+ DragTrackingMessage theMessage, WindowPtr theWindow,
+ void *handlerRefCon, DragReference theDrag )
+{
+ MacTrackingGlobals* trackingGlobals = (MacTrackingGlobals*) handlerRefCon;
+
+ Point mouse, localMouse;
+ DragAttributes attributes;
+
+ GetDragAttributes( theDrag, &attributes );
+
+ wxNonOwnedWindow* toplevel = wxFindWinFromMacWindow( theWindow );
+
+ bool optionDown = GetCurrentKeyModifiers() & optionKey;
+ wxDragResult result = optionDown ? wxDragCopy : wxDragMove;
+
+ switch (theMessage)
+ {
+ case kDragTrackingEnterHandler:
+ case kDragTrackingLeaveHandler:
+ break;
+
+ case kDragTrackingEnterWindow:
+ if (trackingGlobals != NULL)
+ {
+ trackingGlobals->m_currentTargetWindow = NULL;
+ trackingGlobals->m_currentTarget = NULL;
+ }
+ break;
+
+ case kDragTrackingInWindow:
+ if (trackingGlobals == NULL)
+ break;
+ if (toplevel == NULL)
+ break;
+
+ GetDragMouse( theDrag, &mouse, 0L );
+ localMouse = mouse;
+ wxMacGlobalToLocal( theWindow, &localMouse );
+
+ {
+ wxWindow *win = NULL;
+ ControlPartCode controlPart;
+ ControlRef control = FindControlUnderMouse( localMouse, theWindow, &controlPart );
+ if ( control )
+ win = wxFindControlFromMacControl( control );
+ else
+ win = toplevel;
+
+ int localx, localy;
+ localx = localMouse.h;
+ localy = localMouse.v;
+
+ if ( win )
+ win->MacRootWindowToWindow( &localx, &localy );
+ if ( win != trackingGlobals->m_currentTargetWindow )
+ {
+ if ( trackingGlobals->m_currentTargetWindow )
+ {
+ // this window is left
+ if ( trackingGlobals->m_currentTarget )
+ {
+#ifndef __LP64__
+ HideDragHilite( theDrag );
+#endif
+ trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag );
+ trackingGlobals->m_currentTarget->OnLeave();
+ trackingGlobals->m_currentTarget = NULL;
+ trackingGlobals->m_currentTargetWindow = NULL;
+ }
+ }
+
+ if ( win )
+ {
+ // this window is entered
+ trackingGlobals->m_currentTargetWindow = win;
+ trackingGlobals->m_currentTarget = win->GetDropTarget();
+ {
+ if ( trackingGlobals->m_currentTarget )
+ {
+ trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag );
+ result = trackingGlobals->m_currentTarget->OnEnter( localx, localy, result );
+ }
+
+ if ( result != wxDragNone )
+ {
+ int x, y;
+
+ x = y = 0;
+ win->MacWindowToRootWindow( &x, &y );
+ RgnHandle hiliteRgn = NewRgn();
+ Rect r = { y, x, y + win->GetSize().y, x + win->GetSize().x };
+ RectRgn( hiliteRgn, &r );
+#ifndef __LP64__
+ ShowDragHilite( theDrag, hiliteRgn, true );
+#endif
+ DisposeRgn( hiliteRgn );
+ }
+ }
+ }
+ }
+ else
+ {
+ if ( trackingGlobals->m_currentTarget )
+ {
+ trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag );
+ result = trackingGlobals->m_currentTarget->OnDragOver( localx, localy, result );
+ }
+ }
+
+ // set cursor for OnEnter and OnDragOver
+ if ( trackingGlobals->m_currentSource && !trackingGlobals->m_currentSource->GiveFeedback( result ) )
+ {
+ if ( !trackingGlobals->m_currentSource->MacInstallDefaultCursor( result ) )
+ {
+ int cursorID = wxCURSOR_NONE;
+
+ switch (result)
+ {
+ case wxDragCopy:
+ cursorID = wxCURSOR_COPY_ARROW;
+ break;
+
+ case wxDragMove:
+ cursorID = wxCURSOR_ARROW;
+ break;
+
+ case wxDragNone:
+ cursorID = wxCURSOR_NO_ENTRY;
+ break;
+
+ case wxDragError:
+ case wxDragLink:
+ case wxDragCancel:
+ default:
+ // put these here to make gcc happy
+ ;
+ }
+
+ if (cursorID != wxCURSOR_NONE)
+ {
+ wxCursor cursor( cursorID );
+ cursor.MacInstall();
+ }
+ }
+ }
+ }
+ break;
+
+ case kDragTrackingLeaveWindow:
+ if (trackingGlobals == NULL)
+ break;
+
+ if (trackingGlobals->m_currentTarget)
+ {
+ trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag );
+ trackingGlobals->m_currentTarget->OnLeave();
+#ifndef __LP64__
+ HideDragHilite( theDrag );
+#endif
+ trackingGlobals->m_currentTarget = NULL;
+ }
+ trackingGlobals->m_currentTargetWindow = NULL;
+ break;
+
+ default:
+ break;
+ }
+
+ return noErr;
+}
+
+pascal OSErr wxMacWindowDragReceiveHandler(
+ WindowPtr theWindow,
+ void *handlerRefCon,
+ DragReference theDrag)
+{
+ MacTrackingGlobals* trackingGlobals = (MacTrackingGlobals*)handlerRefCon;
+ if ( trackingGlobals->m_currentTarget )
+ {
+ Point mouse, localMouse;
+ int localx, localy;
+
+ trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag );
+ GetDragMouse( theDrag, &mouse, 0L );
+ localMouse = mouse;
+ wxMacGlobalToLocal( theWindow, &localMouse );
+ localx = localMouse.h;
+ localy = localMouse.v;
+
+ // TODO : should we use client coordinates?
+ if ( trackingGlobals->m_currentTargetWindow )
+ trackingGlobals->m_currentTargetWindow->MacRootWindowToWindow( &localx, &localy );
+ if ( trackingGlobals->m_currentTarget->OnDrop( localx, localy ) )
+ {
+ // the option key indicates copy in Mac UI, if it's not pressed do
+ // move by default if it's allowed at all
+ wxDragResult
+ result = !(trackingGlobals->m_flags & wxDrag_AllowMove) ||
+ (GetCurrentKeyModifiers() & optionKey)
+ ? wxDragCopy
+ : wxDragMove;
+ trackingGlobals->m_result =
+ trackingGlobals->m_currentTarget->OnData( localx, localy, result );
+ }
+ }
+
+ return noErr;
+}
+
+#endif // wxUSE_DRAG_AND_DROP
+
diff --git a/src/osx/carbon/drawer.cpp b/src/osx/carbon/drawer.cpp
new file mode 100644
index 0000000000..4adb28e239
--- /dev/null
+++ b/src/osx/carbon/drawer.cpp
@@ -0,0 +1,199 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: drawer.cpp
+// Purpose: Drawer child window classes.
+// Drawer windows appear under their parent window and
+// behave like a drawer, opening and closing to reveal
+// content that does not need to be visible at all times.
+// Author: Jason Bagley
+// Modified by: Ryan Norton (To make it work :), plus bug fixes)
+// Created: 2004-30-01
+// RCS-ID: $Id$
+// Copyright: (c) Jason Bagley; Art & Logic, Inc.
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/wxprec.h"
+
+#include "wx/mac/private.h"
+
+#if defined( __WXMAC__ )
+
+#include "wx/mac/carbon/drawer.h"
+
+IMPLEMENT_DYNAMIC_CLASS(wxDrawerWindow, wxWindow)
+
+// Use constants for now.
+// These can be made into member variables and set dynamically.
+const int kLeadingOffset = 20;
+const int kTrailingOffset = 20;
+
+
+// Converts Mac window edge constants to wxDirections, wxLEFT, wxRIGHT, etc.
+static wxDirection WindowEdgeToDirection(OptionBits edge);
+
+// Convert wxDirections to MAc window edge constants.
+static OptionBits DirectionToWindowEdge(wxDirection direction);
+
+
+wxDrawerWindow::wxDrawerWindow()
+{
+}
+
+wxDrawerWindow::~wxDrawerWindow()
+{
+ m_isBeingDeleted = TRUE;
+ this->Show(FALSE);
+}
+
+bool wxDrawerWindow::Create(wxWindow *parent,
+ wxWindowID id, const wxString& title,
+ wxSize size, wxDirection edge, const wxString& name)
+{
+ wxASSERT_MSG(NULL != parent, wxT("wxDrawerWindows must be attached to a parent window."));
+
+ // Constrain the drawer size to the parent window.
+ const wxSize parentSize(parent->GetClientSize());
+ if (wxLEFT == edge || wxRIGHT == edge)
+ {
+ if (size.GetHeight() > parentSize.GetHeight())
+ size.SetHeight(parentSize.GetHeight() - (kLeadingOffset + kTrailingOffset));
+ }
+ else
+ {
+ if (size.GetWidth() > parentSize.GetWidth())
+ size.SetWidth(parentSize.GetWidth() - (kLeadingOffset + kTrailingOffset));
+ }
+
+ // Create the drawer window.
+ const wxPoint pos(0, 0);
+ const wxSize dummySize(0,0);
+ const long style = wxFRAME_DRAWER;
+
+ bool success = wxWindow::Create(parent, id, pos, dummySize, style, name);
+ if (success)
+ {
+ this->MacCreateRealWindow(pos, size, style, name);
+ success = (m_macWindow != NULL);
+ }
+
+ if (success)
+ {
+ // Use drawer brush.
+ SetBackgroundColour( wxColour( wxMacCreateCGColorFromHITheme( kThemeBrushDrawerBackground ) ) );
+ ::SetThemeWindowBackground((WindowRef)m_macWindow, kThemeBrushDrawerBackground, false);
+
+ // Leading and trailing offset are gaps from parent window edges
+ // to where the drawer starts.
+ ::SetDrawerOffsets((WindowRef)m_macWindow, kLeadingOffset, kTrailingOffset);
+
+ // Set the drawers parent.
+ // Is there a better way to get the parent's WindowRef?
+ wxTopLevelWindow* tlwParent = wxDynamicCast(parent, wxTopLevelWindow);
+ if (NULL != tlwParent)
+ {
+ OSStatus status = ::SetDrawerParent((WindowRef)m_macWindow,
+ (WindowRef)tlwParent->MacGetWindowRef());
+ success = (noErr == status);
+ }
+ else
+ success = false;
+ }
+
+ return success && SetPreferredEdge(edge);
+}
+
+wxDirection wxDrawerWindow::GetCurrentEdge() const
+{
+ const OptionBits edge = ::GetDrawerCurrentEdge((WindowRef)m_macWindow);
+ return WindowEdgeToDirection(edge);
+}
+
+wxDirection wxDrawerWindow::GetPreferredEdge() const
+{
+ const OptionBits edge = ::GetDrawerPreferredEdge((WindowRef)m_macWindow);
+ return WindowEdgeToDirection(edge);
+}
+
+bool wxDrawerWindow::IsOpen() const
+{
+ WindowDrawerState state = ::GetDrawerState((WindowRef)m_macWindow);
+ return (state == kWindowDrawerOpen || state == kWindowDrawerOpening);
+}
+
+bool wxDrawerWindow::Open(bool show)
+{
+ static const Boolean kAsynchronous = true;
+ OSStatus status = noErr;
+
+ if (show)
+ {
+ const OptionBits preferredEdge = ::GetDrawerPreferredEdge((WindowRef)m_macWindow);
+ status = ::OpenDrawer((WindowRef)m_macWindow, preferredEdge, kAsynchronous);
+ }
+ else
+ status = ::CloseDrawer((WindowRef)m_macWindow, kAsynchronous);
+
+ return (noErr == status);
+}
+
+bool wxDrawerWindow::SetPreferredEdge(wxDirection edge)
+{
+ const OSStatus status = ::SetDrawerPreferredEdge((WindowRef)m_macWindow,
+ DirectionToWindowEdge(edge));
+ return (noErr == status);
+}
+
+
+OptionBits DirectionToWindowEdge(wxDirection direction)
+{
+ OptionBits edge;
+ switch (direction)
+ {
+ case wxTOP:
+ edge = kWindowEdgeTop;
+ break;
+
+ case wxBOTTOM:
+ edge = kWindowEdgeBottom;
+ break;
+
+ case wxRIGHT:
+ edge = kWindowEdgeRight;
+ break;
+
+ case wxLEFT:
+ default:
+ edge = kWindowEdgeLeft;
+ break;
+ }
+ return edge;
+}
+
+wxDirection WindowEdgeToDirection(OptionBits edge)
+{
+ wxDirection direction;
+ switch (edge)
+ {
+ case kWindowEdgeTop:
+ direction = wxTOP;
+ break;
+
+ case kWindowEdgeBottom:
+ direction = wxBOTTOM;
+ break;
+
+ case kWindowEdgeRight:
+ direction = wxRIGHT;
+ break;
+
+ case kWindowEdgeDefault: // store current preferred and return that here?
+ case kWindowEdgeLeft:
+ default:
+ direction = wxLEFT;
+ break;
+ }
+
+ return direction;
+}
+
+#endif // defined( __WXMAC__ )
diff --git a/src/osx/carbon/dummy.txt b/src/osx/carbon/dummy.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/src/osx/carbon/evtloop.cpp b/src/osx/carbon/evtloop.cpp
new file mode 100644
index 0000000000..681564bffa
--- /dev/null
+++ b/src/osx/carbon/evtloop.cpp
@@ -0,0 +1,109 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/evtloop.cpp
+// Purpose: implementation of wxEventLoop for wxMac
+// Author: Vadim Zeitlin
+// Modified by:
+// Created: 2006-01-12
+// RCS-ID: $Id$
+// Copyright: (c) 2006 Vadim Zeitlin
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+// for compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+
+#include "wx/evtloop.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/app.h"
+#endif // WX_PRECOMP
+
+#ifdef __DARWIN__
+ #include
+#else
+ #include
+#endif
+// ============================================================================
+// wxEventLoop implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// high level functions for RunApplicationEventLoop() case
+// ----------------------------------------------------------------------------
+
+#if wxMAC_USE_RUN_APP_EVENT_LOOP
+
+int wxGUIEventLoop::Run()
+{
+ wxEventLoopActivator activate(this);
+
+ RunApplicationEventLoop();
+
+ return m_exitcode;
+}
+
+void wxGUIEventLoop::Exit(int rc)
+{
+ m_exitcode = rc;
+
+ QuitApplicationEventLoop();
+
+ OnExit();
+}
+
+#else // manual event loop
+
+// ----------------------------------------------------------------------------
+// functions only used by wxEventLoopManual-based implementation
+// ----------------------------------------------------------------------------
+
+void wxGUIEventLoop::WakeUp()
+{
+ extern void wxMacWakeUp();
+
+ wxMacWakeUp();
+}
+
+#endif // high/low-level event loop
+
+// ----------------------------------------------------------------------------
+// low level functions used in both cases
+// ----------------------------------------------------------------------------
+
+bool wxGUIEventLoop::Pending() const
+{
+ EventRef theEvent;
+
+ return ReceiveNextEvent
+ (
+ 0, // we want any event at all so we don't specify neither
+ NULL, // the number of event types nor the types themselves
+ kEventDurationNoWait,
+ false, // don't remove the event from queue
+ &theEvent
+ ) == noErr;
+}
+
+bool wxGUIEventLoop::Dispatch()
+{
+ // TODO: we probably should do the dispatching directly from here but for
+ // now it's easier to forward to wxApp which has all the code to do
+ // it
+ if ( !wxTheApp )
+ return false;
+
+ wxTheApp->MacDoOneEvent();
+ return true;
+}
diff --git a/src/osx/carbon/filedlg.cpp b/src/osx/carbon/filedlg.cpp
new file mode 100644
index 0000000000..6e43845335
--- /dev/null
+++ b/src/osx/carbon/filedlg.cpp
@@ -0,0 +1,436 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/filedlg.cpp
+// Purpose: wxFileDialog
+// Author: Stefan Csomor
+// Modified by:
+// Created: 1998-01-01
+// RCS-ID: $Id$
+// Copyright: (c) Stefan Csomor
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/wxprec.h"
+
+#if wxUSE_FILEDLG
+
+#include "wx/filedlg.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/intl.h"
+ #include "wx/app.h"
+ #include "wx/utils.h"
+ #include "wx/dialog.h"
+#endif
+
+#include "wx/tokenzr.h"
+#include "wx/filename.h"
+
+#include "wx/mac/private.h"
+
+#ifndef __DARWIN__
+ #include
+ #include "PLStringFuncs.h"
+#endif
+
+IMPLEMENT_CLASS(wxFileDialog, wxFileDialogBase)
+
+// the data we need to pass to our standard file hook routine
+// includes a pointer to the dialog, a pointer to the standard
+// file reply record (so we can inspect the current selection)
+// and a copy of the "previous" file spec of the reply record
+// so we can see if the selection has changed
+
+struct OpenUserDataRec
+{
+ int currentfilter ;
+ bool saveMode ;
+ wxArrayString name ;
+ wxArrayString extensions ;
+ wxArrayLong filtermactypes ;
+ wxString defaultLocation;
+ CFArrayRef menuitems ;
+};
+
+typedef struct OpenUserDataRec
+OpenUserDataRec, *OpenUserDataRecPtr;
+
+static pascal void NavEventProc(
+ NavEventCallbackMessage inSelector,
+ NavCBRecPtr ioParams,
+ NavCallBackUserData ioUserData );
+
+static NavEventUPP sStandardNavEventFilter = NewNavEventUPP(NavEventProc);
+
+static pascal void NavEventProc(
+ NavEventCallbackMessage inSelector,
+ NavCBRecPtr ioParams,
+ NavCallBackUserData ioUserData )
+{
+ OpenUserDataRec * data = ( OpenUserDataRec *) ioUserData ;
+ if (inSelector == kNavCBEvent)
+ {
+ }
+ else if ( inSelector == kNavCBStart )
+ {
+ if (data && !(data->defaultLocation).empty())
+ {
+ // Set default location for the modern Navigation APIs
+ // Apple Technical Q&A 1151
+ FSRef theFile;
+ wxMacPathToFSRef(data->defaultLocation, &theFile);
+ AEDesc theLocation = { typeNull, NULL };
+ if (noErr == ::AECreateDesc(typeFSRef, &theFile, sizeof(FSRef), &theLocation))
+ ::NavCustomControl(ioParams->context, kNavCtlSetLocation, (void *) &theLocation);
+ }
+
+ if( data->extensions.GetCount() > 0 )
+ {
+ NavMenuItemSpec menuItem;
+ memset( &menuItem, 0, sizeof(menuItem) );
+ menuItem.version = kNavMenuItemSpecVersion;
+ menuItem.menuType = data->currentfilter;
+ ::NavCustomControl(ioParams->context, kNavCtlSelectCustomType, &menuItem);
+ }
+ }
+ else if ( inSelector == kNavCBPopupMenuSelect )
+ {
+ NavMenuItemSpec * menu = (NavMenuItemSpec *) ioParams->eventData.eventDataParms.param ;
+ const size_t numFilters = data->extensions.GetCount();
+
+ if ( menu->menuType < numFilters )
+ {
+ data->currentfilter = menu->menuType ;
+ if ( data->saveMode )
+ {
+ int i = menu->menuType ;
+
+ // isolate the first extension string
+ wxString firstExtension = data->extensions[i].BeforeFirst('|').BeforeFirst(';');
+
+ wxString extension = firstExtension.AfterLast('.') ;
+ wxString sfilename ;
+
+ wxCFStringRef cfString( wxCFRetain( NavDialogGetSaveFileName( ioParams->context ) ) );
+ sfilename = cfString.AsString() ;
+
+ int pos = sfilename.Find('.', true) ;
+ if ( pos != wxNOT_FOUND && extension != wxT("*") )
+ {
+ sfilename = sfilename.Left(pos+1)+extension ;
+ cfString = wxCFStringRef( sfilename , wxFONTENCODING_DEFAULT ) ;
+ NavDialogSetSaveFileName( ioParams->context , cfString ) ;
+ }
+ }
+ }
+ }
+}
+
+void MakeUserDataRec(OpenUserDataRec *myData , const wxString& filter )
+{
+ myData->menuitems = NULL ;
+ myData->currentfilter = 0 ;
+ myData->saveMode = false ;
+
+ if ( !filter.empty() )
+ {
+ wxString filter2(filter) ;
+ int filterIndex = 0;
+ bool isName = true ;
+ wxString current ;
+
+ for ( unsigned int i = 0; i < filter2.length() ; i++ )
+ {
+ if ( filter2.GetChar(i) == wxT('|') )
+ {
+ if ( isName )
+ {
+ myData->name.Add( current ) ;
+ }
+ else
+ {
+ myData->extensions.Add( current ) ;
+ ++filterIndex ;
+ }
+
+ isName = !isName ;
+ current = wxEmptyString ;
+ }
+ else
+ {
+ current += filter2.GetChar(i) ;
+ }
+ }
+ // we allow for compatibility reason to have a single filter expression (like *.*) without
+ // an explanatory text, in that case the first part is name and extension at the same time
+
+ wxASSERT_MSG( filterIndex == 0 || !isName , wxT("incorrect format of format string") ) ;
+ if ( current.empty() )
+ myData->extensions.Add( myData->name[filterIndex] ) ;
+ else
+ myData->extensions.Add( current ) ;
+ if ( filterIndex == 0 || isName )
+ myData->name.Add( current ) ;
+
+ ++filterIndex ;
+
+ const size_t extCount = myData->extensions.GetCount();
+ for ( size_t i = 0 ; i < extCount; i++ )
+ {
+ wxUint32 fileType, creator;
+ wxString extension = myData->extensions[i];
+
+ // Remove leading '*'
+ if (extension.length() && (extension.GetChar(0) == '*'))
+ extension = extension.Mid( 1 );
+
+ // Remove leading '.'
+ if (extension.length() && (extension.GetChar(0) == '.'))
+ extension = extension.Mid( 1 );
+
+ if (wxFileName::MacFindDefaultTypeAndCreator( extension, &fileType, &creator ))
+ myData->filtermactypes.Add( (OSType)fileType );
+ else
+ myData->filtermactypes.Add( '****' ); // We'll fail safe if it's not recognized
+ }
+ }
+}
+
+static Boolean CheckFile( const wxString &filename , OSType type , OpenUserDataRecPtr data)
+{
+ wxString file(filename) ;
+ file.MakeUpper() ;
+
+ if ( data->extensions.GetCount() > 0 )
+ {
+ //for ( int i = 0 ; i < data->numfilters ; ++i )
+ int i = data->currentfilter ;
+ if ( data->extensions[i].Right(2) == wxT(".*") )
+ return true ;
+
+ {
+ if ( type == (OSType)data->filtermactypes[i] )
+ return true ;
+
+ wxStringTokenizer tokenizer( data->extensions[i] , wxT(";") ) ;
+ while ( tokenizer.HasMoreTokens() )
+ {
+ wxString extension = tokenizer.GetNextToken() ;
+ if ( extension.GetChar(0) == '*' )
+ extension = extension.Mid(1) ;
+ extension.MakeUpper();
+
+ if ( file.length() >= extension.length() && extension == file.Right(extension.length() ) )
+ return true ;
+ }
+ }
+
+ return false ;
+ }
+
+ return true ;
+}
+
+// end wxmac
+
+wxFileDialog::wxFileDialog(
+ wxWindow *parent, const wxString& message,
+ const wxString& defaultDir, const wxString& defaultFileName, const wxString& wildCard,
+ long style, const wxPoint& pos, const wxSize& sz, const wxString& name)
+ : wxFileDialogBase(parent, message, defaultDir, defaultFileName, wildCard, style, pos, sz, name)
+{
+ wxASSERT_MSG( NavServicesAvailable() , wxT("Navigation Services are not running") ) ;
+}
+
+pascal Boolean CrossPlatformFilterCallback(
+ AEDesc *theItem,
+ void *info,
+ void *callBackUD,
+ NavFilterModes filterMode )
+{
+ OpenUserDataRecPtr data = (OpenUserDataRecPtr) callBackUD ;
+
+ if (filterMode == kNavFilteringBrowserList)
+ {
+ // We allow navigation to all folders. For files, we check against the current
+ // filter string.
+ // However, packages should be dealt with like files and not like folders. So
+ // check if a folder is a package before deciding what to do.
+ NavFileOrFolderInfo* theInfo = (NavFileOrFolderInfo*) info ;
+ FSRef fsref;
+
+ if ( theInfo->isFolder )
+ {
+ // check bundle bit (using Finder Services - used by OS9 on some bundles)
+ FSCatalogInfo catalogInfo;
+ if (FSGetCatalogInfo (&fsref, kFSCatInfoFinderInfo, &catalogInfo, NULL, NULL, NULL) != noErr)
+ return true;
+
+ // Check bundle item (using Launch Services - used by OS-X through info.plist or APP)
+ LSItemInfoRecord lsInfo;
+ if (LSCopyItemInfoForRef(&fsref, kLSRequestBasicFlagsOnly, &lsInfo ) != noErr)
+ return true;
+
+ // If it's not a bundle, then it's a normal folder and it passes our filter
+ FileInfo *fileInfo = (FileInfo *) catalogInfo.finderInfo;
+ if ( !(fileInfo->finderFlags & kHasBundle) &&
+ !(lsInfo.flags & (kLSItemInfoIsApplication | kLSItemInfoIsPackage)) )
+ return true;
+ }
+ else
+ {
+ AECoerceDesc (theItem, typeFSRef, theItem);
+ if ( AEGetDescData (theItem, &fsref, sizeof (FSRef)) == noErr)
+ {
+ wxString file = wxMacFSRefToPath( &fsref ) ;
+ return CheckFile( file , theInfo->fileAndFolder.fileInfo.finderInfo.fdType , data ) ;
+ }
+ }
+ }
+
+ return true;
+}
+
+int wxFileDialog::ShowModal()
+{
+ OSErr err;
+ NavDialogCreationOptions dialogCreateOptions;
+
+ // set default options
+ ::NavGetDefaultDialogCreationOptions(&dialogCreateOptions);
+
+ // this was always unset in the old code
+ dialogCreateOptions.optionFlags &= ~kNavSelectDefaultLocation;
+
+ wxCFStringRef message(m_message, GetFont().GetEncoding());
+ dialogCreateOptions.windowTitle = message;
+
+ wxCFStringRef defaultFileName(m_fileName, GetFont().GetEncoding());
+ dialogCreateOptions.saveFileName = defaultFileName;
+
+
+ NavDialogRef dialog;
+ NavObjectFilterUPP navFilterUPP = NULL;
+ OpenUserDataRec myData;
+ myData.defaultLocation = m_dir;
+
+ MakeUserDataRec(&myData , m_wildCard);
+ myData.currentfilter = m_filterIndex;
+ size_t numFilters = myData.extensions.GetCount();
+ if (numFilters)
+ {
+ CFMutableArrayRef popup = CFArrayCreateMutable( kCFAllocatorDefault ,
+ numFilters , &kCFTypeArrayCallBacks ) ;
+ dialogCreateOptions.popupExtension = popup ;
+ myData.menuitems = dialogCreateOptions.popupExtension ;
+ for ( size_t i = 0 ; i < numFilters ; ++i )
+ {
+ CFArrayAppendValue( popup , (CFStringRef) wxCFStringRef( myData.name[i] , GetFont().GetEncoding() ) ) ;
+ }
+ }
+
+ if (HasFdFlag(wxFD_SAVE))
+ {
+ myData.saveMode = true;
+
+ dialogCreateOptions.optionFlags |= kNavDontAutoTranslate;
+ dialogCreateOptions.optionFlags |= kNavDontAddTranslateItems;
+ if (!numFilters)
+ dialogCreateOptions.optionFlags |= kNavNoTypePopup;
+
+ // The extension is important
+ if (numFilters < 2)
+ dialogCreateOptions.optionFlags |= kNavPreserveSaveFileExtension;
+
+ if (!(m_windowStyle & wxFD_OVERWRITE_PROMPT))
+ dialogCreateOptions.optionFlags |= kNavDontConfirmReplacement;
+
+ err = ::NavCreatePutFileDialog(
+ &dialogCreateOptions,
+ kNavGenericSignature, // Suppresses the 'Default' (top) menu item
+ kNavGenericSignature,
+ sStandardNavEventFilter,
+ &myData, // for defaultLocation
+ &dialog );
+ }
+ else
+ {
+ // let the user select bundles/programs in dialogs
+ dialogCreateOptions.optionFlags |= kNavSupportPackages;
+
+ navFilterUPP = NewNavObjectFilterUPP(CrossPlatformFilterCallback);
+ err = ::NavCreateGetFileDialog(
+ &dialogCreateOptions,
+ NULL, // NavTypeListHandle
+ sStandardNavEventFilter,
+ NULL, // NavPreviewUPP
+ navFilterUPP,
+ (void *) &myData, // inClientData
+ &dialog );
+ }
+
+ if (err == noErr)
+ err = ::NavDialogRun(dialog);
+
+ // clean up filter related data, etc.
+ if (navFilterUPP)
+ ::DisposeNavObjectFilterUPP(navFilterUPP);
+
+ if (err != noErr)
+ {
+ ::NavDialogDispose(dialog);
+ return wxID_CANCEL;
+ }
+
+ NavReplyRecord navReply;
+ err = ::NavDialogGetReply(dialog, &navReply);
+ if (err == noErr && navReply.validRecord)
+ {
+ AEKeyword theKeyword;
+ DescType actualType;
+ Size actualSize;
+ FSRef theFSRef;
+ wxString thePath ;
+ long count;
+
+ m_filterIndex = myData.currentfilter;
+ ::AECountItems( &navReply.selection, &count );
+ for (long i = 1; i <= count; ++i)
+ {
+ err = ::AEGetNthPtr(
+ &(navReply.selection), i, typeFSRef, &theKeyword, &actualType,
+ &theFSRef, sizeof(theFSRef), &actualSize );
+ if (err != noErr)
+ break;
+
+ if (HasFdFlag(wxFD_SAVE))
+ thePath = wxMacFSRefToPath( &theFSRef, navReply.saveFileName );
+ else
+ thePath = wxMacFSRefToPath( &theFSRef );
+
+ if (!thePath)
+ {
+ ::NavDisposeReply(&navReply);
+ ::NavDialogDispose(dialog);
+ return wxID_CANCEL;
+ }
+
+ m_path = thePath;
+ m_paths.Add(m_path);
+ m_fileName = wxFileNameFromPath(m_path);
+ m_fileNames.Add(m_fileName);
+ }
+
+ // set these to the first hit
+ m_path = m_paths[0];
+ m_fileName = wxFileNameFromPath(m_path);
+ m_dir = wxPathOnly(m_path);
+ }
+
+ ::NavDisposeReply(&navReply);
+ ::NavDialogDispose(dialog);
+
+ return (err == noErr) ? wxID_OK : wxID_CANCEL;
+}
+
+#endif // wxUSE_FILEDLG
+
diff --git a/src/osx/carbon/font.cpp b/src/osx/carbon/font.cpp
new file mode 100644
index 0000000000..d069f3c89e
--- /dev/null
+++ b/src/osx/carbon/font.cpp
@@ -0,0 +1,1021 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/mac/carbon/font.cpp
+// Purpose: wxFont class
+// Author: Stefan Csomor
+// Modified by:
+// Created: 1998-01-01
+// RCS-ID: $Id$
+// Copyright: (c) Stefan Csomor
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/wxprec.h"
+
+#include "wx/font.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/string.h"
+ #include "wx/utils.h"
+ #include "wx/intl.h"
+ #include "wx/gdicmn.h"
+ #include "wx/log.h"
+#endif
+
+#include "wx/fontutil.h"
+#include "wx/graphics.h"
+#include "wx/settings.h"
+
+#include "wx/mac/uma.h"
+
+#ifndef __DARWIN__
+#include
+#endif
+
+#include