X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/af717fa87a47084b4faa3d6e5dcabc6cdf3ff36f..e4dd1e19a281da5d1e23b12fd76c9fc242bcb1d6:/src/mac/corefoundation/strconv_cf.cpp diff --git a/src/mac/corefoundation/strconv_cf.cpp b/src/mac/corefoundation/strconv_cf.cpp new file mode 100644 index 0000000000..94cb8f34af --- /dev/null +++ b/src/mac/corefoundation/strconv_cf.cpp @@ -0,0 +1,208 @@ +///////////////////////////////////////////////////////////////////////////// +// 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 +// ============================================================================ + + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 +// 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 + +#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 */ + + 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 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 MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 + 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 +#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 */ + { + // 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 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 MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 + if(CFStringIsEncodingAvailable(wxCFStringEncodingWcharT)) + { + theString = wxCFRef(CFStringCreateWithBytes( + kCFAllocatorDefault, + (UInt8*)src, + srcSize * sizeof(wchar_t), + wxCFStringEncodingWcharT, + false)); + } + else +#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 */ + { + 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(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__ + +