1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/corefoundation/strconv.cpp
3 // Purpose: Unicode conversion classes
4 // Author: David Elliott
8 // Copyright: (c) 2007 David Elliott
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
16 #include "wx/string.h"
19 #include "wx/strconv.h"
20 #include "wx/fontmap.h"
24 #include "wx/mac/corefoundation/private/strconv_cf.h"
25 #include "wx/mac/corefoundation/cfref.h"
28 // ============================================================================
29 // CoreFoundation conversion classes
30 // ============================================================================
33 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
34 // Provide a constant for the wchat_t encoding used by the host platform.
35 #ifdef WORDS_BIGENDIAN
36 static const CFStringEncoding wxCFStringEncodingWcharT
= kCFStringEncodingUTF32BE
;
38 static const CFStringEncoding wxCFStringEncodingWcharT
= kCFStringEncodingUTF32LE
;
41 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 */
43 size_t wxMBConv_cf::ToWChar(wchar_t * dst
, size_t dstSize
, const char * src
, size_t srcSize
) const
45 wxCHECK(src
, wxCONV_FAILED
);
47 /* NOTE: This is wrong if the source encoding has an element size
48 * other than char (e.g. it's kCFStringEncodingUnicode)
49 * If the user specifies it, it's presumably right though.
50 * Right now we don't support UTF-16 in anyway since wx can do a better job.
52 if(srcSize
== wxNO_LEN
)
53 srcSize
= strlen(src
) + 1;
55 // First create the temporary CFString
56 wxCFRef
<CFStringRef
> theString( CFStringCreateWithBytes (
61 false //no BOM/external representation
64 wxCHECK(theString
!= NULL
, wxCONV_FAILED
);
66 /* NOTE: The string content includes the NULL element if the source string did
67 * That means we have to do nothing special because the destination will have
68 * the NULL element iff the source did and the NULL element will be included
69 * in the count iff it was included in the source count.
73 /* If we're compiling against Tiger headers we can support direct conversion
74 * to UTF32. If we are then run against a pre-Tiger system, the encoding
75 * won't be available so we'll defer to the string->UTF-16->UTF-32 conversion.
77 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
78 if(CFStringIsEncodingAvailable(wxCFStringEncodingWcharT
))
80 CFRange fullStringRange
= CFRangeMake(0, CFStringGetLength(theString
));
83 CFIndex charsConverted
= CFStringGetBytes(
86 wxCFStringEncodingWcharT
,
89 // if dstSize is 0 then pass NULL to get required length in usedBufLen
90 dstSize
!= 0?(UInt8
*)dst
:NULL
,
91 dstSize
* sizeof(wchar_t),
94 // charsConverted is > 0 iff conversion succeeded
95 if(charsConverted
<= 0)
98 /* usedBufLen is the number of bytes written, so we divide by
99 * sizeof(wchar_t) to get the number of elements written.
101 wxASSERT( (usedBufLen
% sizeof(wchar_t)) == 0 );
103 // CFStringGetBytes does exactly the right thing when buffer
104 // pointer is NULL and returns the number of bytes required
105 return usedBufLen
/ sizeof(wchar_t);
108 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 */
110 // NOTE: Includes NULL iff source did
111 /* NOTE: This is an approximation. The eventual UTF-32 will
112 * possibly have less elements but certainly not more.
114 size_t returnSize
= CFStringGetLength(theString
);
116 if (dstSize
== 0 || dst
== NULL
)
121 // Convert the entire string.. too hard to figure out how many UTF-16 we'd need
122 // for an undersized UTF-32 destination buffer.
123 CFRange fullStringRange
= CFRangeMake(0, CFStringGetLength(theString
));
124 UniChar
*szUniCharBuffer
= new UniChar
[fullStringRange
.length
];
126 CFStringGetCharacters(theString
, fullStringRange
, szUniCharBuffer
);
128 wxMBConvUTF16 converter
;
129 returnSize
= converter
.ToWChar( dst
, dstSize
, (const char*)szUniCharBuffer
, fullStringRange
.length
);
130 delete [] szUniCharBuffer
;
137 size_t wxMBConv_cf::FromWChar(char *dst
, size_t dstSize
, const wchar_t *src
, size_t srcSize
) const
139 wxCHECK(src
, wxCONV_FAILED
);
141 if(srcSize
== wxNO_LEN
)
142 srcSize
= wxStrlen(src
) + 1;
144 // Temporary CFString
145 wxCFRef
<CFStringRef
> theString
;
147 /* If we're compiling against Tiger headers we can support direct conversion
148 * from UTF32. If we are then run against a pre-Tiger system, the encoding
149 * won't be available so we'll defer to the UTF-32->UTF-16->string conversion.
151 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
152 if(CFStringIsEncodingAvailable(wxCFStringEncodingWcharT
))
154 theString
= wxCFRef
<CFStringRef
>(CFStringCreateWithBytes(
157 srcSize
* sizeof(wchar_t),
158 wxCFStringEncodingWcharT
,
162 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 */
164 wxMBConvUTF16 converter
;
165 size_t cbUniBuffer
= converter
.FromWChar( NULL
, 0, src
, srcSize
);
166 wxASSERT(cbUniBuffer
% sizeof(UniChar
));
168 // Will be free'd by kCFAllocatorMalloc when CFString is released
169 UniChar
*tmpUniBuffer
= (UniChar
*)malloc(cbUniBuffer
);
171 cbUniBuffer
= converter
.FromWChar( (char*) tmpUniBuffer
, cbUniBuffer
, src
, srcSize
);
172 wxASSERT(cbUniBuffer
% sizeof(UniChar
));
174 theString
= wxCFRef
<CFStringRef
>(CFStringCreateWithCharactersNoCopy(
177 cbUniBuffer
/ sizeof(UniChar
),
183 wxCHECK(theString
!= NULL
, wxCONV_FAILED
);
187 CFIndex charsConverted
= CFStringGetBytes(
189 CFRangeMake(0, CFStringGetLength(theString
)),
191 0, // FAIL on unconvertible characters
192 false, // not an external representation
193 // if dstSize is 0 then pass NULL to get required length in usedBufLen
194 (dstSize
!= 0)?(UInt8
*)dst
:NULL
,
199 // charsConverted is > 0 iff conversion succeeded
200 if(charsConverted
<= 0)
201 return wxCONV_FAILED
;