]> git.saurik.com Git - wxWidgets.git/commitdiff
renaming
authorStefan Csomor <csomor@advancedconcepts.ch>
Wed, 11 Jun 2008 16:26:59 +0000 (16:26 +0000)
committerStefan Csomor <csomor@advancedconcepts.ch>
Wed, 11 Jun 2008 16:26:59 +0000 (16:26 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@54115 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

src/mac/core/cfstring.cpp [new file with mode: 0644]
src/mac/core/gsockosx.cpp [new file with mode: 0644]
src/mac/core/hid.cpp [new file with mode: 0644]
src/mac/core/hidjoystick.cpp [new file with mode: 0644]
src/mac/core/stdpaths_cf.cpp [new file with mode: 0644]
src/mac/core/strconv_cf.cpp [new file with mode: 0644]
src/mac/core/utilsexc_base.cpp [new file with mode: 0644]
src/mac/core/utilsexc_cf.cpp [new file with mode: 0644]

diff --git a/src/mac/core/cfstring.cpp b/src/mac/core/cfstring.cpp
new file mode 100644 (file)
index 0000000..5b1f8ce
--- /dev/null
@@ -0,0 +1,732 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        src/mac/corefoundation/cfstring.cpp
+// Purpose:     wxCFStringHolder and other string functions
+// Author:      Stefan Csomor
+// Modified by:
+// Created:     2004-10-29 (from code in src/mac/carbon/utils.cpp)
+// RCS-ID:      $Id$
+// Copyright:   (c) Stefan Csomor
+// Licence:     wxWindows licence
+// Usage:       Darwin (base library)
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/wxprec.h"
+
+#ifndef WX_PRECOMP
+    #include "wx/string.h"
+    #include "wx/intl.h"
+    #if wxUSE_GUI
+        #include "wx/font.h"
+    #endif
+#endif
+
+#include "wx/mac/corefoundation/cfstring.h"
+
+#include <CoreFoundation/CoreFoundation.h>
+
+void wxMacConvertNewlines13To10( char * data )
+{
+    char * buf = data ;
+    while( (buf=strchr(buf,0x0d)) != NULL )
+    {
+        *buf = 0x0a ;
+        buf++ ;
+    }
+}
+
+void wxMacConvertNewlines10To13( char * data )
+{
+    char * buf = data ;
+    while( (buf=strchr(buf,0x0a)) != NULL )
+    {
+        *buf = 0x0d ;
+        buf++ ;
+    }
+}
+
+const wxString sCR((wxChar)13);
+const wxString sLF((wxChar)10);
+
+void wxMacConvertNewlines13To10( wxString * data )
+{
+    data->Replace( sCR,sLF);
+}
+
+void wxMacConvertNewlines10To13( wxString * data )
+{
+    data->Replace( sLF,sCR);
+}
+
+wxUint32 wxMacGetSystemEncFromFontEnc(wxFontEncoding encoding)
+{
+    CFStringEncoding enc = 0 ;
+    if ( encoding == wxFONTENCODING_DEFAULT )
+    {
+#if wxUSE_GUI
+        encoding = wxFont::GetDefaultEncoding() ;
+#else
+        encoding = wxFONTENCODING_SYSTEM; // to be set below
+#endif
+    }
+
+    if ( encoding == wxFONTENCODING_SYSTEM )
+    {
+        enc = CFStringGetSystemEncoding();
+    }
+
+    switch( encoding)
+    {
+    case wxFONTENCODING_ISO8859_1 :
+        enc = kCFStringEncodingISOLatin1 ;
+        break ;
+    case wxFONTENCODING_ISO8859_2 :
+        enc = kCFStringEncodingISOLatin2;
+        break ;
+    case wxFONTENCODING_ISO8859_3 :
+        enc = kCFStringEncodingISOLatin3 ;
+        break ;
+    case wxFONTENCODING_ISO8859_4 :
+        enc = kCFStringEncodingISOLatin4;
+        break ;
+    case wxFONTENCODING_ISO8859_5 :
+        enc = kCFStringEncodingISOLatinCyrillic;
+        break ;
+    case wxFONTENCODING_ISO8859_6 :
+        enc = kCFStringEncodingISOLatinArabic;
+        break ;
+    case wxFONTENCODING_ISO8859_7 :
+        enc = kCFStringEncodingISOLatinGreek;
+        break ;
+    case wxFONTENCODING_ISO8859_8 :
+        enc = kCFStringEncodingISOLatinHebrew;
+        break ;
+    case wxFONTENCODING_ISO8859_9 :
+        enc = kCFStringEncodingISOLatin5;
+        break ;
+    case wxFONTENCODING_ISO8859_10 :
+        enc = kCFStringEncodingISOLatin6;
+        break ;
+    case wxFONTENCODING_ISO8859_13 :
+        enc = kCFStringEncodingISOLatin7;
+        break ;
+    case wxFONTENCODING_ISO8859_14 :
+        enc = kCFStringEncodingISOLatin8;
+        break ;
+    case wxFONTENCODING_ISO8859_15 :
+        enc = kCFStringEncodingISOLatin9;
+        break ;
+
+    case wxFONTENCODING_KOI8 :
+        enc = kCFStringEncodingKOI8_R;
+        break ;
+    case wxFONTENCODING_ALTERNATIVE : // MS-DOS CP866
+        enc = kCFStringEncodingDOSRussian;
+        break ;
+/*
+    case wxFONTENCODING_BULGARIAN :
+        enc = ;
+        break ;
+*/
+    case wxFONTENCODING_CP437 :
+        enc =kCFStringEncodingDOSLatinUS ;
+        break ;
+    case wxFONTENCODING_CP850 :
+        enc = kCFStringEncodingDOSLatin1;
+        break ;
+    case wxFONTENCODING_CP852 :
+        enc = kCFStringEncodingDOSLatin2;
+        break ;
+    case wxFONTENCODING_CP855 :
+        enc = kCFStringEncodingDOSCyrillic;
+        break ;
+    case wxFONTENCODING_CP866 :
+        enc =kCFStringEncodingDOSRussian ;
+        break ;
+    case wxFONTENCODING_CP874 :
+        enc = kCFStringEncodingDOSThai;
+        break ;
+    case wxFONTENCODING_CP932 :
+        enc = kCFStringEncodingDOSJapanese;
+        break ;
+    case wxFONTENCODING_CP936 :
+        enc = kCFStringEncodingDOSChineseSimplif ;
+        break ;
+    case wxFONTENCODING_CP949 :
+        enc = kCFStringEncodingDOSKorean;
+        break ;
+    case wxFONTENCODING_CP950 :
+        enc = kCFStringEncodingDOSChineseTrad;
+        break ;
+
+    case wxFONTENCODING_CP1250 :
+        enc = kCFStringEncodingWindowsLatin2;
+        break ;
+    case wxFONTENCODING_CP1251 :
+        enc =kCFStringEncodingWindowsCyrillic ;
+        break ;
+    case wxFONTENCODING_CP1252 :
+        enc =kCFStringEncodingWindowsLatin1 ;
+        break ;
+    case wxFONTENCODING_CP1253 :
+        enc = kCFStringEncodingWindowsGreek;
+        break ;
+    case wxFONTENCODING_CP1254 :
+        enc = kCFStringEncodingWindowsLatin5;
+        break ;
+    case wxFONTENCODING_CP1255 :
+        enc =kCFStringEncodingWindowsHebrew ;
+        break ;
+    case wxFONTENCODING_CP1256 :
+        enc =kCFStringEncodingWindowsArabic ;
+        break ;
+    case wxFONTENCODING_CP1257 :
+        enc = kCFStringEncodingWindowsBalticRim;
+        break ;
+#if 0
+    case wxFONTENCODING_UTF7 :
+        enc = CreateTextEncoding(kCFStringEncodingUnicodeDefault,0,kUnicodeUTF7Format) ;
+#endif
+        break ;
+    case wxFONTENCODING_UTF8 :
+        enc = kCFStringEncodingUTF8;
+        break ;
+    case wxFONTENCODING_EUC_JP :
+        enc = kCFStringEncodingEUC_JP;
+        break ;
+    case wxFONTENCODING_UTF16BE :
+        enc = kCFStringEncodingUTF16BE;
+        break ;
+    case wxFONTENCODING_UTF16LE :
+        enc = kCFStringEncodingUTF16LE;
+        break ;
+    case wxFONTENCODING_UTF32BE :
+        enc = kCFStringEncodingUTF32BE;
+        break ;
+    case wxFONTENCODING_UTF32LE :
+        enc = kCFStringEncodingUTF32LE;
+        break ;
+
+    case wxFONTENCODING_MACROMAN :
+        enc = kCFStringEncodingMacRoman ;
+        break ;
+    case wxFONTENCODING_MACJAPANESE :
+        enc = kCFStringEncodingMacJapanese ;
+        break ;
+    case wxFONTENCODING_MACCHINESETRAD :
+        enc = kCFStringEncodingMacChineseTrad ;
+        break ;
+    case wxFONTENCODING_MACKOREAN :
+        enc = kCFStringEncodingMacKorean ;
+        break ;
+    case wxFONTENCODING_MACARABIC :
+        enc = kCFStringEncodingMacArabic ;
+        break ;
+    case wxFONTENCODING_MACHEBREW :
+        enc = kCFStringEncodingMacHebrew ;
+        break ;
+    case wxFONTENCODING_MACGREEK :
+        enc = kCFStringEncodingMacGreek ;
+        break ;
+    case wxFONTENCODING_MACCYRILLIC :
+        enc = kCFStringEncodingMacCyrillic ;
+        break ;
+    case wxFONTENCODING_MACDEVANAGARI :
+        enc = kCFStringEncodingMacDevanagari ;
+        break ;
+    case wxFONTENCODING_MACGURMUKHI :
+        enc = kCFStringEncodingMacGurmukhi ;
+        break ;
+    case wxFONTENCODING_MACGUJARATI :
+        enc = kCFStringEncodingMacGujarati ;
+        break ;
+    case wxFONTENCODING_MACORIYA :
+        enc = kCFStringEncodingMacOriya ;
+        break ;
+    case wxFONTENCODING_MACBENGALI :
+        enc = kCFStringEncodingMacBengali ;
+        break ;
+    case wxFONTENCODING_MACTAMIL :
+        enc = kCFStringEncodingMacTamil ;
+        break ;
+    case wxFONTENCODING_MACTELUGU :
+        enc = kCFStringEncodingMacTelugu ;
+        break ;
+    case wxFONTENCODING_MACKANNADA :
+        enc = kCFStringEncodingMacKannada ;
+        break ;
+    case wxFONTENCODING_MACMALAJALAM :
+        enc = kCFStringEncodingMacMalayalam ;
+        break ;
+    case wxFONTENCODING_MACSINHALESE :
+        enc = kCFStringEncodingMacSinhalese ;
+        break ;
+    case wxFONTENCODING_MACBURMESE :
+        enc = kCFStringEncodingMacBurmese ;
+        break ;
+    case wxFONTENCODING_MACKHMER :
+        enc = kCFStringEncodingMacKhmer ;
+        break ;
+    case wxFONTENCODING_MACTHAI :
+        enc = kCFStringEncodingMacThai ;
+        break ;
+    case wxFONTENCODING_MACLAOTIAN :
+        enc = kCFStringEncodingMacLaotian ;
+        break ;
+    case wxFONTENCODING_MACGEORGIAN :
+        enc = kCFStringEncodingMacGeorgian ;
+        break ;
+    case wxFONTENCODING_MACARMENIAN :
+        enc = kCFStringEncodingMacArmenian ;
+        break ;
+    case wxFONTENCODING_MACCHINESESIMP :
+        enc = kCFStringEncodingMacChineseSimp ;
+        break ;
+    case wxFONTENCODING_MACTIBETAN :
+        enc = kCFStringEncodingMacTibetan ;
+        break ;
+    case wxFONTENCODING_MACMONGOLIAN :
+        enc = kCFStringEncodingMacMongolian ;
+        break ;
+    case wxFONTENCODING_MACETHIOPIC :
+        enc = kCFStringEncodingMacEthiopic ;
+        break ;
+    case wxFONTENCODING_MACCENTRALEUR :
+        enc = kCFStringEncodingMacCentralEurRoman ;
+        break ;
+    case wxFONTENCODING_MACVIATNAMESE :
+        enc = kCFStringEncodingMacVietnamese ;
+        break ;
+    case wxFONTENCODING_MACARABICEXT :
+        enc = kCFStringEncodingMacExtArabic ;
+        break ;
+    case wxFONTENCODING_MACSYMBOL :
+        enc = kCFStringEncodingMacSymbol ;
+        break ;
+    case wxFONTENCODING_MACDINGBATS :
+        enc = kCFStringEncodingMacDingbats ;
+        break ;
+    case wxFONTENCODING_MACTURKISH :
+        enc = kCFStringEncodingMacTurkish ;
+        break ;
+    case wxFONTENCODING_MACCROATIAN :
+        enc = kCFStringEncodingMacCroatian ;
+        break ;
+    case wxFONTENCODING_MACICELANDIC :
+        enc = kCFStringEncodingMacIcelandic ;
+        break ;
+    case wxFONTENCODING_MACROMANIAN :
+        enc = kCFStringEncodingMacRomanian ;
+        break ;
+    case wxFONTENCODING_MACCELTIC :
+        enc = kCFStringEncodingMacCeltic ;
+        break ;
+    case wxFONTENCODING_MACGAELIC :
+        enc = kCFStringEncodingMacGaelic ;
+        break ;
+    case wxFONTENCODING_MACKEYBOARD :
+        enc = 41; /* kTextEncodingMacKeyboardGlyphs ; */
+        break ;
+    default : // to make gcc happy
+        break ;
+    };
+    return enc ;
+}
+
+wxFontEncoding wxMacGetFontEncFromSystemEnc(wxUint32 encoding)
+{
+    wxFontEncoding enc = wxFONTENCODING_DEFAULT ;
+
+    switch( encoding)
+    {
+    case kCFStringEncodingISOLatin1  :
+        enc = wxFONTENCODING_ISO8859_1 ;
+        break ;
+    case kCFStringEncodingISOLatin2 :
+        enc = wxFONTENCODING_ISO8859_2;
+        break ;
+    case kCFStringEncodingISOLatin3 :
+        enc = wxFONTENCODING_ISO8859_3 ;
+        break ;
+    case kCFStringEncodingISOLatin4 :
+        enc = wxFONTENCODING_ISO8859_4;
+        break ;
+    case kCFStringEncodingISOLatinCyrillic :
+        enc = wxFONTENCODING_ISO8859_5;
+        break ;
+    case kCFStringEncodingISOLatinArabic :
+        enc = wxFONTENCODING_ISO8859_6;
+        break ;
+    case kCFStringEncodingISOLatinGreek :
+        enc = wxFONTENCODING_ISO8859_7;
+        break ;
+    case kCFStringEncodingISOLatinHebrew :
+        enc = wxFONTENCODING_ISO8859_8;
+        break ;
+    case kCFStringEncodingISOLatin5 :
+        enc = wxFONTENCODING_ISO8859_9;
+        break ;
+    case kCFStringEncodingISOLatin6 :
+        enc = wxFONTENCODING_ISO8859_10;
+        break ;
+    case kCFStringEncodingISOLatin7 :
+        enc = wxFONTENCODING_ISO8859_13;
+        break ;
+    case kCFStringEncodingISOLatin8 :
+        enc = wxFONTENCODING_ISO8859_14;
+        break ;
+    case kCFStringEncodingISOLatin9 :
+        enc =wxFONTENCODING_ISO8859_15 ;
+        break ;
+
+    case kCFStringEncodingKOI8_R :
+        enc = wxFONTENCODING_KOI8;
+        break ;
+/*
+    case  :
+        enc = wxFONTENCODING_BULGARIAN;
+        break ;
+*/
+    case kCFStringEncodingDOSLatinUS :
+        enc = wxFONTENCODING_CP437;
+        break ;
+    case kCFStringEncodingDOSLatin1 :
+        enc = wxFONTENCODING_CP850;
+        break ;
+    case kCFStringEncodingDOSLatin2 :
+        enc =wxFONTENCODING_CP852 ;
+        break ;
+    case kCFStringEncodingDOSCyrillic :
+        enc = wxFONTENCODING_CP855;
+        break ;
+    case kCFStringEncodingDOSRussian :
+        enc = wxFONTENCODING_CP866;
+        break ;
+    case kCFStringEncodingDOSThai :
+        enc =wxFONTENCODING_CP874 ;
+        break ;
+    case kCFStringEncodingDOSJapanese :
+        enc = wxFONTENCODING_CP932;
+        break ;
+    case kCFStringEncodingDOSChineseSimplif :
+        enc = wxFONTENCODING_CP936;
+        break ;
+    case kCFStringEncodingDOSKorean :
+        enc = wxFONTENCODING_CP949;
+        break ;
+    case kCFStringEncodingDOSChineseTrad :
+        enc = wxFONTENCODING_CP950;
+        break ;
+
+    case kCFStringEncodingWindowsLatin2 :
+        enc = wxFONTENCODING_CP1250;
+        break ;
+    case kCFStringEncodingWindowsCyrillic :
+        enc = wxFONTENCODING_CP1251;
+        break ;
+    case kCFStringEncodingWindowsLatin1 :
+        enc = wxFONTENCODING_CP1252;
+        break ;
+    case kCFStringEncodingWindowsGreek :
+        enc = wxFONTENCODING_CP1253;
+        break ;
+    case kCFStringEncodingWindowsLatin5 :
+        enc = wxFONTENCODING_CP1254;
+        break ;
+    case kCFStringEncodingWindowsHebrew :
+        enc = wxFONTENCODING_CP1255;
+        break ;
+    case kCFStringEncodingWindowsArabic :
+        enc = wxFONTENCODING_CP1256;
+        break ;
+    case kCFStringEncodingWindowsBalticRim :
+        enc =wxFONTENCODING_CP1257 ;
+        break ;
+    case kCFStringEncodingEUC_JP :
+        enc = wxFONTENCODING_EUC_JP;
+        break ;
+
+    case kCFStringEncodingUTF8 :
+        enc = wxFONTENCODING_UTF8;
+        break ;
+    case kCFStringEncodingUTF16BE :
+        enc = wxFONTENCODING_UTF16BE;
+        break ;
+    case kCFStringEncodingUTF16LE :
+        enc = wxFONTENCODING_UTF16LE;
+        break ;
+    case kCFStringEncodingUTF32BE :
+        enc = wxFONTENCODING_UTF32BE;
+        break ;
+    case kCFStringEncodingUTF32LE :
+        enc = wxFONTENCODING_UTF32LE;
+        break ;
+
+#if 0
+    case wxFONTENCODING_UTF7 :
+        enc = CreateTextEncoding(kCFStringEncodingUnicodeDefault,0,kUnicodeUTF7Format) ;
+        break ;
+#endif
+    case kCFStringEncodingMacRoman :
+        enc = wxFONTENCODING_MACROMAN ;
+        break ;
+    case kCFStringEncodingMacJapanese :
+        enc = wxFONTENCODING_MACJAPANESE ;
+        break ;
+    case kCFStringEncodingMacChineseTrad :
+        enc = wxFONTENCODING_MACCHINESETRAD ;
+        break ;
+    case kCFStringEncodingMacKorean :
+        enc = wxFONTENCODING_MACKOREAN ;
+        break ;
+    case kCFStringEncodingMacArabic :
+        enc =wxFONTENCODING_MACARABIC ;
+        break ;
+    case kCFStringEncodingMacHebrew :
+        enc = wxFONTENCODING_MACHEBREW ;
+        break ;
+    case kCFStringEncodingMacGreek :
+        enc = wxFONTENCODING_MACGREEK ;
+        break ;
+    case kCFStringEncodingMacCyrillic :
+        enc = wxFONTENCODING_MACCYRILLIC ;
+        break ;
+    case kCFStringEncodingMacDevanagari :
+        enc = wxFONTENCODING_MACDEVANAGARI ;
+        break ;
+    case kCFStringEncodingMacGurmukhi :
+        enc = wxFONTENCODING_MACGURMUKHI ;
+        break ;
+    case kCFStringEncodingMacGujarati :
+        enc = wxFONTENCODING_MACGUJARATI ;
+        break ;
+    case kCFStringEncodingMacOriya :
+        enc =wxFONTENCODING_MACORIYA ;
+        break ;
+    case kCFStringEncodingMacBengali :
+        enc =wxFONTENCODING_MACBENGALI ;
+        break ;
+    case kCFStringEncodingMacTamil :
+        enc = wxFONTENCODING_MACTAMIL ;
+        break ;
+    case kCFStringEncodingMacTelugu :
+        enc = wxFONTENCODING_MACTELUGU ;
+        break ;
+    case kCFStringEncodingMacKannada :
+        enc = wxFONTENCODING_MACKANNADA ;
+        break ;
+    case kCFStringEncodingMacMalayalam :
+        enc = wxFONTENCODING_MACMALAJALAM ;
+        break ;
+    case kCFStringEncodingMacSinhalese :
+        enc = wxFONTENCODING_MACSINHALESE ;
+        break ;
+    case kCFStringEncodingMacBurmese :
+        enc = wxFONTENCODING_MACBURMESE ;
+        break ;
+    case kCFStringEncodingMacKhmer :
+        enc = wxFONTENCODING_MACKHMER ;
+        break ;
+    case kCFStringEncodingMacThai :
+        enc = wxFONTENCODING_MACTHAI ;
+        break ;
+    case kCFStringEncodingMacLaotian :
+        enc = wxFONTENCODING_MACLAOTIAN ;
+        break ;
+    case kCFStringEncodingMacGeorgian :
+        enc = wxFONTENCODING_MACGEORGIAN ;
+        break ;
+    case kCFStringEncodingMacArmenian :
+        enc = wxFONTENCODING_MACARMENIAN ;
+        break ;
+    case kCFStringEncodingMacChineseSimp :
+        enc = wxFONTENCODING_MACCHINESESIMP ;
+        break ;
+    case kCFStringEncodingMacTibetan :
+        enc = wxFONTENCODING_MACTIBETAN ;
+        break ;
+    case kCFStringEncodingMacMongolian :
+        enc = wxFONTENCODING_MACMONGOLIAN ;
+        break ;
+    case kCFStringEncodingMacEthiopic :
+        enc = wxFONTENCODING_MACETHIOPIC ;
+        break ;
+    case kCFStringEncodingMacCentralEurRoman:
+        enc = wxFONTENCODING_MACCENTRALEUR  ;
+        break ;
+    case kCFStringEncodingMacVietnamese:
+        enc = wxFONTENCODING_MACVIATNAMESE  ;
+        break ;
+    case kCFStringEncodingMacExtArabic :
+        enc = wxFONTENCODING_MACARABICEXT ;
+        break ;
+    case kCFStringEncodingMacSymbol :
+        enc = wxFONTENCODING_MACSYMBOL ;
+        break ;
+    case kCFStringEncodingMacDingbats :
+        enc = wxFONTENCODING_MACDINGBATS ;
+        break ;
+    case kCFStringEncodingMacTurkish :
+        enc = wxFONTENCODING_MACTURKISH ;
+        break ;
+    case kCFStringEncodingMacCroatian :
+        enc = wxFONTENCODING_MACCROATIAN ;
+        break ;
+    case kCFStringEncodingMacIcelandic :
+        enc = wxFONTENCODING_MACICELANDIC ;
+        break ;
+    case kCFStringEncodingMacRomanian :
+        enc = wxFONTENCODING_MACROMANIAN ;
+        break ;
+    case kCFStringEncodingMacCeltic :
+        enc = wxFONTENCODING_MACCELTIC ;
+        break ;
+    case kCFStringEncodingMacGaelic :
+        enc = wxFONTENCODING_MACGAELIC ;
+        break ;
+    case 41 /* kTextEncodingMacKeyboardGlyphs */ :
+        enc = wxFONTENCODING_MACKEYBOARD ;
+        break ;
+    } ;
+    return enc ;
+}
+
+
+//
+// CFStringRefs
+//
+
+// converts this string into a core foundation string with optional pc 2 mac encoding
+
+wxCFStringRef::wxCFStringRef( const wxString &st , wxFontEncoding WXUNUSED_IN_UNICODE(encoding) )
+{
+    if (st.IsEmpty())
+    {
+        reset( wxCFRetain( CFSTR("") ) );
+    }
+    else
+    {
+        wxString str = st ;
+        wxMacConvertNewlines13To10( &str ) ;
+#if wxUSE_UNICODE
+#if SIZEOF_WCHAR_T == 2
+        reset( CFStringCreateWithCharacters( kCFAllocatorDefault,
+            (UniChar*)str.wc_str() , str.Len() ) );
+#else
+        wxMBConvUTF16 converter ;
+        size_t unicharbytes = converter.FromWChar( NULL , 0 , str.wc_str() , str.Length() ) ;
+        wxASSERT( unicharbytes != wxCONV_FAILED );
+        if ( unicharbytes == wxCONV_FAILED )
+        {
+            // create an empty string
+            reset( wxCFRetain( CFSTR("") ) );
+        }
+        else
+        {
+            // unicharbytes: number of bytes needed for UTF-16 encoded string (without terminating null)
+            // unichars: number of UTF-16 characters (without terminating null)
+            size_t unichars = unicharbytes /  sizeof(UniChar) ;
+            UniChar *unibuf = new UniChar[ unichars ] ;
+            converter.FromWChar( (char*)unibuf , unicharbytes , str.wc_str() , str.Length() ) ;
+            reset( CFStringCreateWithCharacters( kCFAllocatorDefault , unibuf , unichars ) ) ;
+            delete[] unibuf ;
+        }
+#endif
+#else // not wxUSE_UNICODE
+        reset( CFStringCreateWithCString( kCFAllocatorSystemDefault , str.c_str() ,
+            wxMacGetSystemEncFromFontEnc( encoding ) ) );
+#endif
+    }
+}
+
+wxString wxCFStringRef::AsString(wxFontEncoding WXUNUSED_IN_UNICODE(encoding))
+{
+    if ( !get() )
+        return wxEmptyString ;
+
+    Size cflen = CFStringGetLength( get() )  ;
+    size_t noChars ;
+    wxChar* buf = NULL ;
+
+#if wxUSE_UNICODE
+#if SIZEOF_WCHAR_T == 2
+    buf = new wxChar[ cflen + 1 ] ;
+    CFStringGetCharacters( get() , CFRangeMake( 0 , cflen ) , (UniChar*) buf ) ;
+    noChars = cflen ;
+#else
+    UniChar* unibuf = new UniChar[ cflen + 1 ] ;
+    CFStringGetCharacters( get() , CFRangeMake( 0 , cflen ) , (UniChar*) unibuf ) ;
+    unibuf[cflen] = 0 ;
+    wxMBConvUTF16 converter ;
+    noChars = converter.MB2WC( NULL , (const char*)unibuf , 0 ) ;
+    wxASSERT_MSG( noChars != wxCONV_FAILED, _T("Unable to count the number of characters in this string!") );
+    buf = new wxChar[ noChars + 1 ] ;
+    noChars = converter.MB2WC( buf , (const char*)unibuf , noChars + 1 ) ;
+    wxASSERT_MSG( noChars != wxCONV_FAILED, _T("Conversion of string failed!") );
+    delete[] unibuf ;
+#endif
+#else
+    CFIndex cStrLen ;
+    CFStringGetBytes( get() , CFRangeMake(0, cflen) , wxMacGetSystemEncFromFontEnc( encoding ) ,
+        '?' , false , NULL , 0 , &cStrLen ) ;
+    buf = new wxChar[ cStrLen + 1 ] ;
+    CFStringGetBytes( get() , CFRangeMake(0, cflen) , wxMacGetSystemEncFromFontEnc( encoding ) ,
+        '?' , false , (unsigned char*) buf , cStrLen , &cStrLen) ;
+    noChars = cStrLen ;
+#endif
+
+    buf[noChars] = 0 ;
+    wxString result(buf) ;
+    delete[] buf ;
+    wxMacConvertNewlines10To13( &result);
+    return result ;
+}
+
+//
+// wxMacUniCharBuffer
+//
+
+wxMacUniCharBuffer::wxMacUniCharBuffer( const wxString &str )
+{
+    m_chars = str.length() ;
+    m_ubuf = NULL ;
+
+#if SIZEOF_WCHAR_T == 4
+    wxMBConvUTF16 converter ;
+#if wxUSE_UNICODE
+    size_t unicharlen = converter.WC2MB( NULL , str.wc_str() , 0 ) ;
+    m_ubuf = (UniChar*) malloc( unicharlen + 2 ) ;
+    converter.WC2MB( (char*) m_ubuf , str.wc_str(), unicharlen + 2 ) ;
+#else
+    const wxWCharBuffer wchar = str.wc_str( wxConvLocal ) ;
+    size_t unicharlen = converter.WC2MB( NULL , wchar.data() , 0 ) ;
+    m_ubuf = (UniChar*) malloc( unicharlen + 2 ) ;
+    converter.WC2MB( (char*) m_ubuf , wchar.data() , unicharlen + 2 ) ;
+#endif
+    m_chars = unicharlen / 2 ;
+#else // SIZEOF_WCHAR_T is then 2
+#if wxUSE_UNICODE
+    m_ubuf = malloc( m_chars * 2 + 2 ) ;
+    memcpy( m_ubuf , (UniChar*) str.wc_str() , m_chars * 2 + 2 ) ;
+#else
+    wxWCharBuffer wchar = str.wc_str( wxConvLocal ) ;
+    m_chars = wxWcslen( wchar.data() ) ;
+    m_ubuf = malloc( m_chars * 2 + 2 ) ;
+    memcpy( m_ubuf , (UniChar*) wchar.data() , m_chars * 2 + 2 ) ;
+#endif
+#endif
+}
+
+wxMacUniCharBuffer::~wxMacUniCharBuffer()
+{
+    free( m_ubuf ) ;
+}
+
+UniCharPtr wxMacUniCharBuffer::GetBuffer() 
+{
+    return m_ubuf ;
+}
+   
+UniCharCount wxMacUniCharBuffer::GetChars()
+{
+    return m_chars ;
+}
diff --git a/src/mac/core/gsockosx.cpp b/src/mac/core/gsockosx.cpp
new file mode 100644 (file)
index 0000000..695dab7
--- /dev/null
@@ -0,0 +1,318 @@
+/* -------------------------------------------------------------------------
+ * Project: GSocket (Generic Socket) for WX
+ * Name:    src/mac/corefoundation/gsockosx.c
+ * Purpose: GSocket: Mac OS X mach-o part
+ * CVSID:   $Id$
+ * Mac code by Brian Victor, February 2002.  Email comments to bhv1@psu.edu
+ * ------------------------------------------------------------------------- */
+
+#include "wx/wxprec.h"
+
+#if wxUSE_SOCKETS
+
+#include "wx/gsocket.h"
+#include "wx/apptrait.h"
+
+#include <CoreFoundation/CoreFoundation.h>
+
+// ----------------------------------------------------------------------------
+// Mac-specific data associated with each socket by GSocketCFManager
+// ----------------------------------------------------------------------------
+
+class MacGSocketData
+{
+public:
+    // default ctor creates the object in uninitialized state, use Initialize()
+    // later to make it usable
+    MacGSocketData()
+    {
+        m_socket = NULL;
+        m_source = NULL;
+    }
+
+    // initialize the data associated with the given socket
+    bool Initialize(GSocket *socket)
+    {
+        wxASSERT_MSG( !IsInitialized(), "shouldn't be called twice" );
+
+        // we need a valid Unix socket to create a CFSocket
+        if ( socket->m_fd < 0 )
+            return false;
+
+        CFSocketContext cont;
+        cont.version = 0;               // this currently must be 0
+        cont.info = socket;             // pointer passed to our callback
+        cont.retain = NULL;             // no need to retain/release/copy the
+        cont.release = NULL;            //  socket pointer, so all callbacks
+        cont.copyDescription = NULL;    //  can be left NULL
+
+        m_socket = CFSocketCreateWithNative
+                   (
+                        NULL,                   // default allocator
+                        socket->m_fd,
+                        kCFSocketReadCallBack |
+                        kCFSocketWriteCallBack |
+                        kCFSocketConnectCallBack,
+                        SocketCallback,
+                        &cont
+                   );
+        if ( !m_socket )
+            return false;
+
+        m_source = CFSocketCreateRunLoopSource(NULL, m_socket, 0);
+
+        return m_source != NULL;
+    }
+
+    // free the objects created by Initialize()
+    ~MacGSocketData()
+    {
+        if ( m_source )
+            CFRelease(m_source);
+        if ( m_socket )
+            CFRelease(m_socket);
+    }
+
+    // return true if Initialize() had already been called successfully
+    bool IsInitialized() const { return m_source && m_socket; }
+
+
+    // accessors: should only be called if IsInitialized()
+    CFSocketRef GetSocket() const
+    {
+        wxASSERT( IsInitialized() );
+
+        return m_socket;
+    }
+
+    CFRunLoopSourceRef GetSource() const
+    {
+        wxASSERT( IsInitialized() );
+
+        return m_source;
+    }
+
+private:
+    static void SocketCallback(CFSocketRef WXUNUSED(s),
+                               CFSocketCallBackType callbackType,
+                               CFDataRef WXUNUSED(address),
+                               const void* data,
+                               void* info)
+    {
+        GSocket * const socket = wx_static_cast(GSocket *, info);
+        MacGSocketData * const
+            macdata = wx_static_cast(MacGSocketData *, socket->m_gui_dependent);
+        if ( !macdata )
+            return;
+
+        switch (callbackType)
+        {
+            case kCFSocketConnectCallBack:
+                wxASSERT(!socket->m_server);
+                // KH: If data is non-NULL, the connect failed, do not call Detected_Write,
+                // which will only end up creating a spurious connect event because the
+                // call to getsocketopt SO_ERROR inexplicably returns no error.
+                // The change in behavior cannot be traced to any particular commit or
+                // timeframe so I'm not sure what to think, but after so many hours,
+                // this seems to address the issue and it's time to move on.
+                if (data == NULL)
+                    socket->Detected_Write();
+                break;
+
+            case kCFSocketReadCallBack:
+                socket->Detected_Read();
+                break;
+
+            case kCFSocketWriteCallBack:
+                socket->Detected_Write();
+                break;
+
+            default:
+                wxFAIL_MSG( "unexpected socket callback" );
+        }
+    }
+
+    CFSocketRef m_socket;
+    CFRunLoopSourceRef m_source;
+
+    DECLARE_NO_COPY_CLASS(MacGSocketData);
+};
+
+// ----------------------------------------------------------------------------
+// CoreFoundation implementation of GSocketManager
+// ----------------------------------------------------------------------------
+
+class GSocketCFManager : public GSocketManager
+{
+public:
+    virtual bool OnInit();
+    virtual void OnExit();
+
+    virtual bool Init_Socket(GSocket *socket);
+    virtual void Destroy_Socket(GSocket *socket);
+
+    virtual void Install_Callback(GSocket *socket, GSocketEvent event);
+    virtual void Uninstall_Callback(GSocket *socket, GSocketEvent event);
+
+    virtual void Enable_Events(GSocket *socket);
+    virtual void Disable_Events(GSocket *socket);
+
+private:
+    // retrieve our custom data associated with the given socket
+    //
+    // this is a low level function, use GetInitializedData() instead if the
+    // data pointer should also be correctly initialized if it hadn't been done
+    // yet
+    //
+    // may return NULL if we hadn't created the data for this socket yet
+    MacGSocketData *GetData(GSocket *socket) const
+    {
+        return wx_static_cast(MacGSocketData *, socket->m_gui_dependent);
+    }
+
+    // return the custom data pointer initializing it if it hadn't been done
+    // yet
+    //
+    // may return NULL if there is no associated data
+    MacGSocketData *GetInitializedData(GSocket *socket) const
+    {
+        MacGSocketData * const data = GetData(socket);
+        if ( data && !data->IsInitialized() )
+        {
+            if ( !data->Initialize(socket) )
+                return NULL;
+        }
+
+        return data;
+    }
+
+    // return CFSocket callback mask corresponding to the given event (the
+    // socket parameter is needed because some events are interpreted
+    // differently depending on whether they happen on a server or on a client
+    // socket)
+    static int GetCFCallback(GSocket *socket, GSocketEvent event);
+
+
+    // Sockets must use the event loop on the main thread so we store a
+    // reference to the main loop here in OnInit()
+    static CFRunLoopRef ms_mainRunLoop;
+};
+
+CFRunLoopRef GSocketCFManager::ms_mainRunLoop = NULL;
+
+bool GSocketCFManager::OnInit()
+{
+    // No need to store the main loop again
+    if (ms_mainRunLoop != NULL)
+        return true;
+
+    // Get the loop for the main thread so our events will actually fire.
+    // The common socket.cpp code will assert if initialize is called from a
+    // secondary thread, otherwise Mac would have the same problems as MSW
+    ms_mainRunLoop = CFRunLoopGetCurrent();
+    if ( !ms_mainRunLoop )
+        return false;
+
+    CFRetain(ms_mainRunLoop);
+
+    return true;
+}
+
+void GSocketCFManager::OnExit()
+{
+    // Release the reference count, and set the reference back to NULL
+    CFRelease(ms_mainRunLoop);
+    ms_mainRunLoop = NULL;
+}
+
+bool GSocketCFManager::Init_Socket(GSocket *socket)
+{
+    socket->m_gui_dependent = new MacGSocketData;
+    return true;
+}
+
+void GSocketCFManager::Destroy_Socket(GSocket *socket)
+{
+    MacGSocketData * const data = GetData(socket);
+    if ( data )
+    {
+        delete data;
+        socket->m_gui_dependent = NULL;
+    }
+}
+
+/* static */
+int GSocketCFManager::GetCFCallback(GSocket *socket, GSocketEvent event)
+{
+    switch ( event )
+    {
+        case GSOCK_CONNECTION:
+            return socket->m_server ? kCFSocketReadCallBack
+                                    : kCFSocketConnectCallBack;
+
+        case GSOCK_LOST:
+        case GSOCK_INPUT:
+            return kCFSocketReadCallBack;
+
+        case GSOCK_OUTPUT:
+            return kCFSocketWriteCallBack;
+
+        case GSOCK_MAX_EVENT:
+            wxFAIL_MSG( "invalid GSocketEvent" );
+            return 0;
+
+        default:
+            wxFAIL_MSG( "unknown GSocketEvent" );
+            return 0;
+    }
+}
+
+void GSocketCFManager::Install_Callback(GSocket *socket, GSocketEvent event)
+{
+    const MacGSocketData * const data = GetInitializedData(socket);
+    if ( !data )
+        return;
+
+    CFSocketEnableCallBacks(data->GetSocket(), GetCFCallback(socket, event));
+}
+
+void GSocketCFManager::Uninstall_Callback(GSocket *socket, GSocketEvent event)
+{
+    const MacGSocketData * const data = GetInitializedData(socket);
+    if ( !data )
+        return;
+
+    CFSocketDisableCallBacks(data->GetSocket(), GetCFCallback(socket, event));
+}
+
+void GSocketCFManager::Enable_Events(GSocket *socket)
+{
+    const MacGSocketData * const data = GetInitializedData(socket);
+    if ( !data )
+        return;
+
+    CFRunLoopAddSource(ms_mainRunLoop, data->GetSource(), kCFRunLoopCommonModes);
+}
+
+void GSocketCFManager::Disable_Events(GSocket *socket)
+{
+    const MacGSocketData * const data = GetInitializedData(socket);
+    if ( !data )
+        return;
+
+    // CFSocketInvalidate does CFRunLoopRemoveSource anyway
+    CFRunLoopRemoveSource(ms_mainRunLoop, data->GetSource(), kCFRunLoopCommonModes);
+    CFSocketInvalidate(data->GetSocket());
+
+    // CFSocketInvalidate has closed the socket so we want to make sure GSocket knows this
+    socket->m_fd = -1;
+}
+
+GSocketManager *wxAppTraits::GetSocketManager()
+{
+    static GSocketCFManager s_manager;
+
+    return &s_manager;
+};
+
+#endif // wxUSE_SOCKETS
diff --git a/src/mac/core/hid.cpp b/src/mac/core/hid.cpp
new file mode 100644 (file)
index 0000000..fb9a4d0
--- /dev/null
@@ -0,0 +1,741 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        src/mac/corefoundation/hid.cpp
+// Purpose:     DARWIN HID layer for WX Implementation
+// Author:      Ryan Norton
+// Modified by:
+// Created:     11/11/2003
+// RCS-ID:      $Id$
+// Copyright:   (c) Ryan Norton
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+// ===========================================================================
+// declarations
+// ===========================================================================
+
+// ---------------------------------------------------------------------------
+// headers
+// ---------------------------------------------------------------------------
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+    #pragma hdrstop
+#endif
+
+//DARWIN _ONLY_
+#ifdef __DARWIN__
+
+#include "wx/mac/corefoundation/hid.h"
+
+#ifndef WX_PRECOMP
+    #include "wx/dynarray.h"
+    #include "wx/string.h"
+    #include "wx/log.h"
+    #include "wx/utils.h"
+    #include "wx/module.h"
+#endif
+
+#include "wx/mac/corefoundation/cfstring.h"
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// wxHIDDevice
+//
+// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+// ----------------------------------------------------------------------------
+// wxHIDDevice::Create
+//
+//  nClass is the HID Page such as
+//      kHIDPage_GenericDesktop
+//  nType is the HID Usage such as
+//      kHIDUsage_GD_Joystick,kHIDUsage_GD_Mouse,kHIDUsage_GD_Keyboard
+//  nDev is the device number to use
+//
+// ----------------------------------------------------------------------------
+bool wxHIDDevice::Create (int nClass, int nType, int nDev)
+{
+    //Create the mach port
+    if(IOMasterPort(bootstrap_port, &m_pPort) != kIOReturnSuccess)
+    {
+        wxLogSysError(wxT("Could not create mach port"));
+        return false;
+    }
+
+    //Dictionary that will hold first
+    //the matching dictionary for determining which kind of devices we want,
+    //then later some registry properties from an iterator (see below)
+    //
+    //The call to IOServiceMatching filters down the
+    //the services we want to hid services (and also eats the
+    //dictionary up for us (consumes one reference))
+    CFMutableDictionaryRef pDictionary = IOServiceMatching(kIOHIDDeviceKey);
+    if(pDictionary == NULL)
+    {
+        wxLogSysError( _T("IOServiceMatching(kIOHIDDeviceKey) failed") );
+        return false;
+    }
+
+    //Here we'll filter down the services to what we want
+    if (nType != -1)
+    {
+        CFNumberRef pType = CFNumberCreate(kCFAllocatorDefault,
+                                    kCFNumberIntType, &nType);
+        CFDictionarySetValue(pDictionary, CFSTR(kIOHIDPrimaryUsageKey), pType);
+        CFRelease(pType);
+    }
+    if (nClass != -1)
+    {
+        CFNumberRef pClass = CFNumberCreate(kCFAllocatorDefault,
+                                    kCFNumberIntType, &nClass);
+        CFDictionarySetValue(pDictionary, CFSTR(kIOHIDPrimaryUsagePageKey), pClass);
+        CFRelease(pClass);
+    }
+
+    //Now get the maching services
+    io_iterator_t pIterator;
+    if( IOServiceGetMatchingServices(m_pPort,
+                        pDictionary, &pIterator) != kIOReturnSuccess )
+    {
+        wxLogSysError(_T("No Matching HID Services"));
+        return false;
+    }
+
+    //Were there any devices matched?
+    if(pIterator == 0)
+        return false; // No devices found
+
+    //Now we iterate through them
+    io_object_t pObject;
+    while ( (pObject = IOIteratorNext(pIterator)) != 0)
+    {
+        if(--nDev != 0)
+        {
+            IOObjectRelease(pObject);
+            continue;
+        }
+
+        if ( IORegistryEntryCreateCFProperties
+             (
+                pObject,
+                &pDictionary,
+                kCFAllocatorDefault,
+                kNilOptions
+             ) != KERN_SUCCESS )
+        {
+            wxLogDebug(_T("IORegistryEntryCreateCFProperties failed"));
+        }
+
+        //
+        // Now we get the attributes of each "product" in the iterator
+        //
+
+        //Get [product] name
+        CFStringRef cfsProduct = (CFStringRef)
+            CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDProductKey));
+        m_szProductName =
+            wxCFStringRef( wxCFRetain(cfsProduct)
+                               ).AsString();
+
+        //Get the Product ID Key
+        CFNumberRef cfnProductId = (CFNumberRef)
+            CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDProductIDKey));
+        if (cfnProductId)
+        {
+            CFNumberGetValue(cfnProductId, kCFNumberIntType, &m_nProductId);
+        }
+
+        //Get the Vendor ID Key
+        CFNumberRef cfnVendorId = (CFNumberRef)
+            CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDVendorIDKey));
+        if (cfnVendorId)
+        {
+            CFNumberGetValue(cfnVendorId, kCFNumberIntType, &m_nManufacturerId);
+        }
+
+        //
+        // End attribute getting
+        //
+
+        //Create the interface (good grief - long function names!)
+        SInt32 nScore;
+        IOCFPlugInInterface** ppPlugin;
+        if(IOCreatePlugInInterfaceForService(pObject,
+                                             kIOHIDDeviceUserClientTypeID,
+                                             kIOCFPlugInInterfaceID, &ppPlugin,
+                                             &nScore) !=  kIOReturnSuccess)
+        {
+            wxLogSysError(wxT("Could not create HID Interface for product"));
+            return false;
+        }
+
+        //Now, the final thing we can check before we fall back to asserts
+        //(because the dtor only checks if the device is ok, so if anything
+        //fails from now on the dtor will delete the device anyway, so we can't break from this).
+
+        //Get the HID interface from the plugin to the mach port
+        if((*ppPlugin)->QueryInterface(ppPlugin,
+                               CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID),
+                               (void**) &m_ppDevice) != S_OK)
+        {
+            wxLogSysError(wxT("Could not get device interface from HID interface"));
+            return false;
+        }
+
+        //release the plugin
+        (*ppPlugin)->Release(ppPlugin);
+
+        //open the HID interface...
+        if ( (*m_ppDevice)->open(m_ppDevice, 0) != S_OK )
+            wxLogDebug(_T("HID device: open failed"));
+
+        //
+        //Now the hard part - in order to scan things we need "cookies"
+        //
+        CFArrayRef cfaCookies = (CFArrayRef)CFDictionaryGetValue(pDictionary,
+                                 CFSTR(kIOHIDElementKey));
+        BuildCookies(cfaCookies);
+
+        //cleanup
+        CFRelease(pDictionary);
+        IOObjectRelease(pObject);
+
+        //iterator cleanup
+        IOObjectRelease(pIterator);
+
+        return true;
+    }
+
+    //iterator cleanup
+    IOObjectRelease(pIterator);
+
+    return false; //no device
+}//end Create()
+
+// ----------------------------------------------------------------------------
+// wxHIDDevice::GetCount [static]
+//
+//  Obtains the number of devices on a system for a given HID Page (nClass)
+// and HID Usage (nType).
+// ----------------------------------------------------------------------------
+size_t wxHIDDevice::GetCount (int nClass, int nType)
+{
+    //Create the mach port
+    mach_port_t             pPort;
+    if(IOMasterPort(bootstrap_port, &pPort) != kIOReturnSuccess)
+    {
+        wxLogSysError(wxT("Could not create mach port"));
+        return false;
+    }
+
+    //Dictionary that will hold first
+    //the matching dictionary for determining which kind of devices we want,
+    //then later some registry properties from an iterator (see below)
+    CFMutableDictionaryRef pDictionary = IOServiceMatching(kIOHIDDeviceKey);
+    if(pDictionary == NULL)
+    {
+        wxLogSysError( _T("IOServiceMatching(kIOHIDDeviceKey) failed") );
+        return false;
+    }
+
+    //Here we'll filter down the services to what we want
+    if (nType != -1)
+    {
+        CFNumberRef pType = CFNumberCreate(kCFAllocatorDefault,
+                                    kCFNumberIntType, &nType);
+        CFDictionarySetValue(pDictionary, CFSTR(kIOHIDPrimaryUsageKey), pType);
+        CFRelease(pType);
+    }
+    if (nClass != -1)
+    {
+        CFNumberRef pClass = CFNumberCreate(kCFAllocatorDefault,
+                                    kCFNumberIntType, &nClass);
+        CFDictionarySetValue(pDictionary, CFSTR(kIOHIDPrimaryUsagePageKey), pClass);
+        CFRelease(pClass);
+    }
+
+    //Now get the maching services
+    io_iterator_t pIterator;
+    if( IOServiceGetMatchingServices(pPort,
+                                     pDictionary, &pIterator) != kIOReturnSuccess )
+    {
+        wxLogSysError(_T("No Matching HID Services"));
+        return false;
+    }
+
+    //If the iterator doesn't exist there are no devices :)
+    if ( !pIterator )
+        return 0;
+
+    //Now we iterate through them
+    size_t nCount = 0;
+    io_object_t pObject;
+    while ( (pObject = IOIteratorNext(pIterator)) != 0)
+    {
+        ++nCount;
+        IOObjectRelease(pObject);
+    }
+
+    //cleanup
+    IOObjectRelease(pIterator);
+    mach_port_deallocate(mach_task_self(), pPort);
+
+    return nCount;
+}//end Create()
+
+// ----------------------------------------------------------------------------
+// wxHIDDevice::AddCookie
+//
+// Adds a cookie to the internal cookie array from a CFType
+// ----------------------------------------------------------------------------
+void wxHIDDevice::AddCookie(CFTypeRef Data, int i)
+{
+    CFNumberGetValue(
+                (CFNumberRef) CFDictionaryGetValue    ( (CFDictionaryRef) Data
+                                        , CFSTR(kIOHIDElementCookieKey)
+                                        ),
+                kCFNumberIntType,
+                &m_pCookies[i]
+                );
+}
+
+// ----------------------------------------------------------------------------
+// wxHIDDevice::AddCookieInQueue
+//
+// Adds a cookie to the internal cookie array from a CFType and additionally
+// adds it to the internal HID Queue
+// ----------------------------------------------------------------------------
+void wxHIDDevice::AddCookieInQueue(CFTypeRef Data, int i)
+{
+    //3rd Param flags (none yet)
+    AddCookie(Data, i);
+    if ( (*m_ppQueue)->addElement(m_ppQueue, m_pCookies[i], 0) != S_OK )
+        wxLogDebug(_T("HID device: adding element failed"));
+}
+
+// ----------------------------------------------------------------------------
+// wxHIDDevice::InitCookies
+//
+// Create the internal cookie array, optionally creating a HID Queue
+// ----------------------------------------------------------------------------
+void wxHIDDevice::InitCookies(size_t dwSize, bool bQueue)
+{
+    m_pCookies = new IOHIDElementCookie[dwSize];
+    if (bQueue)
+    {
+        wxASSERT( m_ppQueue == NULL);
+        m_ppQueue = (*m_ppDevice)->allocQueue(m_ppDevice);
+        if ( !m_ppQueue )
+        {
+            wxLogDebug(_T("HID device: allocQueue failed"));
+            return;
+        }
+
+        //Param 2, flags, none yet
+        if ( (*m_ppQueue)->create(m_ppQueue, 0, 512) != S_OK )
+        {
+            wxLogDebug(_T("HID device: create failed"));
+        }
+    }
+
+    //make sure that cookie array is clear
+    memset(m_pCookies, 0, sizeof(*m_pCookies) * dwSize);
+}
+
+// ----------------------------------------------------------------------------
+// wxHIDDevice::IsActive
+//
+// Returns true if a cookie of the device is active - for example if a key is
+// held down, joystick button pressed, caps lock active, etc..
+// ----------------------------------------------------------------------------
+bool wxHIDDevice::IsActive(int nIndex)
+{
+    if(!HasElement(nIndex))
+    {
+        //cookie at index does not exist - getElementValue
+        //could return true which would be incorrect so we
+        //check here
+        return false;
+    }
+
+    IOHIDEventStruct Event;
+    (*m_ppDevice)->getElementValue(m_ppDevice, m_pCookies[nIndex], &Event);
+    return !!Event.value;
+}
+
+// ----------------------------------------------------------------------------
+// wxHIDDevice::HasElement
+//
+// Returns true if the element in the internal cookie array exists
+// ----------------------------------------------------------------------------
+bool wxHIDDevice::HasElement(int nIndex)
+{
+    return m_pCookies[nIndex] != NULL;
+}
+
+// ----------------------------------------------------------------------------
+// wxHIDDevice Destructor
+//
+// Frees all memory and objects from the structure
+// ----------------------------------------------------------------------------
+wxHIDDevice::~wxHIDDevice()
+{
+    if (m_ppDevice != NULL)
+    {
+        if (m_ppQueue != NULL)
+        {
+            (*m_ppQueue)->stop(m_ppQueue);
+            (*m_ppQueue)->dispose(m_ppQueue);
+            (*m_ppQueue)->Release(m_ppQueue);
+        }
+        (*m_ppDevice)->close(m_ppDevice);
+        (*m_ppDevice)->Release(m_ppDevice);
+        mach_port_deallocate(mach_task_self(), m_pPort);
+    }
+
+    if (m_pCookies != NULL)
+    {
+        delete [] m_pCookies;
+    }
+}
+
+// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// wxHIDKeyboard
+//
+// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//There are no right shift, alt etc. in the wx headers yet so just sort
+//of "define our own" for now
+enum
+{
+    WXK_RSHIFT = 400,
+    WXK_RALT,
+    WXK_RCONTROL,
+    WXK_RMENU
+};
+
+// ----------------------------------------------------------------------------
+// wxHIDKeyboard::GetCount [static]
+//
+// Get number of HID keyboards available
+// ----------------------------------------------------------------------------
+int wxHIDKeyboard::GetCount()
+{
+    return wxHIDDevice::GetCount(kHIDPage_GenericDesktop,
+                               kHIDUsage_GD_Keyboard);
+}
+
+// ----------------------------------------------------------------------------
+// wxHIDKeyboard::Create
+//
+// Create the HID Keyboard
+// ----------------------------------------------------------------------------
+bool wxHIDKeyboard::Create(int nDev /* = 1*/)
+{
+    return wxHIDDevice::Create(kHIDPage_GenericDesktop,
+                               kHIDUsage_GD_Keyboard,
+                               nDev);
+}
+
+// ----------------------------------------------------------------------------
+// wxHIDKeyboard::AddCookie
+//
+// Overloaded version of wxHIDDevice::AddCookie that simply does not
+// add a cookie if a duplicate is found
+// ----------------------------------------------------------------------------
+void wxHIDKeyboard::AddCookie(CFTypeRef Data, int i)
+{
+    if(!HasElement(i))
+        wxHIDDevice::AddCookie(Data, i);
+}
+
+// ----------------------------------------------------------------------------
+// wxHIDKeyboard::BuildCookies
+//
+// Callback from Create() to build the HID cookies for the internal cookie
+// array
+// ----------------------------------------------------------------------------
+void wxHIDKeyboard::BuildCookies(CFArrayRef Array)
+{
+    //Create internal cookie array
+    InitCookies(500);
+
+    //Begin recursing in array
+    DoBuildCookies(Array);
+}
+
+void wxHIDKeyboard::DoBuildCookies(CFArrayRef Array)
+{
+    //Now go through each possible cookie
+    int i,
+        nUsage;
+//    bool bEOTriggered = false;
+    for (i = 0; i < CFArrayGetCount(Array); ++i)
+    {
+        const void* ref = CFDictionaryGetValue(
+                (CFDictionaryRef)CFArrayGetValueAtIndex(Array, i),
+                CFSTR(kIOHIDElementKey)
+                                              );
+
+        if (ref != NULL)
+        {
+            DoBuildCookies((CFArrayRef) ref);
+        }
+        else
+    {
+
+            //
+            // Get the usage #
+            //
+        CFNumberGetValue(
+                (CFNumberRef)
+                    CFDictionaryGetValue((CFDictionaryRef)
+                        CFArrayGetValueAtIndex(Array, i),
+                        CFSTR(kIOHIDElementUsageKey)
+                                        ),
+                              kCFNumberLongType,
+                              &nUsage);
+
+            //
+            // Now translate the usage # into a wx keycode
+            //
+
+        //
+        // OK, this is strange - basically this kind of strange -
+        // Starting from 0xEO these elements (like shift) appear twice in
+        // the array!  The ones at the end are bogus I guess - the funny part
+        // is that besides the fact that the ones at the front have a Unit
+        // and UnitExponent key with a value of 0 and a different cookie value,
+        // there is no discernable difference between the two...
+        //
+        // Will the real shift please stand up?
+        //
+        // Something to spend a support request on, if I had one, LOL.
+        //
+        //if(nUsage == 0xE0)
+        //{
+        //    if(bEOTriggered)
+        //       break;
+        //    bEOTriggered = true;
+        //}
+        //Instead of that though we now just don't add duplicate keys
+
+        if (nUsage >= kHIDUsage_KeyboardA && nUsage <= kHIDUsage_KeyboardZ)
+            AddCookie(CFArrayGetValueAtIndex(Array, i), 'A' + (nUsage - kHIDUsage_KeyboardA) );
+        else if (nUsage >= kHIDUsage_Keyboard1 && nUsage <= kHIDUsage_Keyboard9)
+            AddCookie(CFArrayGetValueAtIndex(Array, i), '1' + (nUsage - kHIDUsage_Keyboard1) );
+        else if (nUsage >= kHIDUsage_KeyboardF1 && nUsage <= kHIDUsage_KeyboardF12)
+            AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_F1 + (nUsage - kHIDUsage_KeyboardF1) );
+        else if (nUsage >= kHIDUsage_KeyboardF13 && nUsage <= kHIDUsage_KeyboardF24)
+            AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_F13 + (nUsage - kHIDUsage_KeyboardF13) );
+        else if (nUsage >= kHIDUsage_Keypad1 && nUsage <= kHIDUsage_Keypad9)
+            AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_NUMPAD1 + (nUsage - kHIDUsage_Keypad1) );
+        else switch (nUsage)
+        {
+            //0's (wx & ascii go 0-9, but HID goes 1-0)
+            case kHIDUsage_Keyboard0:
+                AddCookie(CFArrayGetValueAtIndex(Array, i), '0');
+                break;
+            case kHIDUsage_Keypad0:
+                AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_NUMPAD0);
+                break;
+
+            //Basic
+            case kHIDUsage_KeyboardReturnOrEnter:
+                AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_RETURN);
+                break;
+            case kHIDUsage_KeyboardEscape:
+                AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_ESCAPE);
+                break;
+            case kHIDUsage_KeyboardDeleteOrBackspace:
+                AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_BACK);
+                break;
+            case kHIDUsage_KeyboardTab:
+                AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_TAB);
+                break;
+            case kHIDUsage_KeyboardSpacebar:
+                AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_SPACE);
+                break;
+            case kHIDUsage_KeyboardPageUp:
+                AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_PAGEUP);
+                break;
+            case kHIDUsage_KeyboardEnd:
+                AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_END);
+                break;
+            case kHIDUsage_KeyboardPageDown:
+                AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_PAGEDOWN);
+                break;
+            case kHIDUsage_KeyboardRightArrow:
+                AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_RIGHT);
+                break;
+            case kHIDUsage_KeyboardLeftArrow:
+                AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_LEFT);
+                break;
+            case kHIDUsage_KeyboardDownArrow:
+                AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_DOWN);
+                break;
+            case kHIDUsage_KeyboardUpArrow:
+                AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_UP);
+                break;
+
+            //LEDS
+            case kHIDUsage_KeyboardCapsLock:
+                AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_CAPITAL);
+                break;
+            case kHIDUsage_KeypadNumLock:
+                AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_NUMLOCK);
+                break;
+            case kHIDUsage_KeyboardScrollLock:
+                AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_SCROLL);
+                break;
+
+            //Menu keys, Shift, other specials
+            case kHIDUsage_KeyboardLeftControl:
+                AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_CONTROL);
+                break;
+            case kHIDUsage_KeyboardLeftShift:
+                AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_SHIFT);
+                break;
+            case kHIDUsage_KeyboardLeftAlt:
+                AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_ALT);
+                break;
+            case kHIDUsage_KeyboardLeftGUI:
+                AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_MENU);
+                break;
+            case kHIDUsage_KeyboardRightControl:
+                AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_RCONTROL);
+                break;
+            case kHIDUsage_KeyboardRightShift:
+                AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_RSHIFT);
+                break;
+            case kHIDUsage_KeyboardRightAlt:
+                AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_RALT);
+                break;
+            case kHIDUsage_KeyboardRightGUI:
+                AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_RMENU);
+                break;
+
+            //Default
+            default:
+            //not in wx keycodes - do nothing....
+            break;
+            } //end mightly long switch
+        } //end if the current element is not an array...
+    } //end for loop for Array
+}//end buildcookies
+
+// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// wxHIDModule
+//
+// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+class wxHIDModule : public wxModule
+{
+    DECLARE_DYNAMIC_CLASS(wxHIDModule)
+
+    public:
+        static wxArrayPtrVoid sm_keyboards;
+        virtual bool OnInit()
+        {
+            return true;
+        }
+        virtual void OnExit()
+        {
+            for(size_t i = 0; i < sm_keyboards.GetCount(); ++i)
+                delete (wxHIDKeyboard*) sm_keyboards[i];
+        }
+};
+
+IMPLEMENT_DYNAMIC_CLASS(wxHIDModule, wxModule)
+
+wxArrayPtrVoid wxHIDModule::sm_keyboards;
+
+// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// wxGetKeyState()
+//
+// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+bool wxGetKeyState (wxKeyCode key)
+{
+    wxASSERT_MSG(key != WXK_LBUTTON && key != WXK_RBUTTON && key !=
+        WXK_MBUTTON, wxT("can't use wxGetKeyState() for mouse buttons"));
+
+    if (wxHIDModule::sm_keyboards.GetCount() == 0)
+    {
+        int nKeyboards = wxHIDKeyboard::GetCount();
+
+        for(int i = 1; i <= nKeyboards; ++i)
+        {
+            wxHIDKeyboard* keyboard = new wxHIDKeyboard();
+            if(keyboard->Create(i))
+            {
+                wxHIDModule::sm_keyboards.Add(keyboard);
+            }
+            else
+            {
+                delete keyboard;
+                break;
+            }
+        }
+
+        wxASSERT_MSG(wxHIDModule::sm_keyboards.GetCount() != 0,
+                     wxT("No keyboards found!"));
+    }
+
+    for(size_t i = 0; i < wxHIDModule::sm_keyboards.GetCount(); ++i)
+    {
+        wxHIDKeyboard* keyboard = (wxHIDKeyboard*)
+                                wxHIDModule::sm_keyboards[i];
+
+    switch(key)
+    {
+    case WXK_SHIFT:
+            if( keyboard->IsActive(WXK_SHIFT) ||
+                   keyboard->IsActive(WXK_RSHIFT) )
+            {
+                return true;
+            }
+        break;
+    case WXK_ALT:
+            if( keyboard->IsActive(WXK_ALT) ||
+                   keyboard->IsActive(WXK_RALT) )
+            {
+                return true;
+            }
+        break;
+    case WXK_CONTROL:
+            if( keyboard->IsActive(WXK_CONTROL) ||
+                   keyboard->IsActive(WXK_RCONTROL) )
+            {
+                return true;
+            }
+        break;
+    case WXK_MENU:
+            if( keyboard->IsActive(WXK_MENU) ||
+                   keyboard->IsActive(WXK_RMENU) )
+            {
+                return true;
+            }
+        break;
+    default:
+            if( keyboard->IsActive(key) )
+            {
+                return true;
+            }
+        break;
+    }
+    }
+
+    return false; //not down/error
+}
+
+#endif //__DARWIN__
diff --git a/src/mac/core/hidjoystick.cpp b/src/mac/core/hidjoystick.cpp
new file mode 100644 (file)
index 0000000..637546c
--- /dev/null
@@ -0,0 +1,905 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        src/mac/corefoundation/joystick.cpp
+// Purpose:     wxJoystick class
+// Author:      Ryan Norton
+// Modified by:
+// Created:     2/13/2005
+// RCS-ID:      $Id$
+// Copyright:   (c) Ryan Norton
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+//===========================================================================
+//  DECLARATIONS
+//===========================================================================
+
+//---------------------------------------------------------------------------
+// Pre-compiled header stuff
+//---------------------------------------------------------------------------
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+//---------------------------------------------------------------------------
+// Guard
+//---------------------------------------------------------------------------
+
+//we only support HID on OSX (DARWIN), since it requires DARWIN...
+#if wxUSE_JOYSTICK && wxUSE_THREADS
+
+//---------------------------------------------------------------------------
+// Includes
+//---------------------------------------------------------------------------
+
+#ifndef WX_PRECOMP
+    #include "wx/log.h"
+    #include "wx/event.h"   //joystick wxEvents
+    #include "wx/window.h"  //for wxWindow to "capture" joystick
+#endif
+
+#include "wx/joystick.h"    //...
+#include "wx/thread.h"      //wxThread for polling thread/ wxCriticalSection
+
+//private headers
+#include "wx/mac/corefoundation/hid.h" //private mac hid stuff
+
+//mac headers
+#include <CoreServices/CoreServices.h>
+#include <mach/mach.h>
+#include <mach/mach_time.h>
+#include <unistd.h>
+
+//---------------------------------------------------------------------------
+// Definitions/Enumerations
+//---------------------------------------------------------------------------
+
+#define wxJS_MAX_AXES       10 /*max number of axes*/
+#define wxJS_MAX_BUTTONS    40 /*max number of buttons*/
+
+enum
+{
+    //These are positions within the cookie array
+    //in wxHIDJoystick that the cookies that store the axis' are
+    wxJS_AXIS_X = 40,
+    wxJS_AXIS_Y,
+    wxJS_AXIS_Z,
+    wxJS_AXIS_RUDDER,
+    wxJS_AXIS_U,
+    wxJS_AXIS_V,
+};
+
+//---------------------------------------------------------------------------
+// wxHIDJoystick
+//---------------------------------------------------------------------------
+class wxHIDJoystick : public wxHIDDevice
+{
+public:
+    wxHIDJoystick();
+    virtual ~wxHIDJoystick();
+
+    bool Create(int nWhich);
+    virtual void BuildCookies(CFArrayRef Array);
+    void MakeCookies(CFArrayRef Array);
+    IOHIDElementCookie* GetCookies();
+    IOHIDQueueInterface** GetQueue();
+
+    int  m_nXMax, m_nYMax, m_nZMax, m_nRudderMax, m_nUMax, m_nVMax,
+         m_nXMin, m_nYMin, m_nZMin, m_nRudderMin, m_nUMin, m_nVMin;
+
+    friend class wxJoystick;
+};
+
+//---------------------------------------------------------------------------
+// wxJoystickThread
+//---------------------------------------------------------------------------
+class wxJoystickThread : public wxThread
+{
+public:
+    wxJoystickThread(wxHIDJoystick* hid, int joystick);
+    void* Entry();
+    static void HIDCallback(void* target, IOReturn res, void* context, void* sender);
+
+private:
+    wxHIDJoystick*       m_hid;
+    int       m_joystick;
+    wxPoint   m_lastposition;
+    int       m_axe[wxJS_MAX_AXES];
+    int       m_buttons;
+    wxWindow* m_catchwin;
+    int       m_polling;
+
+    friend class wxJoystick;
+};
+
+//===========================================================================
+//  IMPLEMENTATION
+//===========================================================================
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// wxGetIntFromCFDictionary
+//
+// Helper function that gets a integer from a dictionary key
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+void wxGetIntFromCFDictionary(CFTypeRef cfDict, CFStringRef key, int* pOut)
+{
+        CFNumberGetValue(
+          (CFNumberRef) CFDictionaryGetValue((CFDictionaryRef) cfDict,
+                                              key),
+                        kCFNumberIntType, pOut);
+}
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// wxJoystick
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+IMPLEMENT_DYNAMIC_CLASS(wxJoystick, wxObject)
+
+//---------------------------------------------------------------------------
+// wxJoystick Constructor
+//
+// 1) Initializes member variables
+// 2) Attempts to create the native HID joystick implementation - if none
+//    could be found (no joysticks, etc.) then it sets it to NULL
+//---------------------------------------------------------------------------
+wxJoystick::wxJoystick(int joystick)
+    : m_joystick(joystick),
+      m_thread(NULL)
+{
+    m_hid = new wxHIDJoystick();
+
+    if (m_hid->Create(m_joystick+1)) //wxHIDDevice is 1-based while this is 0
+    {
+        m_thread = new wxJoystickThread(m_hid, m_joystick);
+        m_thread->Create();
+        m_thread->Run();
+    }
+    else
+    {
+        delete m_hid;
+        m_hid = NULL;
+    }
+}
+
+//---------------------------------------------------------------------------
+// wxJoystick Destructor
+//
+// Releases the capture of the thread, deletes it, and deletes
+// the native implementation.
+//---------------------------------------------------------------------------
+wxJoystick::~wxJoystick()
+{
+    ReleaseCapture();
+    if (m_thread)
+        m_thread->Delete();  // It's detached so it will delete itself
+
+    if (m_hid)
+        delete m_hid;
+}
+
+//---------------------------------------------------------------------------
+// wxJoystick::Get[XXX]Position
+//
+// Returns the value of an axis that was polled from the thread. In the
+// case of GetPosition returns the X and Y values in a wxPoint
+//---------------------------------------------------------------------------
+wxPoint wxJoystick::GetPosition() const
+{
+    wxPoint pos(wxDefaultPosition);
+    if (m_thread) pos = m_thread->m_lastposition;
+    return pos;
+}
+int wxJoystick::GetZPosition() const
+{
+    if (m_thread)
+        return m_thread->m_axe[wxJS_AXIS_Z];
+    return 0;
+}
+int wxJoystick::GetRudderPosition() const
+{
+    if (m_thread)
+        return m_thread->m_axe[wxJS_AXIS_RUDDER];
+    return 0;
+}
+int wxJoystick::GetUPosition() const
+{
+    if (m_thread)
+        return m_thread->m_axe[wxJS_AXIS_U];
+    return 0;
+}
+int wxJoystick::GetVPosition() const
+{
+    if (m_thread)
+        return m_thread->m_axe[wxJS_AXIS_V];
+    return 0;
+}
+
+//---------------------------------------------------------------------------
+// wxJoystick::GetButtonState
+//
+// Returns the state of the buttons in a bitmask as dictated by the
+// wx manual (the real work takes place in the thread, as always)
+//---------------------------------------------------------------------------
+int wxJoystick::GetButtonState() const
+{
+    if (m_thread)
+        return m_thread->m_buttons;
+    return 0;
+}
+
+//---------------------------------------------------------------------------
+// wxJoystick::IsOk
+//
+// Returns whether the joystick initialized successfully - in this case
+// if the native implementation doesn't exist (in constructor)
+//---------------------------------------------------------------------------
+bool wxJoystick::IsOk() const
+{
+    return m_hid != NULL;
+}
+
+//---------------------------------------------------------------------------
+// wxJoystick::Get[XXX](Id/Name)
+//
+// Simple accessors to the native HID implementation
+//---------------------------------------------------------------------------
+int wxJoystick::GetManufacturerId() const
+{
+    return m_hid->m_nManufacturerId;
+}
+
+int wxJoystick::GetProductId() const
+{
+    return m_hid->m_nProductId;
+}
+
+wxString wxJoystick::GetProductName() const
+{
+    return m_hid->m_szProductName;
+}
+
+//---------------------------------------------------------------------------
+// wxJoystick::GetNumberButtons
+// wxJoystick::GetNumberAxes
+//
+// Queries the joystick for an active number of buttons/axes.
+//
+// In the native HID implementation, the cookies:
+// 0-40     are the buttons of the joystick
+// 40-50    are the axes of the joystick
+//
+// These just query the native HID implementation as above.
+//---------------------------------------------------------------------------
+int wxJoystick::GetNumberButtons() const
+{
+    int nCount = 0;
+
+    for(int nIndex = 0; nIndex < 40; ++nIndex)
+    {
+        if(m_hid->HasElement(nIndex))
+            ++nCount;
+    }
+
+    return nCount;
+}
+int wxJoystick::GetNumberAxes() const
+{
+    int nCount = 0;
+
+    for(int nIndex = 40; nIndex < 50; ++nIndex)
+    {
+        if(m_hid->HasElement(nIndex))
+            ++nCount;
+    }
+
+    return nCount;
+}
+
+//---------------------------------------------------------------------------
+// wxJoystick::GetNumberJoysticks
+//
+// Gets the number of joysticks on the system. In HID that
+// is all devices with the kHIDUsage_GD_Joystick or kHIDUsage_GD_GamePad
+// identifiers.
+//---------------------------------------------------------------------------
+int wxJoystick::GetNumberJoysticks()
+{
+    return
+        wxHIDDevice::GetCount(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick) +
+        wxHIDDevice::GetCount(kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad);
+}
+
+//---------------------------------------------------------------------------
+// wxJoystick::SetCapture
+//
+// Stops sending events from the thread to the window set in
+// SetCapture and stops polling the joystick
+//---------------------------------------------------------------------------
+bool wxJoystick::SetCapture(wxWindow* win, int pollingFreq)
+{
+    if (m_thread)
+    {
+        m_thread->m_catchwin = win;
+        m_thread->m_polling = pollingFreq;
+        return true;
+    }
+    return false;
+}
+
+//---------------------------------------------------------------------------
+// wxJoystick::ReleaseCapture
+//
+// Stops sending events from the thread to the window set in
+// SetCapture and stops polling the joystick
+//---------------------------------------------------------------------------
+bool wxJoystick::ReleaseCapture()
+{
+    if (m_thread)
+    {
+        m_thread->m_catchwin = NULL;
+        m_thread->m_polling = 0;
+        return true;
+    }
+    return false;
+}
+
+//---------------------------------------------------------------------------
+// wxJoystick::Get[XXX]
+//
+// Gets the minimum and maximum values for each axis, returning 0 if the
+// axis doesn't exist.
+//---------------------------------------------------------------------------
+int wxJoystick::GetXMin() const
+{
+    return m_hid->m_nXMin;
+}
+
+int wxJoystick::GetYMin() const
+{
+    return m_hid->m_nYMin;
+}
+
+int wxJoystick::GetZMin() const
+{
+    return m_hid->m_nZMin;
+}
+
+int wxJoystick::GetRudderMin() const
+{
+    return m_hid->m_nRudderMin;
+}
+
+int wxJoystick::GetUMin() const
+{
+    return m_hid->m_nUMin;
+}
+
+int wxJoystick::GetVMin() const
+{
+    return m_hid->m_nVMin;
+}
+
+int wxJoystick::GetXMax() const
+{
+    return m_hid->m_nXMax;
+}
+
+int wxJoystick::GetYMax() const
+{
+    return m_hid->m_nYMax;
+}
+
+int wxJoystick::GetZMax() const
+{
+    return m_hid->m_nZMax;
+}
+
+int wxJoystick::GetRudderMax() const
+{
+    return m_hid->m_nRudderMax;
+}
+
+int wxJoystick::GetUMax() const
+{
+    return m_hid->m_nUMax;
+}
+
+int wxJoystick::GetVMax() const
+{
+    return m_hid->m_nVMax;
+}
+
+//---------------------------------------------------------------------------
+// wxJoystick::Get[XXX]
+//
+// Min/Max values for buttons, axes, etc.. Polling in this case is just
+// what the linux port has.
+//---------------------------------------------------------------------------
+int wxJoystick::GetMaxButtons() const
+{
+    return wxJS_MAX_BUTTONS;
+}
+
+int wxJoystick::GetMaxAxes() const
+{
+    return wxJS_MAX_AXES;
+}
+
+int wxJoystick::GetPollingMin() const
+{
+    return 10;
+}
+
+int wxJoystick::GetPollingMax() const
+{
+    return 1000;
+}
+
+//---------------------------------------------------------------------------
+// wxJoystick::Has[XXX]
+//
+// Just queries the native hid implementation if the cookie was found
+// when enumerating the cookies of the joystick device
+//---------------------------------------------------------------------------
+bool wxJoystick::HasZ() const
+{
+    return m_hid->HasElement(wxJS_AXIS_Z);
+}
+
+bool wxJoystick::HasRudder() const
+{
+    return m_hid->HasElement(wxJS_AXIS_RUDDER);
+}
+
+bool wxJoystick::HasU() const
+{
+    return m_hid->HasElement(wxJS_AXIS_U);
+}
+
+bool wxJoystick::HasV() const
+{
+    return m_hid->HasElement(wxJS_AXIS_V);
+}
+
+//---------------------------------------------------------------------------
+// UNSUPPORTED
+//---------------------------------------------------------------------------
+int wxJoystick::GetPOVPosition() const
+{
+    return -1;
+}
+
+int wxJoystick::GetPOVCTSPosition() const
+{
+    return -1;
+}
+
+int wxJoystick::GetMovementThreshold() const
+{
+    return 0;
+}
+
+void wxJoystick::SetMovementThreshold(int WXUNUSED(threshold))
+{
+}
+
+bool wxJoystick::HasPOV() const
+{
+    return false;
+}
+
+bool wxJoystick::HasPOV4Dir() const
+{
+    return false;
+}
+
+bool wxJoystick::HasPOVCTS() const
+{
+    return false;
+}
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// wxHIDJoystick
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+// wxHIDJoystick ctor
+//
+// Initializes the min/max members
+//---------------------------------------------------------------------------
+wxHIDJoystick::wxHIDJoystick() :
+ m_nXMax(0), m_nYMax(0), m_nZMax(0), m_nRudderMax(0), m_nUMax(0), m_nVMax(0),
+ m_nXMin(0), m_nYMin(0), m_nZMin(0), m_nRudderMin(0), m_nUMin(0), m_nVMin(0)
+{
+}
+
+//---------------------------------------------------------------------------
+// wxHIDJoystick dtor
+//
+// Nothing...
+//---------------------------------------------------------------------------
+wxHIDJoystick::~wxHIDJoystick()
+{
+}
+
+//---------------------------------------------------------------------------
+// wxHIDJoystick::Create
+//
+// Creates the native HID device (joysticks are of either
+// kHIDUsage_GD_Joystick or kHIDUsage_GD_GamePad)
+//---------------------------------------------------------------------------
+bool wxHIDJoystick::Create(int nWhich)
+{
+    int nJoysticks = GetCount(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick);
+
+    if (nWhich <= nJoysticks)
+        return wxHIDDevice::Create(kHIDPage_GenericDesktop,
+                                   kHIDUsage_GD_Joystick,
+                                   nWhich);
+    else
+        nWhich -= nJoysticks;
+
+    int nGamePads = GetCount(kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad);
+
+    if (nWhich <= nGamePads)
+        return wxHIDDevice::Create(kHIDPage_GenericDesktop,
+                                   kHIDUsage_GD_GamePad,
+                                   nWhich);
+    else
+    return false;
+}
+
+//---------------------------------------------------------------------------
+// wxHIDJoystick::BuildCookies
+// wxHIDJoystick::MakeCookies
+//
+// Sets up the cookies for the HID device (called from Create) - as
+// mentioned 0-40 are the buttons and 40-50 are the axes.
+//
+// MakeCookies is just a recursive function for each array within
+// BuildCookies.
+//---------------------------------------------------------------------------
+void wxHIDJoystick::BuildCookies(CFArrayRef Array)
+{
+    InitCookies(50, true);
+
+    //
+    // I wasted two hours of my life on this line :(
+    // accidently removed it during some source cleaning...
+    //
+    MakeCookies(Array);
+
+    //paranoid debugging stuff
+#if 0
+    for(int i = 0; i < 50; ++i)
+        wxPrintf(wxT("\nVAL #%i:[%i]"), i, m_pCookies[i]);
+#endif
+}//end buildcookies
+
+void wxHIDJoystick::MakeCookies(CFArrayRef Array)
+{
+    int i, nUsage, nPage;
+
+    for (i = 0; i < CFArrayGetCount(Array); ++i)
+    {
+        const void* ref = CFDictionaryGetValue(
+                (CFDictionaryRef)CFArrayGetValueAtIndex(Array, i),
+                CFSTR(kIOHIDElementKey)
+                                              );
+
+        if (ref != NULL)
+        {
+            MakeCookies((CFArrayRef) ref);
+    }
+        else
+        {
+            CFNumberGetValue(
+                (CFNumberRef)
+                    CFDictionaryGetValue(
+                        (CFDictionaryRef) CFArrayGetValueAtIndex(Array, i),
+                        CFSTR(kIOHIDElementUsageKey)
+                                        ),
+                kCFNumberIntType,
+                &nUsage    );
+
+            CFNumberGetValue(
+                (CFNumberRef)
+                    CFDictionaryGetValue(
+                        (CFDictionaryRef) CFArrayGetValueAtIndex(Array, i),
+                        CFSTR(kIOHIDElementUsagePageKey)
+                                        ),
+                kCFNumberIntType,
+                &nPage     );
+
+#if 0
+            wxLogSysError(wxT("[%i][%i]"), nUsage, nPage);
+#endif
+            if (nPage == kHIDPage_Button && nUsage <= 40)
+                AddCookieInQueue(CFArrayGetValueAtIndex(Array, i), nUsage-1 );
+            else if (nPage == kHIDPage_GenericDesktop)
+            {
+                //axis...
+                switch(nUsage)
+                {
+                    case kHIDUsage_GD_X:
+                        AddCookieInQueue(CFArrayGetValueAtIndex(Array, i), wxJS_AXIS_X);
+                        wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i),
+                                                 CFSTR(kIOHIDElementMaxKey),
+                                                 &m_nXMax);
+                        wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i),
+                                                 CFSTR(kIOHIDElementMinKey),
+                                                 &m_nXMin);
+                        break;
+                    case kHIDUsage_GD_Y:
+                        AddCookieInQueue(CFArrayGetValueAtIndex(Array, i), wxJS_AXIS_Y);
+                        wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i),
+                                                 CFSTR(kIOHIDElementMaxKey),
+                                                 &m_nYMax);
+                        wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i),
+                                                 CFSTR(kIOHIDElementMinKey),
+                                                 &m_nYMin);
+                        break;
+                    case kHIDUsage_GD_Z:
+                        AddCookieInQueue(CFArrayGetValueAtIndex(Array, i), wxJS_AXIS_Z);
+                        wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i),
+                                                 CFSTR(kIOHIDElementMaxKey),
+                                                 &m_nZMax);
+                        wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i),
+                                                 CFSTR(kIOHIDElementMinKey),
+                                                 &m_nZMin);
+                        break;
+                    default:
+                        break;
+                }
+            }
+            else if (nPage == kHIDPage_Simulation && nUsage == kHIDUsage_Sim_Rudder)
+            {
+                //rudder...
+                AddCookieInQueue(CFArrayGetValueAtIndex(Array, i), wxJS_AXIS_RUDDER );
+                wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i),
+                                         CFSTR(kIOHIDElementMaxKey),
+                                         &m_nRudderMax);
+                wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i),
+                                         CFSTR(kIOHIDElementMinKey),
+                                         &m_nRudderMin);
+            }
+        }
+    }
+}
+
+//---------------------------------------------------------------------------
+// wxHIDJoystick::Get[XXX]
+//
+// Simple accessors so that the HID callback and the thread procedure
+// can access members from wxHIDDevice (our parent here).
+//---------------------------------------------------------------------------
+IOHIDElementCookie* wxHIDJoystick::GetCookies()
+{   return m_pCookies;  }
+IOHIDQueueInterface** wxHIDJoystick::GetQueue()
+{   return m_ppQueue;   }
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// wxJoystickThread
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+// wxJoystickThread Constructor
+//
+// Just initializes members
+//---------------------------------------------------------------------------
+wxJoystickThread::wxJoystickThread(wxHIDJoystick* hid, int joystick)
+    : m_hid(hid),
+      m_joystick(joystick),
+      m_lastposition(127,127),
+      m_buttons(0),
+      m_catchwin(NULL),
+      m_polling(0)
+{
+    memset(m_axe, 0, sizeof(int) * wxJS_MAX_AXES);
+}
+
+//---------------------------------------------------------------------------
+// wxJoystickThread::Entry
+//
+// Thread procedure
+//
+// Runs a CFRunLoop for polling. Basically, it sets the HID queue to
+// call wxJoystickThread::HIDCallback in the context of this thread
+// when something changes on the device. It polls as long as the user
+// wants, or a certain amount if the user wants to "block". Note that
+// we don't actually block here since this is in a secondary thread.
+//---------------------------------------------------------------------------
+void* wxJoystickThread::Entry()
+{
+    CFRunLoopSourceRef pRLSource = NULL;
+
+    if ((*m_hid->GetQueue())->createAsyncEventSource(
+                    m_hid->GetQueue(), &pRLSource) != kIOReturnSuccess )
+    {
+        wxLogSysError(wxT("Couldn't create async event source"));
+        return NULL;
+    }
+
+    wxASSERT(pRLSource != NULL);
+
+    //attach runloop source to main run loop in thread
+    CFRunLoopRef pRL = CFRunLoopGetCurrent();
+    CFRunLoopAddSource(pRL, pRLSource, kCFRunLoopDefaultMode);
+    wxASSERT( CFRunLoopContainsSource(pRL, pRLSource, kCFRunLoopDefaultMode) );
+
+
+    if( (*m_hid->GetQueue())->setEventCallout(m_hid->GetQueue(),
+          wxJoystickThread::HIDCallback, this, this) != kIOReturnSuccess )
+    {
+        wxLogSysError(wxT("Could not set event callout for queue"));
+        return NULL;
+    }
+
+    if( (*m_hid->GetQueue())->start(m_hid->GetQueue()) != kIOReturnSuccess )
+    {
+        wxLogSysError(wxT("Could not start queue"));
+        return NULL;
+    }
+
+    double dTime;
+
+    while(true)
+    {
+        if (TestDestroy())
+            break;
+
+        if (m_polling)
+            dTime = 0.0001 * m_polling;
+        else
+            dTime = 0.0001 * 10;  // check at least every 10 msec in "blocking" case
+
+        //true just "handles and returns" - false forces it to stay the time
+        //amount
+#if 1
+        CFRunLoopRunInMode(kCFRunLoopDefaultMode, dTime, true);
+#else
+        IOReturn ret = NULL;
+        HIDCallback(this, ret, this, this);
+        Sleep(3000);
+#endif
+    }
+
+    wxASSERT( CFRunLoopContainsSource(pRL, pRLSource, kCFRunLoopDefaultMode) );
+
+    CFRunLoopRemoveSource(pRL, pRLSource, kCFRunLoopDefaultMode);
+    CFRelease(pRLSource);
+
+    return NULL;
+}
+
+//---------------------------------------------------------------------------
+// wxJoystickThread::HIDCallback (static)
+//
+// Callback for the native HID device when it recieves input.
+//
+// This is where the REAL dirty work gets done.
+//
+// 1) Loops through each event the queue has recieved
+// 2) First, checks if the thread that is running the loop for
+//    the polling has ended - if so it breaks out
+// 3) Next, it checks if there was an error getting this event from
+//    the HID queue, if there was, it logs an error and returns
+// 4) Now it does the real dirty work by getting the button states
+//    from cookies 0-40 and axes positions/states from cookies 40-50
+//    in the native HID device by quering cookie values.
+// 5) Sends the event to the polling window (if any)
+// 6) Gets the next event and goes back to (1)
+//---------------------------------------------------------------------------
+/*static*/ void wxJoystickThread::HIDCallback(void* WXUNUSED(target),
+                                              IOReturn WXUNUSED(res),
+                                              void* context,
+                                              void* WXUNUSED(sender))
+{
+    IOHIDEventStruct hidevent;
+    AbsoluteTime bogustime = {0,0};
+    IOReturn ret;
+    wxJoystickThread* pThis = (wxJoystickThread*) context;
+    wxHIDJoystick* m_hid = pThis->m_hid;
+
+    //Get the "first" event from the queue
+    //bogustime tells it we don't care at what time to start
+    //where it gets the next from
+    ret = (*m_hid->GetQueue())->getNextEvent(m_hid->GetQueue(),
+                    &hidevent, bogustime, 0);
+
+    while (ret != kIOReturnUnderrun)
+    {
+        if (pThis->TestDestroy())
+            break;
+
+        if(ret != kIOReturnSuccess)
+        {
+            wxLogSysError(wxString::Format(wxT("wxJoystick Error:[%i]"), ret));
+            return;
+        }
+
+        wxJoystickEvent wxevent;
+
+        //Find the cookie that changed
+        int nIndex = 0;
+        IOHIDElementCookie* pCookies = m_hid->GetCookies();
+        while(nIndex < 50)
+        {
+            if(hidevent.elementCookie == pCookies[nIndex])
+                break;
+
+            ++nIndex;
+        }
+
+        //debugging stuff
+#if 0
+        if(nIndex == 50)
+        {
+            wxLogSysError(wxString::Format(wxT("wxJoystick Out Of Bounds Error")));
+            break;
+        }
+#endif
+
+        //is the cookie a button?
+        if (nIndex < 40)
+        {
+            if (hidevent.value)
+            {
+                pThis->m_buttons |= (1 << nIndex);
+                wxevent.SetEventType(wxEVT_JOY_BUTTON_DOWN);
+            }
+            else
+            {
+                pThis->m_buttons &= ~(1 << nIndex);
+                wxevent.SetEventType(wxEVT_JOY_BUTTON_UP);
+            }
+
+            wxevent.SetButtonChange(nIndex+1);
+        }
+        else if (nIndex == wxJS_AXIS_X)
+        {
+            pThis->m_lastposition.x = hidevent.value;
+            wxevent.SetEventType(wxEVT_JOY_MOVE);
+            pThis->m_axe[0] = hidevent.value;
+        }
+        else if (nIndex == wxJS_AXIS_Y)
+        {
+            pThis->m_lastposition.y = hidevent.value;
+            wxevent.SetEventType(wxEVT_JOY_MOVE);
+            pThis->m_axe[1] = hidevent.value;
+        }
+        else if (nIndex == wxJS_AXIS_Z)
+        {
+            wxevent.SetEventType(wxEVT_JOY_ZMOVE);
+            pThis->m_axe[2] = hidevent.value;
+        }
+        else
+            wxevent.SetEventType(wxEVT_JOY_MOVE);
+
+        Nanoseconds timestamp = AbsoluteToNanoseconds(hidevent.timestamp);
+
+        wxULongLong llTime(timestamp.hi, timestamp.lo);
+
+        llTime /= 1000000;
+
+        wxevent.SetTimestamp(llTime.GetValue());
+        wxevent.SetJoystick(pThis->m_joystick);
+        wxevent.SetButtonState(pThis->m_buttons);
+        wxevent.SetPosition(pThis->m_lastposition);
+        wxevent.SetZPosition(pThis->m_axe[2]);
+        wxevent.SetEventObject(pThis->m_catchwin);
+
+        if (pThis->m_catchwin)
+            pThis->m_catchwin->AddPendingEvent(wxevent);
+
+        ret = (*m_hid->GetQueue())->getNextEvent(m_hid->GetQueue(),
+                    &hidevent, bogustime, 0);
+    }
+}
+
+#endif // wxUSE_JOYSTICK 
diff --git a/src/mac/core/stdpaths_cf.cpp b/src/mac/core/stdpaths_cf.cpp
new file mode 100644 (file)
index 0000000..69e524f
--- /dev/null
@@ -0,0 +1,217 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name:        mac/corefoundation/stdpaths.cpp
+// Purpose:     wxStandardPaths implementation for CoreFoundation systems
+// Author:      David Elliott
+// Modified by:
+// Created:     2004-10-27
+// RCS-ID:      $Id$
+// Copyright:   (c) 2004 David Elliott <dfe@cox.net>
+// Licence:     wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+#include "wx/wxprec.h"
+
+#if wxUSE_STDPATHS
+
+#ifndef WX_PRECOMP
+    #include "wx/intl.h"
+#endif //ndef WX_PRECOMP
+
+#include "wx/stdpaths.h"
+#include "wx/filename.h"
+#ifdef __WXMAC__
+#include "wx/mac/private.h"
+#endif
+#include "wx/mac/corefoundation/cfstring.h"
+
+#include <CoreFoundation/CFBundle.h>
+#include <CoreFoundation/CFURL.h>
+
+#define kDefaultPathStyle kCFURLPOSIXPathStyle
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// wxStandardPathsCF ctors/dtor
+// ----------------------------------------------------------------------------
+
+wxStandardPathsCF::wxStandardPathsCF()
+                 : m_bundle(CFBundleGetMainBundle())
+{
+    CFRetain(m_bundle);
+    UseAppInfo(AppInfo_AppName | AppInfo_VendorName);
+}
+
+wxStandardPathsCF::wxStandardPathsCF(wxCFBundleRef bundle)
+                 : m_bundle(bundle)
+{
+    CFRetain(m_bundle);
+    UseAppInfo(AppInfo_AppName | AppInfo_VendorName);
+}
+
+wxStandardPathsCF::~wxStandardPathsCF()
+{
+    CFRelease(m_bundle);
+}
+
+// ----------------------------------------------------------------------------
+// wxStandardPathsCF Mac-specific methods
+// ----------------------------------------------------------------------------
+
+void wxStandardPathsCF::SetBundle(wxCFBundleRef bundle)
+{
+    CFRetain(bundle);
+    CFRelease(m_bundle);
+    m_bundle = bundle;
+}
+
+// ----------------------------------------------------------------------------
+// generic functions in terms of which the other ones are implemented
+// ----------------------------------------------------------------------------
+
+static wxString BundleRelativeURLToPath(CFURLRef relativeURL)
+{
+    CFURLRef absoluteURL = CFURLCopyAbsoluteURL(relativeURL);
+    wxCHECK_MSG(absoluteURL, wxEmptyString, wxT("Failed to resolve relative URL to absolute URL"));
+    CFStringRef cfStrPath = CFURLCopyFileSystemPath(absoluteURL,kDefaultPathStyle);
+    CFRelease(absoluteURL);
+    return wxCFStringRef(cfStrPath).AsString(wxLocale::GetSystemEncoding());
+}
+
+wxString wxStandardPathsCF::GetFromFunc(wxCFURLRef (*func)(wxCFBundleRef)) const
+{
+    wxCHECK_MSG(m_bundle, wxEmptyString,
+                wxT("wxStandardPaths for CoreFoundation only works with bundled apps"));
+    CFURLRef relativeURL = (*func)(m_bundle);
+    wxCHECK_MSG(relativeURL, wxEmptyString, wxT("Couldn't get URL"));
+    wxString ret(BundleRelativeURLToPath(relativeURL));
+    CFRelease(relativeURL);
+    return ret;
+}
+
+wxString wxStandardPathsCF::GetDocumentsDir() const
+{
+#if defined( __WXMAC__ ) && !defined(__WXOSX_IPHONE__)
+    return wxMacFindFolderNoSeparator
+        (
+        kUserDomain,
+        kDocumentsFolderType,
+        kCreateFolder
+        );
+#else
+    return wxFileName::GetHomeDir() + wxT("/Documents");
+#endif
+}
+
+// ----------------------------------------------------------------------------
+// wxStandardPathsCF public API
+// ----------------------------------------------------------------------------
+
+wxString wxStandardPathsCF::GetConfigDir() const
+{
+#if defined( __WXMAC__ ) && !defined(__WXOSX_IPHONE__)
+    return wxMacFindFolder((short)kLocalDomain, kPreferencesFolderType, kCreateFolder);
+#else
+    return wxT("/Library/Preferences");
+#endif
+}
+
+wxString wxStandardPathsCF::GetUserConfigDir() const
+{
+#if defined( __WXMAC__ ) && !defined(__WXOSX_IPHONE__)
+    return wxMacFindFolder((short)kUserDomain, kPreferencesFolderType, kCreateFolder);
+#else
+    return wxFileName::GetHomeDir() + wxT("/Library/Preferences");
+#endif
+}
+
+wxString wxStandardPathsCF::GetDataDir() const
+{
+    return GetFromFunc(CFBundleCopySharedSupportURL);
+}
+
+wxString wxStandardPathsCF::GetExecutablePath() const
+{
+#ifdef __WXMAC__
+#if 1
+    return GetFromFunc(CFBundleCopyBundleURL);
+#else
+    // TODO remove if cf implementation ok
+    ProcessInfoRec processinfo;
+    ProcessSerialNumber procno ;
+#ifdef __LP64__
+    FSRef  fsRef;
+#else
+    FSSpec fsSpec;
+#endif
+    
+    procno.highLongOfPSN = 0 ;
+    procno.lowLongOfPSN = kCurrentProcess ;
+    processinfo.processInfoLength = sizeof(ProcessInfoRec);
+    processinfo.processName = NULL;
+#ifdef __LP64__
+    processinfo.processAppRef = &fsRef;
+#else
+    processinfo.processAppSpec = &fsSpec;
+#endif
+    
+    GetProcessInformation( &procno , &processinfo ) ;
+#ifdef __LP64__
+    return wxMacFSRefToPath(&fsRef);
+#else
+    return wxMacFSSpec2MacFilename(&fsSpec);
+#endif
+#endif
+    
+#else
+    return wxStandardPathsBase::GetExecutablePath();
+#endif
+}
+
+wxString wxStandardPathsCF::GetLocalDataDir() const
+{
+#if defined( __WXMAC__ ) && !defined(__WXOSX_IPHONE__)
+    return AppendAppInfo(wxMacFindFolder((short)kLocalDomain, kApplicationSupportFolderType, kCreateFolder));
+#else
+    return AppendAppInfo(wxT("/Library/Application Support"));
+#endif
+}
+
+wxString wxStandardPathsCF::GetUserDataDir() const
+{
+#if defined( __WXMAC__ ) && !defined(__WXOSX_IPHONE__)
+    return AppendAppInfo(wxMacFindFolder((short)kUserDomain, kApplicationSupportFolderType, kCreateFolder));
+#else
+    return AppendAppInfo(wxFileName::GetHomeDir() + _T("/Library/Application Support"));
+#endif
+}
+
+wxString wxStandardPathsCF::GetPluginsDir() const
+{
+    return GetFromFunc(CFBundleCopyBuiltInPlugInsURL);
+}
+
+wxString wxStandardPathsCF::GetResourcesDir() const
+{
+    return GetFromFunc(CFBundleCopyResourcesDirectoryURL);
+}
+
+wxString
+wxStandardPathsCF::GetLocalizedResourcesDir(const wxString& lang,
+                                            ResourceCat category) const
+{
+    return wxStandardPathsBase::
+            GetLocalizedResourcesDir(lang, category) + _T(".lproj");
+}
+
+#endif // wxUSE_STDPATHS
diff --git a/src/mac/core/strconv_cf.cpp b/src/mac/core/strconv_cf.cpp
new file mode 100644 (file)
index 0000000..e68d8e4
--- /dev/null
@@ -0,0 +1,228 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        src/mac/corefoundation/strconv.cpp
+// Purpose:     Unicode conversion classes
+// Author:      David Elliott
+// Modified by:
+// Created:     2007-07-06
+// RCS-ID:      $Id$
+// Copyright:   (c) 2007 David Elliott
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifndef WX_PRECOMP
+    #include "wx/string.h"
+#endif
+
+#include "wx/strconv.h"
+#include "wx/fontmap.h"
+
+#ifdef __DARWIN__
+
+#include "wx/mac/corefoundation/private/strconv_cf.h"
+#include "wx/mac/corefoundation/cfref.h"
+
+
+// ============================================================================
+// CoreFoundation conversion classes
+// ============================================================================
+
+/* Provide factory functions for unit tests.  Not in any header.  Do not
+ * assume ABI compatibility even within a given wxWidgets release.
+ */
+
+WXDLLIMPEXP_BASE wxMBConv* new_wxMBConv_cf( const char* name)
+{
+    wxMBConv_cf *result = new wxMBConv_cf(name);
+    if(!result->IsOk())
+    {
+        delete result;
+        return NULL;
+    }
+    else
+        return result;
+}
+
+WXDLLIMPEXP_BASE wxMBConv* new_wxMBConv_cf(wxFontEncoding encoding)
+{
+    wxMBConv_cf *result = new wxMBConv_cf(encoding);
+    if(!result->IsOk())
+    {
+        delete result;
+        return NULL;
+    }
+    else
+        return result;
+}
+
+// Provide a constant for the wchat_t encoding used by the host platform.
+#ifdef WORDS_BIGENDIAN
+    static const CFStringEncoding wxCFStringEncodingWcharT = kCFStringEncodingUTF32BE;
+#else
+    static const CFStringEncoding wxCFStringEncodingWcharT = kCFStringEncodingUTF32LE;
+#endif
+
+    size_t wxMBConv_cf::ToWChar(wchar_t * dst, size_t dstSize, const char * src, size_t srcSize) const
+    {
+        wxCHECK(src, wxCONV_FAILED);
+
+        /* NOTE: This is wrong if the source encoding has an element size
+         * other than char (e.g. it's kCFStringEncodingUnicode)
+         * If the user specifies it, it's presumably right though.
+         * Right now we don't support UTF-16 in anyway since wx can do a better job.
+         */
+        if(srcSize == wxNO_LEN)
+            srcSize = strlen(src) + 1;
+
+        // First create the temporary CFString
+        wxCFRef<CFStringRef> theString( CFStringCreateWithBytes (
+                                                NULL, //the allocator
+                                                (const UInt8*)src,
+                                                srcSize,
+                                                m_encoding,
+                                                false //no BOM/external representation
+                                                ));
+
+        wxCHECK(theString != NULL, wxCONV_FAILED);
+
+        /* NOTE: The string content includes the NULL element if the source string did
+         * That means we have to do nothing special because the destination will have
+         * the NULL element iff the source did and the NULL element will be included
+         * in the count iff it was included in the source count.
+         */
+
+
+/* If we're compiling against Tiger headers we can support direct conversion
+ * to UTF32.  If we are then run against a pre-Tiger system, the encoding
+ * won't be available so we'll defer to the string->UTF-16->UTF-32 conversion.
+ */
+        if(CFStringIsEncodingAvailable(wxCFStringEncodingWcharT))
+        {
+            CFRange fullStringRange = CFRangeMake(0, CFStringGetLength(theString));
+            CFIndex usedBufLen;
+
+            CFIndex charsConverted = CFStringGetBytes(
+                    theString,
+                    fullStringRange,
+                    wxCFStringEncodingWcharT,
+                    0,
+                    false,
+                    // if dstSize is 0 then pass NULL to get required length in usedBufLen
+                    dstSize != 0?(UInt8*)dst:NULL,
+                    dstSize * sizeof(wchar_t),
+                    &usedBufLen);
+
+            // charsConverted is > 0 iff conversion succeeded
+            if(charsConverted <= 0)
+                return wxCONV_FAILED;
+
+            /* usedBufLen is the number of bytes written, so we divide by
+             * sizeof(wchar_t) to get the number of elements written.
+             */
+            wxASSERT( (usedBufLen % sizeof(wchar_t)) == 0 );
+
+            // CFStringGetBytes does exactly the right thing when buffer
+            // pointer is NULL and returns the number of bytes required
+            return usedBufLen / sizeof(wchar_t);
+        }
+        else
+        {
+            // NOTE: Includes NULL iff source did
+            /* NOTE: This is an approximation.  The eventual UTF-32 will    
+             * possibly have less elements but certainly not more.
+             */
+            size_t returnSize = CFStringGetLength(theString);
+    
+            if (dstSize == 0 || dst == NULL)
+            {
+                return returnSize;
+            }
+
+            // Convert the entire string.. too hard to figure out how many UTF-16 we'd need
+            // for an undersized UTF-32 destination buffer.
+            CFRange fullStringRange = CFRangeMake(0, CFStringGetLength(theString));
+            UniChar *szUniCharBuffer = new UniChar[fullStringRange.length];
+    
+            CFStringGetCharacters(theString, fullStringRange, szUniCharBuffer);
+    
+            wxMBConvUTF16 converter;
+            returnSize = converter.ToWChar( dst, dstSize, (const char*)szUniCharBuffer, fullStringRange.length );
+            delete [] szUniCharBuffer;
+    
+            return returnSize;
+        }
+        // NOTREACHED
+    }
+
+    size_t wxMBConv_cf::FromWChar(char *dst, size_t dstSize, const wchar_t *src, size_t srcSize) const
+    {
+        wxCHECK(src, wxCONV_FAILED);
+
+        if(srcSize == wxNO_LEN)
+            srcSize = wxStrlen(src) + 1;
+
+        // Temporary CFString
+        wxCFRef<CFStringRef> theString;
+
+/* If we're compiling against Tiger headers we can support direct conversion
+ * from UTF32.  If we are then run against a pre-Tiger system, the encoding
+ * won't be available so we'll defer to the UTF-32->UTF-16->string conversion.
+ */
+        if(CFStringIsEncodingAvailable(wxCFStringEncodingWcharT))
+        {
+            theString = wxCFRef<CFStringRef>(CFStringCreateWithBytes(
+                    kCFAllocatorDefault,
+                    (UInt8*)src,
+                    srcSize * sizeof(wchar_t),
+                    wxCFStringEncodingWcharT,
+                    false));
+        }
+        else
+        {
+            wxMBConvUTF16 converter;
+            size_t cbUniBuffer = converter.FromWChar( NULL, 0, src, srcSize );
+            wxASSERT(cbUniBuffer % sizeof(UniChar));
+
+            // Will be free'd by kCFAllocatorMalloc when CFString is released
+            UniChar *tmpUniBuffer = (UniChar*)malloc(cbUniBuffer);
+
+            cbUniBuffer = converter.FromWChar( (char*) tmpUniBuffer, cbUniBuffer, src, srcSize );
+            wxASSERT(cbUniBuffer % sizeof(UniChar));
+
+            theString = wxCFRef<CFStringRef>(CFStringCreateWithCharactersNoCopy(
+                        kCFAllocatorDefault,
+                        tmpUniBuffer,
+                        cbUniBuffer / sizeof(UniChar),
+                        kCFAllocatorMalloc
+                    ));
+
+        }
+
+        wxCHECK(theString != NULL, wxCONV_FAILED);
+
+        CFIndex usedBufLen;
+
+        CFIndex charsConverted = CFStringGetBytes(
+                theString, 
+                CFRangeMake(0, CFStringGetLength(theString)),
+                m_encoding,
+                0, // FAIL on unconvertible characters
+                false, // not an external representation
+                // if dstSize is 0 then pass NULL to get required length in usedBufLen
+                (dstSize != 0)?(UInt8*)dst:NULL,
+                dstSize,
+                &usedBufLen
+            );
+
+        // charsConverted is > 0 iff conversion succeeded
+        if(charsConverted <= 0)
+            return wxCONV_FAILED;
+
+        return usedBufLen;
+    }
+
+#endif // __DARWIN__
+
+
diff --git a/src/mac/core/utilsexc_base.cpp b/src/mac/core/utilsexc_base.cpp
new file mode 100644 (file)
index 0000000..377b246
--- /dev/null
@@ -0,0 +1,229 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        mac/corefoundation/utilsexc_base.cpp
+// Purpose:     wxMacLaunch
+// Author:      Ryan Norton
+// Modified by:
+// Created:     2005-06-21
+// RCS-ID:      $Id$
+// Copyright:   (c) Ryan Norton
+// Licence:     wxWindows licence
+// Notes:       Source was originally in utilsexc_cf.cpp,1.6 then moved
+//              to totally unrelated hid.cpp,1.8.
+/////////////////////////////////////////////////////////////////////////////
+
+//===========================================================================
+//  DECLARATIONS
+//===========================================================================
+
+//---------------------------------------------------------------------------
+// Pre-compiled header stuff
+//---------------------------------------------------------------------------
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+// WX includes
+#ifndef WX_PRECOMP
+    #include "wx/string.h"
+    #include "wx/log.h"
+    #include "wx/intl.h"
+    #include "wx/utils.h"
+    #include "wx/wxcrt.h"
+#endif // WX_PRECOMP
+
+// Mac Includes
+#include <CoreFoundation/CoreFoundation.h>
+#ifndef __WXOSX_IPHONE__
+#include <ApplicationServices/ApplicationServices.h>
+#endif
+
+// More WX Includes
+#include "wx/filename.h"
+#include "wx/mac/corefoundation/cfstring.h"
+
+// Default path style
+#define kDefaultPathStyle kCFURLPOSIXPathStyle
+
+//===========================================================================
+//  IMPLEMENTATION
+//===========================================================================
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+//    wxMacLaunch
+//
+// argv is the command line split up, with the application path first
+// flags are the flags from wxExecute
+// process is the process passed from wxExecute for pipe streams etc.
+// returns -1 on error for wxEXEC_SYNC and 0 on error for wxEXEC_ASYNC
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+bool wxMacLaunch(char **argv)
+{
+    // Obtains the number of arguments for determining the size of
+    // the CFArray used to hold them
+    CFIndex cfiCount = 0;
+    for(char** argvcopy = argv; *argvcopy != NULL ; ++argvcopy)
+    {
+        ++cfiCount;
+    }
+
+    // If there is not a single argument then there is no application
+    // to launch
+    if(cfiCount == 0)
+    {
+        wxLogDebug(wxT("wxMacLaunch No file to launch!"));
+        return false ;
+    }
+
+    // Path to bundle
+    wxString path = *argv++;
+
+    // Create a CFURL for the application path
+    // Created this way because we are opening a bundle which is a directory
+    CFURLRef cfurlApp =
+        CFURLCreateWithFileSystemPath(
+            kCFAllocatorDefault,
+            wxCFStringRef(path),
+            kDefaultPathStyle,
+            true); //false == not a directory
+
+    // Check for error from the CFURL
+    if(!cfurlApp)
+    {
+        wxLogDebug(wxT("wxMacLaunch Can't open path: %s"), path.c_str());
+        return false ;
+    }
+
+    // Create a CFBundle from the CFURL created earlier
+    CFBundleRef cfbApp = CFBundleCreate(kCFAllocatorDefault, cfurlApp);
+
+    // Check to see if CFBundleCreate returned an error,
+    // and if it did this was an invalid bundle or not a bundle
+    // at all (maybe a simple directory etc.)
+    if(!cfbApp)
+    {
+        wxLogDebug(wxT("wxMacLaunch Bad bundle: %s"), path.c_str());
+        CFRelease(cfurlApp);
+        return false ;
+    }
+
+    // Get the bundle type and make sure its an 'APPL' bundle
+    // Otherwise we're dealing with something else here...
+    UInt32 dwBundleType, dwBundleCreator;
+    CFBundleGetPackageInfo(cfbApp, &dwBundleType, &dwBundleCreator);
+    if(dwBundleType != 'APPL')
+    {
+        wxLogDebug(wxT("wxMacLaunch Not an APPL bundle: %s"), path.c_str());
+        CFRelease(cfbApp);
+        CFRelease(cfurlApp);
+        return false ;
+    }
+
+    // Create a CFArray for dealing with the command line
+    // arguments to the bundle
+    CFMutableArrayRef cfaFiles = CFArrayCreateMutable(kCFAllocatorDefault,
+                                    cfiCount-1, &kCFTypeArrayCallBacks);
+    if(!cfaFiles) //This should never happen
+    {
+        wxLogDebug(wxT("wxMacLaunch Could not create CFMutableArray"));
+        CFRelease(cfbApp);
+        CFRelease(cfurlApp);
+        return false ;
+    }
+
+    // Loop through command line arguments to the bundle,
+    // turn them into CFURLs and then put them in cfaFiles
+    // For use to launch services call
+        for( ; *argv != NULL ; ++argv)
+        {
+        // Check for '<' as this will ring true for
+        // CFURLCreateWithString but is generally not considered
+        // typical on mac but is usually passed here from wxExecute
+        if (wxStrcmp(*argv, wxT("<")) == 0)
+            continue;
+
+
+        CFURLRef cfurlCurrentFile;    // CFURL to hold file path
+        wxFileName argfn(*argv);     // Filename for path
+
+        if(argfn.DirExists())
+        {
+            // First, try creating as a directory
+            cfurlCurrentFile = CFURLCreateWithFileSystemPath(
+                                kCFAllocatorDefault,
+                                wxCFStringRef(*argv),
+                                kDefaultPathStyle,
+                                true); //true == directory
+        }
+        else if(argfn.FileExists())
+        {
+            // And if it isn't a directory try creating it
+            // as a regular file
+            cfurlCurrentFile = CFURLCreateWithFileSystemPath(
+                                kCFAllocatorDefault,
+                                wxCFStringRef(*argv),
+                                kDefaultPathStyle,
+                                false); //false == regular file
+        }
+        else
+        {
+            // Argument did not refer to
+            // an entry in the local filesystem,
+            // so try creating it through CFURLCreateWithString
+            cfurlCurrentFile = CFURLCreateWithString(
+                                kCFAllocatorDefault,
+                                wxCFStringRef(*argv),
+                                NULL);
+        }
+
+        // Continue in the loop if the CFURL could not be created
+        if(!cfurlCurrentFile)
+        {
+            wxLogDebug(
+                wxT("wxMacLaunch Could not create CFURL for argument:%s"),
+                *argv);
+            continue;
+        }
+
+        // Add the valid CFURL to the argument array and then
+        // release it as the CFArray adds a ref count to it
+            CFArrayAppendValue(
+                cfaFiles,
+                cfurlCurrentFile
+                            );
+            CFRelease(cfurlCurrentFile); // array has retained it
+        }
+
+    // Create a LSLaunchURLSpec for use with LSOpenFromURLSpec
+    // Note that there are several flag options (launchFlags) such
+    // as kLSLaunchDontSwitch etc. and maybe we could be more
+    // picky about the flags we choose
+    LSLaunchURLSpec launchspec;
+    launchspec.appURL = cfurlApp;
+    launchspec.itemURLs = cfaFiles;
+    launchspec.passThruParams = NULL; //AEDesc*
+    launchspec.launchFlags = kLSLaunchDefaults;
+    launchspec.asyncRefCon = NULL;
+
+    // Finally, call LSOpenFromURL spec with our arguments
+    // 2nd parameter is a pointer to a CFURL that gets
+    // the actual path launched by the function
+    OSStatus status = LSOpenFromURLSpec(&launchspec, NULL);
+
+    // Cleanup corefoundation references
+    CFRelease(cfbApp);
+    CFRelease(cfurlApp);
+    CFRelease(cfaFiles);
+
+    // Check for error from LSOpenFromURLSpec
+    if(status != noErr)
+    {
+        wxLogDebug(wxT("wxMacLaunch LSOpenFromURLSpec Error: %d"),
+                   (int)status);
+        return false ;
+    }
+
+    // No error from LSOpenFromURLSpec, so app was launched
+    return true ;
+}
+
diff --git a/src/mac/core/utilsexc_cf.cpp b/src/mac/core/utilsexc_cf.cpp
new file mode 100644 (file)
index 0000000..2d95454
--- /dev/null
@@ -0,0 +1,118 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        src/mac/corefoundation/utilsexec_cf.cpp
+// Purpose:     Execution-related utilities for Darwin
+// Author:      David Elliott, Ryan Norton (wxMacExecute)
+// Modified by: Stefan Csomor (added necessary wxT for unicode builds)
+// Created:     2004-11-04
+// RCS-ID:      $Id$
+// Copyright:   (c) David Elliott, Ryan Norton
+// Licence:     wxWindows licence
+// Notes:       This code comes from src/mac/carbon/utilsexc.cpp,1.11
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/wxprec.h"
+#ifndef WX_PRECOMP
+    #include "wx/log.h"
+    #include "wx/utils.h"
+#endif //ndef WX_PRECOMP
+#include "wx/unix/execute.h"
+#include "wx/stdpaths.h"
+#include "wx/app.h"
+#include "wx/apptrait.h"
+#include "wx/thread.h"
+#include "wx/process.h"
+
+#include <sys/wait.h>
+
+#include <CoreFoundation/CFSocket.h>
+
+/*!
+    Called due to source signal detected by the CFRunLoop.
+    This is nearly identical to the wxGTK equivalent.
+ */
+extern "C" void WXCF_EndProcessDetector(CFSocketRef s,
+                                        CFSocketCallBackType WXUNUSED(callbackType),
+                                        CFDataRef WXUNUSED(address),
+                                        void const *WXUNUSED(data),
+                                        void *info)
+{
+    /*
+        Either our pipe was closed or the process ended successfully.  Either way,
+        we're done.  It's not if waitpid is going to magically succeed when
+        we get fired again.  CFSocketInvalidate closes the fd for us and also
+        invalidates the run loop source for us which should cause it to
+        release the CFSocket (thus causing it to be deallocated) and remove
+        itself from the runloop which should release it and cause it to also
+        be deallocated.  Of course, it's possible the RunLoop hangs onto
+        one or both of them by retaining/releasing them within its stack
+        frame.  However, that shouldn't be depended on.  Assume that s is
+        deallocated due to the following call.
+     */
+    CFSocketInvalidate(s);
+
+    // Now tell wx that the process has ended.
+    wxHandleProcessTermination(static_cast<wxEndProcessData *>(info));
+}
+
+/*!
+    Implements the GUI-specific AddProcessCallback() for both wxMac and
+    wxCocoa using the CFSocket/CFRunLoop API which is available to both.
+    Takes advantage of the fact that sockets on UNIX are just regular
+    file descriptors and thus even a non-socket file descriptor can
+    apparently be used with CFSocket so long as you only tell CFSocket
+    to do things with it that would be valid for a non-socket fd.
+ */
+int wxGUIAppTraits::AddProcessCallback(wxEndProcessData *proc_data, int fd)
+{
+    static int s_last_tag = 0;
+    CFSocketContext context =
+    {   0
+    ,   static_cast<void*>(proc_data)
+    ,   NULL
+    ,   NULL
+    ,   NULL
+    };
+    CFSocketRef cfSocket = CFSocketCreateWithNative(kCFAllocatorDefault,fd,kCFSocketReadCallBack,&WXCF_EndProcessDetector,&context);
+    if(cfSocket == NULL)
+    {
+        wxLogError(wxT("Failed to create socket for end process detection"));
+        return 0;
+    }
+    CFRunLoopSourceRef runLoopSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, cfSocket, /*highest priority:*/0);
+    if(runLoopSource == NULL)
+    {
+        wxLogError(wxT("Failed to create CFRunLoopSource from CFSocket for end process detection"));
+        // closes the fd.. we can't really stop it, nor do we necessarily want to.
+        CFSocketInvalidate(cfSocket);
+        CFRelease(cfSocket);
+        return 0;
+    }
+    // Now that the run loop source has the socket retained and we no longer
+    // need to refer to it within this method, we can release it.
+    CFRelease(cfSocket);
+
+    CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);
+    // Now that the run loop has the source retained we can release it.
+    CFRelease(runLoopSource);
+
+    /*
+        Feed wx some bullshit.. we don't use it since CFSocket helpfully passes
+        itself into our callback and that's enough to be able to
+        CFSocketInvalidate it which is all we need to do to get everything we
+        just created to be deallocated.
+     */
+    return ++s_last_tag;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+// NOTE: This doesn't really belong here but this was a handy file to
+// put it in because it's already compiled for wxCocoa and wxMac GUI lib.
+#if wxUSE_STDPATHS
+static wxStandardPathsCF gs_stdPaths;
+wxStandardPathsBase& wxGUIAppTraits::GetStandardPaths()
+{
+    return gs_stdPaths;
+}
+#endif
+