--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// 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 ;
+}
--- /dev/null
+/* -------------------------------------------------------------------------
+ * 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
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// 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__
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// 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
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////
+// 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
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// 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__
+
+
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// 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 ;
+}
+
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// 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
+