1*f6dc9357SAndroid Build Coastguard Worker // Common/StringConvert.cpp
2*f6dc9357SAndroid Build Coastguard Worker
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker
5*f6dc9357SAndroid Build Coastguard Worker #include "StringConvert.h"
6*f6dc9357SAndroid Build Coastguard Worker
7*f6dc9357SAndroid Build Coastguard Worker #ifndef _WIN32
8*f6dc9357SAndroid Build Coastguard Worker // #include <stdio.h>
9*f6dc9357SAndroid Build Coastguard Worker #include <stdlib.h>
10*f6dc9357SAndroid Build Coastguard Worker #endif
11*f6dc9357SAndroid Build Coastguard Worker
12*f6dc9357SAndroid Build Coastguard Worker #if !defined(_WIN32) || defined(ENV_HAVE_LOCALE)
13*f6dc9357SAndroid Build Coastguard Worker #include "UTFConvert.h"
14*f6dc9357SAndroid Build Coastguard Worker #endif
15*f6dc9357SAndroid Build Coastguard Worker
16*f6dc9357SAndroid Build Coastguard Worker #ifdef ENV_HAVE_LOCALE
17*f6dc9357SAndroid Build Coastguard Worker #include <locale.h>
18*f6dc9357SAndroid Build Coastguard Worker #endif
19*f6dc9357SAndroid Build Coastguard Worker
20*f6dc9357SAndroid Build Coastguard Worker static const char k_DefultChar = '_';
21*f6dc9357SAndroid Build Coastguard Worker
22*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
23*f6dc9357SAndroid Build Coastguard Worker
24*f6dc9357SAndroid Build Coastguard Worker /*
25*f6dc9357SAndroid Build Coastguard Worker MultiByteToWideChar(CodePage, DWORD dwFlags,
26*f6dc9357SAndroid Build Coastguard Worker LPCSTR lpMultiByteStr, int cbMultiByte,
27*f6dc9357SAndroid Build Coastguard Worker LPWSTR lpWideCharStr, int cchWideChar)
28*f6dc9357SAndroid Build Coastguard Worker
29*f6dc9357SAndroid Build Coastguard Worker if (cbMultiByte == 0)
30*f6dc9357SAndroid Build Coastguard Worker return: 0. ERR: ERROR_INVALID_PARAMETER
31*f6dc9357SAndroid Build Coastguard Worker
32*f6dc9357SAndroid Build Coastguard Worker if (cchWideChar == 0)
33*f6dc9357SAndroid Build Coastguard Worker return: the required buffer size in characters.
34*f6dc9357SAndroid Build Coastguard Worker
35*f6dc9357SAndroid Build Coastguard Worker if (supplied buffer size was not large enough)
36*f6dc9357SAndroid Build Coastguard Worker return: 0. ERR: ERROR_INSUFFICIENT_BUFFER
37*f6dc9357SAndroid Build Coastguard Worker The number of filled characters in lpWideCharStr can be smaller than cchWideChar (if last character is complex)
38*f6dc9357SAndroid Build Coastguard Worker
39*f6dc9357SAndroid Build Coastguard Worker If there are illegal characters:
40*f6dc9357SAndroid Build Coastguard Worker if MB_ERR_INVALID_CHARS is set in dwFlags:
41*f6dc9357SAndroid Build Coastguard Worker - the function stops conversion on illegal character.
42*f6dc9357SAndroid Build Coastguard Worker - Return: 0. ERR: ERROR_NO_UNICODE_TRANSLATION.
43*f6dc9357SAndroid Build Coastguard Worker
44*f6dc9357SAndroid Build Coastguard Worker if MB_ERR_INVALID_CHARS is NOT set in dwFlags:
45*f6dc9357SAndroid Build Coastguard Worker before Vista: illegal character is dropped (skipped). WinXP-64: GetLastError() returns 0.
46*f6dc9357SAndroid Build Coastguard Worker in Vista+: illegal character is not dropped (MSDN). Undocumented: illegal
47*f6dc9357SAndroid Build Coastguard Worker character is converted to U+FFFD, which is REPLACEMENT CHARACTER.
48*f6dc9357SAndroid Build Coastguard Worker */
49*f6dc9357SAndroid Build Coastguard Worker
50*f6dc9357SAndroid Build Coastguard Worker
MultiByteToUnicodeString2(UString & dest,const AString & src,UINT codePage)51*f6dc9357SAndroid Build Coastguard Worker void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT codePage)
52*f6dc9357SAndroid Build Coastguard Worker {
53*f6dc9357SAndroid Build Coastguard Worker dest.Empty();
54*f6dc9357SAndroid Build Coastguard Worker if (src.IsEmpty())
55*f6dc9357SAndroid Build Coastguard Worker return;
56*f6dc9357SAndroid Build Coastguard Worker {
57*f6dc9357SAndroid Build Coastguard Worker /*
58*f6dc9357SAndroid Build Coastguard Worker wchar_t *d = dest.GetBuf(src.Len());
59*f6dc9357SAndroid Build Coastguard Worker const char *s = (const char *)src;
60*f6dc9357SAndroid Build Coastguard Worker unsigned i;
61*f6dc9357SAndroid Build Coastguard Worker
62*f6dc9357SAndroid Build Coastguard Worker for (i = 0;;)
63*f6dc9357SAndroid Build Coastguard Worker {
64*f6dc9357SAndroid Build Coastguard Worker Byte c = (Byte)s[i];
65*f6dc9357SAndroid Build Coastguard Worker if (c >= 0x80 || c == 0)
66*f6dc9357SAndroid Build Coastguard Worker break;
67*f6dc9357SAndroid Build Coastguard Worker d[i++] = (wchar_t)c;
68*f6dc9357SAndroid Build Coastguard Worker }
69*f6dc9357SAndroid Build Coastguard Worker
70*f6dc9357SAndroid Build Coastguard Worker if (i != src.Len())
71*f6dc9357SAndroid Build Coastguard Worker {
72*f6dc9357SAndroid Build Coastguard Worker unsigned len = MultiByteToWideChar(codePage, 0, s + i,
73*f6dc9357SAndroid Build Coastguard Worker src.Len() - i, d + i,
74*f6dc9357SAndroid Build Coastguard Worker src.Len() + 1 - i);
75*f6dc9357SAndroid Build Coastguard Worker if (len == 0)
76*f6dc9357SAndroid Build Coastguard Worker throw 282228;
77*f6dc9357SAndroid Build Coastguard Worker i += len;
78*f6dc9357SAndroid Build Coastguard Worker }
79*f6dc9357SAndroid Build Coastguard Worker
80*f6dc9357SAndroid Build Coastguard Worker d[i] = 0;
81*f6dc9357SAndroid Build Coastguard Worker dest.ReleaseBuf_SetLen(i);
82*f6dc9357SAndroid Build Coastguard Worker */
83*f6dc9357SAndroid Build Coastguard Worker unsigned len = (unsigned)MultiByteToWideChar(codePage, 0, src, (int)src.Len(), NULL, 0);
84*f6dc9357SAndroid Build Coastguard Worker if (len == 0)
85*f6dc9357SAndroid Build Coastguard Worker {
86*f6dc9357SAndroid Build Coastguard Worker if (GetLastError() != 0)
87*f6dc9357SAndroid Build Coastguard Worker throw 282228;
88*f6dc9357SAndroid Build Coastguard Worker }
89*f6dc9357SAndroid Build Coastguard Worker else
90*f6dc9357SAndroid Build Coastguard Worker {
91*f6dc9357SAndroid Build Coastguard Worker len = (unsigned)MultiByteToWideChar(codePage, 0, src, (int)src.Len(), dest.GetBuf(len), (int)len);
92*f6dc9357SAndroid Build Coastguard Worker if (len == 0)
93*f6dc9357SAndroid Build Coastguard Worker throw 282228;
94*f6dc9357SAndroid Build Coastguard Worker dest.ReleaseBuf_SetEnd(len);
95*f6dc9357SAndroid Build Coastguard Worker }
96*f6dc9357SAndroid Build Coastguard Worker }
97*f6dc9357SAndroid Build Coastguard Worker }
98*f6dc9357SAndroid Build Coastguard Worker
99*f6dc9357SAndroid Build Coastguard Worker /*
100*f6dc9357SAndroid Build Coastguard Worker int WideCharToMultiByte(
101*f6dc9357SAndroid Build Coastguard Worker UINT CodePage, DWORD dwFlags,
102*f6dc9357SAndroid Build Coastguard Worker LPCWSTR lpWideCharStr, int cchWideChar,
103*f6dc9357SAndroid Build Coastguard Worker LPSTR lpMultiByteStr, int cbMultiByte,
104*f6dc9357SAndroid Build Coastguard Worker LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar);
105*f6dc9357SAndroid Build Coastguard Worker
106*f6dc9357SAndroid Build Coastguard Worker if (lpDefaultChar == NULL),
107*f6dc9357SAndroid Build Coastguard Worker - it uses system default value.
108*f6dc9357SAndroid Build Coastguard Worker
109*f6dc9357SAndroid Build Coastguard Worker if (CodePage == CP_UTF7 || CodePage == CP_UTF8)
110*f6dc9357SAndroid Build Coastguard Worker if (lpDefaultChar != NULL || lpUsedDefaultChar != NULL)
111*f6dc9357SAndroid Build Coastguard Worker return: 0. ERR: ERROR_INVALID_PARAMETER.
112*f6dc9357SAndroid Build Coastguard Worker
113*f6dc9357SAndroid Build Coastguard Worker The function operates most efficiently, if (lpDefaultChar == NULL && lpUsedDefaultChar == NULL)
114*f6dc9357SAndroid Build Coastguard Worker
115*f6dc9357SAndroid Build Coastguard Worker */
116*f6dc9357SAndroid Build Coastguard Worker
UnicodeStringToMultiByte2(AString & dest,const UString & src,UINT codePage,char defaultChar,bool & defaultCharWasUsed)117*f6dc9357SAndroid Build Coastguard Worker static void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT codePage, char defaultChar, bool &defaultCharWasUsed)
118*f6dc9357SAndroid Build Coastguard Worker {
119*f6dc9357SAndroid Build Coastguard Worker dest.Empty();
120*f6dc9357SAndroid Build Coastguard Worker defaultCharWasUsed = false;
121*f6dc9357SAndroid Build Coastguard Worker if (src.IsEmpty())
122*f6dc9357SAndroid Build Coastguard Worker return;
123*f6dc9357SAndroid Build Coastguard Worker {
124*f6dc9357SAndroid Build Coastguard Worker /*
125*f6dc9357SAndroid Build Coastguard Worker unsigned numRequiredBytes = src.Len() * 2;
126*f6dc9357SAndroid Build Coastguard Worker char *d = dest.GetBuf(numRequiredBytes);
127*f6dc9357SAndroid Build Coastguard Worker const wchar_t *s = (const wchar_t *)src;
128*f6dc9357SAndroid Build Coastguard Worker unsigned i;
129*f6dc9357SAndroid Build Coastguard Worker
130*f6dc9357SAndroid Build Coastguard Worker for (i = 0;;)
131*f6dc9357SAndroid Build Coastguard Worker {
132*f6dc9357SAndroid Build Coastguard Worker wchar_t c = s[i];
133*f6dc9357SAndroid Build Coastguard Worker if (c >= 0x80 || c == 0)
134*f6dc9357SAndroid Build Coastguard Worker break;
135*f6dc9357SAndroid Build Coastguard Worker d[i++] = (char)c;
136*f6dc9357SAndroid Build Coastguard Worker }
137*f6dc9357SAndroid Build Coastguard Worker
138*f6dc9357SAndroid Build Coastguard Worker if (i != src.Len())
139*f6dc9357SAndroid Build Coastguard Worker {
140*f6dc9357SAndroid Build Coastguard Worker BOOL defUsed = FALSE;
141*f6dc9357SAndroid Build Coastguard Worker defaultChar = defaultChar;
142*f6dc9357SAndroid Build Coastguard Worker
143*f6dc9357SAndroid Build Coastguard Worker bool isUtf = (codePage == CP_UTF8 || codePage == CP_UTF7);
144*f6dc9357SAndroid Build Coastguard Worker unsigned len = WideCharToMultiByte(codePage, 0, s + i, src.Len() - i,
145*f6dc9357SAndroid Build Coastguard Worker d + i, numRequiredBytes + 1 - i,
146*f6dc9357SAndroid Build Coastguard Worker (isUtf ? NULL : &defaultChar),
147*f6dc9357SAndroid Build Coastguard Worker (isUtf ? NULL : &defUsed));
148*f6dc9357SAndroid Build Coastguard Worker defaultCharWasUsed = (defUsed != FALSE);
149*f6dc9357SAndroid Build Coastguard Worker if (len == 0)
150*f6dc9357SAndroid Build Coastguard Worker throw 282229;
151*f6dc9357SAndroid Build Coastguard Worker i += len;
152*f6dc9357SAndroid Build Coastguard Worker }
153*f6dc9357SAndroid Build Coastguard Worker
154*f6dc9357SAndroid Build Coastguard Worker d[i] = 0;
155*f6dc9357SAndroid Build Coastguard Worker dest.ReleaseBuf_SetLen(i);
156*f6dc9357SAndroid Build Coastguard Worker */
157*f6dc9357SAndroid Build Coastguard Worker
158*f6dc9357SAndroid Build Coastguard Worker /*
159*f6dc9357SAndroid Build Coastguard Worker if (codePage != CP_UTF7)
160*f6dc9357SAndroid Build Coastguard Worker {
161*f6dc9357SAndroid Build Coastguard Worker const wchar_t *s = (const wchar_t *)src;
162*f6dc9357SAndroid Build Coastguard Worker unsigned i;
163*f6dc9357SAndroid Build Coastguard Worker for (i = 0;; i++)
164*f6dc9357SAndroid Build Coastguard Worker {
165*f6dc9357SAndroid Build Coastguard Worker wchar_t c = s[i];
166*f6dc9357SAndroid Build Coastguard Worker if (c >= 0x80 || c == 0)
167*f6dc9357SAndroid Build Coastguard Worker break;
168*f6dc9357SAndroid Build Coastguard Worker }
169*f6dc9357SAndroid Build Coastguard Worker
170*f6dc9357SAndroid Build Coastguard Worker if (s[i] == 0)
171*f6dc9357SAndroid Build Coastguard Worker {
172*f6dc9357SAndroid Build Coastguard Worker char *d = dest.GetBuf(src.Len());
173*f6dc9357SAndroid Build Coastguard Worker for (i = 0;;)
174*f6dc9357SAndroid Build Coastguard Worker {
175*f6dc9357SAndroid Build Coastguard Worker wchar_t c = s[i];
176*f6dc9357SAndroid Build Coastguard Worker if (c == 0)
177*f6dc9357SAndroid Build Coastguard Worker break;
178*f6dc9357SAndroid Build Coastguard Worker d[i++] = (char)c;
179*f6dc9357SAndroid Build Coastguard Worker }
180*f6dc9357SAndroid Build Coastguard Worker d[i] = 0;
181*f6dc9357SAndroid Build Coastguard Worker dest.ReleaseBuf_SetLen(i);
182*f6dc9357SAndroid Build Coastguard Worker return;
183*f6dc9357SAndroid Build Coastguard Worker }
184*f6dc9357SAndroid Build Coastguard Worker }
185*f6dc9357SAndroid Build Coastguard Worker */
186*f6dc9357SAndroid Build Coastguard Worker
187*f6dc9357SAndroid Build Coastguard Worker unsigned len = (unsigned)WideCharToMultiByte(codePage, 0, src, (int)src.Len(), NULL, 0, NULL, NULL);
188*f6dc9357SAndroid Build Coastguard Worker if (len == 0)
189*f6dc9357SAndroid Build Coastguard Worker {
190*f6dc9357SAndroid Build Coastguard Worker if (GetLastError() != 0)
191*f6dc9357SAndroid Build Coastguard Worker throw 282228;
192*f6dc9357SAndroid Build Coastguard Worker }
193*f6dc9357SAndroid Build Coastguard Worker else
194*f6dc9357SAndroid Build Coastguard Worker {
195*f6dc9357SAndroid Build Coastguard Worker BOOL defUsed = FALSE;
196*f6dc9357SAndroid Build Coastguard Worker bool isUtf = (codePage == CP_UTF8 || codePage == CP_UTF7);
197*f6dc9357SAndroid Build Coastguard Worker // defaultChar = defaultChar;
198*f6dc9357SAndroid Build Coastguard Worker len = (unsigned)WideCharToMultiByte(codePage, 0, src, (int)src.Len(),
199*f6dc9357SAndroid Build Coastguard Worker dest.GetBuf(len), (int)len,
200*f6dc9357SAndroid Build Coastguard Worker (isUtf ? NULL : &defaultChar),
201*f6dc9357SAndroid Build Coastguard Worker (isUtf ? NULL : &defUsed)
202*f6dc9357SAndroid Build Coastguard Worker );
203*f6dc9357SAndroid Build Coastguard Worker if (!isUtf)
204*f6dc9357SAndroid Build Coastguard Worker defaultCharWasUsed = (defUsed != FALSE);
205*f6dc9357SAndroid Build Coastguard Worker if (len == 0)
206*f6dc9357SAndroid Build Coastguard Worker throw 282228;
207*f6dc9357SAndroid Build Coastguard Worker dest.ReleaseBuf_SetEnd(len);
208*f6dc9357SAndroid Build Coastguard Worker }
209*f6dc9357SAndroid Build Coastguard Worker }
210*f6dc9357SAndroid Build Coastguard Worker }
211*f6dc9357SAndroid Build Coastguard Worker
212*f6dc9357SAndroid Build Coastguard Worker /*
213*f6dc9357SAndroid Build Coastguard Worker #ifndef UNDER_CE
214*f6dc9357SAndroid Build Coastguard Worker AString SystemStringToOemString(const CSysString &src)
215*f6dc9357SAndroid Build Coastguard Worker {
216*f6dc9357SAndroid Build Coastguard Worker AString dest;
217*f6dc9357SAndroid Build Coastguard Worker const unsigned len = src.Len() * 2;
218*f6dc9357SAndroid Build Coastguard Worker CharToOem(src, dest.GetBuf(len));
219*f6dc9357SAndroid Build Coastguard Worker dest.ReleaseBuf_CalcLen(len);
220*f6dc9357SAndroid Build Coastguard Worker return dest;
221*f6dc9357SAndroid Build Coastguard Worker }
222*f6dc9357SAndroid Build Coastguard Worker #endif
223*f6dc9357SAndroid Build Coastguard Worker */
224*f6dc9357SAndroid Build Coastguard Worker
225*f6dc9357SAndroid Build Coastguard Worker #else // _WIN32
226*f6dc9357SAndroid Build Coastguard Worker
227*f6dc9357SAndroid Build Coastguard Worker // #include <stdio.h>
228*f6dc9357SAndroid Build Coastguard Worker /*
229*f6dc9357SAndroid Build Coastguard Worker if (wchar_t is 32-bit (#if WCHAR_MAX > 0xffff),
230*f6dc9357SAndroid Build Coastguard Worker and utf-8 string contains big unicode character > 0xffff),
231*f6dc9357SAndroid Build Coastguard Worker then we still use 16-bit surrogate pair in UString.
232*f6dc9357SAndroid Build Coastguard Worker It simplifies another code where utf-16 encoding is used.
233*f6dc9357SAndroid Build Coastguard Worker So we use surrogate-conversion code only in is file.
234*f6dc9357SAndroid Build Coastguard Worker */
235*f6dc9357SAndroid Build Coastguard Worker
236*f6dc9357SAndroid Build Coastguard Worker /*
237*f6dc9357SAndroid Build Coastguard Worker mbstowcs() returns error if there is error in utf-8 stream,
238*f6dc9357SAndroid Build Coastguard Worker mbstowcs() returns error if there is single surrogates point (d800-dfff) in utf-8 stream
239*f6dc9357SAndroid Build Coastguard Worker */
240*f6dc9357SAndroid Build Coastguard Worker
241*f6dc9357SAndroid Build Coastguard Worker /*
242*f6dc9357SAndroid Build Coastguard Worker static void MultiByteToUnicodeString2_Native(UString &dest, const AString &src)
243*f6dc9357SAndroid Build Coastguard Worker {
244*f6dc9357SAndroid Build Coastguard Worker dest.Empty();
245*f6dc9357SAndroid Build Coastguard Worker if (src.IsEmpty())
246*f6dc9357SAndroid Build Coastguard Worker return;
247*f6dc9357SAndroid Build Coastguard Worker
248*f6dc9357SAndroid Build Coastguard Worker const size_t limit = ((size_t)src.Len() + 1) * 2;
249*f6dc9357SAndroid Build Coastguard Worker wchar_t *d = dest.GetBuf((unsigned)limit);
250*f6dc9357SAndroid Build Coastguard Worker const size_t len = mbstowcs(d, src, limit);
251*f6dc9357SAndroid Build Coastguard Worker if (len != (size_t)-1)
252*f6dc9357SAndroid Build Coastguard Worker {
253*f6dc9357SAndroid Build Coastguard Worker dest.ReleaseBuf_SetEnd((unsigned)len);
254*f6dc9357SAndroid Build Coastguard Worker return;
255*f6dc9357SAndroid Build Coastguard Worker }
256*f6dc9357SAndroid Build Coastguard Worker dest.ReleaseBuf_SetEnd(0);
257*f6dc9357SAndroid Build Coastguard Worker }
258*f6dc9357SAndroid Build Coastguard Worker */
259*f6dc9357SAndroid Build Coastguard Worker
260*f6dc9357SAndroid Build Coastguard Worker bool g_ForceToUTF8 = true; // false;
261*f6dc9357SAndroid Build Coastguard Worker
MultiByteToUnicodeString2(UString & dest,const AString & src,UINT codePage)262*f6dc9357SAndroid Build Coastguard Worker void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT codePage)
263*f6dc9357SAndroid Build Coastguard Worker {
264*f6dc9357SAndroid Build Coastguard Worker dest.Empty();
265*f6dc9357SAndroid Build Coastguard Worker if (src.IsEmpty())
266*f6dc9357SAndroid Build Coastguard Worker return;
267*f6dc9357SAndroid Build Coastguard Worker
268*f6dc9357SAndroid Build Coastguard Worker if (codePage == CP_UTF8 || g_ForceToUTF8)
269*f6dc9357SAndroid Build Coastguard Worker {
270*f6dc9357SAndroid Build Coastguard Worker #if 1
271*f6dc9357SAndroid Build Coastguard Worker ConvertUTF8ToUnicode(src, dest);
272*f6dc9357SAndroid Build Coastguard Worker return;
273*f6dc9357SAndroid Build Coastguard Worker #endif
274*f6dc9357SAndroid Build Coastguard Worker }
275*f6dc9357SAndroid Build Coastguard Worker
276*f6dc9357SAndroid Build Coastguard Worker const size_t limit = ((size_t)src.Len() + 1) * 2;
277*f6dc9357SAndroid Build Coastguard Worker wchar_t *d = dest.GetBuf((unsigned)limit);
278*f6dc9357SAndroid Build Coastguard Worker const size_t len = mbstowcs(d, src, limit);
279*f6dc9357SAndroid Build Coastguard Worker if (len != (size_t)-1)
280*f6dc9357SAndroid Build Coastguard Worker {
281*f6dc9357SAndroid Build Coastguard Worker dest.ReleaseBuf_SetEnd((unsigned)len);
282*f6dc9357SAndroid Build Coastguard Worker
283*f6dc9357SAndroid Build Coastguard Worker #if WCHAR_MAX > 0xffff
284*f6dc9357SAndroid Build Coastguard Worker d = dest.GetBuf();
285*f6dc9357SAndroid Build Coastguard Worker for (size_t i = 0;; i++)
286*f6dc9357SAndroid Build Coastguard Worker {
287*f6dc9357SAndroid Build Coastguard Worker wchar_t c = d[i];
288*f6dc9357SAndroid Build Coastguard Worker // printf("\ni=%2d c = %4x\n", (unsigned)i, (unsigned)c);
289*f6dc9357SAndroid Build Coastguard Worker if (c == 0)
290*f6dc9357SAndroid Build Coastguard Worker break;
291*f6dc9357SAndroid Build Coastguard Worker if (c >= 0x10000 && c < 0x110000)
292*f6dc9357SAndroid Build Coastguard Worker {
293*f6dc9357SAndroid Build Coastguard Worker UString tempString = d + i;
294*f6dc9357SAndroid Build Coastguard Worker const wchar_t *t = tempString.Ptr();
295*f6dc9357SAndroid Build Coastguard Worker
296*f6dc9357SAndroid Build Coastguard Worker for (;;)
297*f6dc9357SAndroid Build Coastguard Worker {
298*f6dc9357SAndroid Build Coastguard Worker wchar_t w = *t++;
299*f6dc9357SAndroid Build Coastguard Worker // printf("\nchar=%x\n", w);
300*f6dc9357SAndroid Build Coastguard Worker if (w == 0)
301*f6dc9357SAndroid Build Coastguard Worker break;
302*f6dc9357SAndroid Build Coastguard Worker if (i == limit)
303*f6dc9357SAndroid Build Coastguard Worker break; // unexpected error
304*f6dc9357SAndroid Build Coastguard Worker if (w >= 0x10000 && w < 0x110000)
305*f6dc9357SAndroid Build Coastguard Worker {
306*f6dc9357SAndroid Build Coastguard Worker #if 1
307*f6dc9357SAndroid Build Coastguard Worker if (i + 1 == limit)
308*f6dc9357SAndroid Build Coastguard Worker break; // unexpected error
309*f6dc9357SAndroid Build Coastguard Worker w -= 0x10000;
310*f6dc9357SAndroid Build Coastguard Worker d[i++] = (unsigned)0xd800 + (((unsigned)w >> 10) & 0x3ff);
311*f6dc9357SAndroid Build Coastguard Worker w = 0xdc00 + (w & 0x3ff);
312*f6dc9357SAndroid Build Coastguard Worker #else
313*f6dc9357SAndroid Build Coastguard Worker // w = '_'; // for debug
314*f6dc9357SAndroid Build Coastguard Worker #endif
315*f6dc9357SAndroid Build Coastguard Worker }
316*f6dc9357SAndroid Build Coastguard Worker d[i++] = w;
317*f6dc9357SAndroid Build Coastguard Worker }
318*f6dc9357SAndroid Build Coastguard Worker dest.ReleaseBuf_SetEnd((unsigned)i);
319*f6dc9357SAndroid Build Coastguard Worker break;
320*f6dc9357SAndroid Build Coastguard Worker }
321*f6dc9357SAndroid Build Coastguard Worker }
322*f6dc9357SAndroid Build Coastguard Worker
323*f6dc9357SAndroid Build Coastguard Worker #endif
324*f6dc9357SAndroid Build Coastguard Worker
325*f6dc9357SAndroid Build Coastguard Worker /*
326*f6dc9357SAndroid Build Coastguard Worker printf("\nMultiByteToUnicodeString2 (%d) %s\n", (int)src.Len(), src.Ptr());
327*f6dc9357SAndroid Build Coastguard Worker printf("char: ");
328*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < src.Len(); i++)
329*f6dc9357SAndroid Build Coastguard Worker printf (" %02x", (int)(Byte)src[i]);
330*f6dc9357SAndroid Build Coastguard Worker printf("\n");
331*f6dc9357SAndroid Build Coastguard Worker printf("\n-> (%d) %ls\n", (int)dest.Len(), dest.Ptr());
332*f6dc9357SAndroid Build Coastguard Worker printf("wchar_t: ");
333*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < dest.Len(); i++)
334*f6dc9357SAndroid Build Coastguard Worker {
335*f6dc9357SAndroid Build Coastguard Worker printf (" %02x", (int)dest[i]);
336*f6dc9357SAndroid Build Coastguard Worker }
337*f6dc9357SAndroid Build Coastguard Worker printf("\n");
338*f6dc9357SAndroid Build Coastguard Worker */
339*f6dc9357SAndroid Build Coastguard Worker
340*f6dc9357SAndroid Build Coastguard Worker return;
341*f6dc9357SAndroid Build Coastguard Worker }
342*f6dc9357SAndroid Build Coastguard Worker
343*f6dc9357SAndroid Build Coastguard Worker /* if there is mbstowcs() error, we have two ways:
344*f6dc9357SAndroid Build Coastguard Worker
345*f6dc9357SAndroid Build Coastguard Worker 1) change 0x80+ characters to some character: '_'
346*f6dc9357SAndroid Build Coastguard Worker in that case we lose data, but we have correct UString()
347*f6dc9357SAndroid Build Coastguard Worker and that scheme can show errors to user in early stages,
348*f6dc9357SAndroid Build Coastguard Worker when file converted back to mbs() cannot be found
349*f6dc9357SAndroid Build Coastguard Worker
350*f6dc9357SAndroid Build Coastguard Worker 2) transfer bad characters in some UTF-16 range.
351*f6dc9357SAndroid Build Coastguard Worker it can be non-original Unicode character.
352*f6dc9357SAndroid Build Coastguard Worker but later we still can restore original character.
353*f6dc9357SAndroid Build Coastguard Worker */
354*f6dc9357SAndroid Build Coastguard Worker
355*f6dc9357SAndroid Build Coastguard Worker
356*f6dc9357SAndroid Build Coastguard Worker // printf("\nmbstowcs ERROR !!!!!! s=%s\n", src.Ptr());
357*f6dc9357SAndroid Build Coastguard Worker {
358*f6dc9357SAndroid Build Coastguard Worker unsigned i;
359*f6dc9357SAndroid Build Coastguard Worker const char *s = (const char *)src;
360*f6dc9357SAndroid Build Coastguard Worker for (i = 0;;)
361*f6dc9357SAndroid Build Coastguard Worker {
362*f6dc9357SAndroid Build Coastguard Worker Byte c = (Byte)s[i];
363*f6dc9357SAndroid Build Coastguard Worker if (c == 0)
364*f6dc9357SAndroid Build Coastguard Worker break;
365*f6dc9357SAndroid Build Coastguard Worker // we can use ascii compatibilty character '_'
366*f6dc9357SAndroid Build Coastguard Worker // if (c > 0x7F) c = '_'; // we replace "bad: character
367*f6dc9357SAndroid Build Coastguard Worker d[i++] = (wchar_t)c;
368*f6dc9357SAndroid Build Coastguard Worker }
369*f6dc9357SAndroid Build Coastguard Worker d[i] = 0;
370*f6dc9357SAndroid Build Coastguard Worker dest.ReleaseBuf_SetLen(i);
371*f6dc9357SAndroid Build Coastguard Worker }
372*f6dc9357SAndroid Build Coastguard Worker }
373*f6dc9357SAndroid Build Coastguard Worker
UnicodeStringToMultiByte2_Native(AString & dest,const UString & src)374*f6dc9357SAndroid Build Coastguard Worker static void UnicodeStringToMultiByte2_Native(AString &dest, const UString &src)
375*f6dc9357SAndroid Build Coastguard Worker {
376*f6dc9357SAndroid Build Coastguard Worker dest.Empty();
377*f6dc9357SAndroid Build Coastguard Worker if (src.IsEmpty())
378*f6dc9357SAndroid Build Coastguard Worker return;
379*f6dc9357SAndroid Build Coastguard Worker
380*f6dc9357SAndroid Build Coastguard Worker const size_t limit = ((size_t)src.Len() + 1) * 6;
381*f6dc9357SAndroid Build Coastguard Worker char *d = dest.GetBuf((unsigned)limit);
382*f6dc9357SAndroid Build Coastguard Worker
383*f6dc9357SAndroid Build Coastguard Worker const size_t len = wcstombs(d, src, limit);
384*f6dc9357SAndroid Build Coastguard Worker
385*f6dc9357SAndroid Build Coastguard Worker if (len != (size_t)-1)
386*f6dc9357SAndroid Build Coastguard Worker {
387*f6dc9357SAndroid Build Coastguard Worker dest.ReleaseBuf_SetEnd((unsigned)len);
388*f6dc9357SAndroid Build Coastguard Worker return;
389*f6dc9357SAndroid Build Coastguard Worker }
390*f6dc9357SAndroid Build Coastguard Worker dest.ReleaseBuf_SetEnd(0);
391*f6dc9357SAndroid Build Coastguard Worker }
392*f6dc9357SAndroid Build Coastguard Worker
393*f6dc9357SAndroid Build Coastguard Worker
UnicodeStringToMultiByte2(AString & dest,const UString & src2,UINT codePage,char defaultChar,bool & defaultCharWasUsed)394*f6dc9357SAndroid Build Coastguard Worker static void UnicodeStringToMultiByte2(AString &dest, const UString &src2, UINT codePage, char defaultChar, bool &defaultCharWasUsed)
395*f6dc9357SAndroid Build Coastguard Worker {
396*f6dc9357SAndroid Build Coastguard Worker // if (codePage == 1234567) // for debug purposes
397*f6dc9357SAndroid Build Coastguard Worker if (codePage == CP_UTF8 || g_ForceToUTF8)
398*f6dc9357SAndroid Build Coastguard Worker {
399*f6dc9357SAndroid Build Coastguard Worker #if 1
400*f6dc9357SAndroid Build Coastguard Worker defaultCharWasUsed = false;
401*f6dc9357SAndroid Build Coastguard Worker ConvertUnicodeToUTF8(src2, dest);
402*f6dc9357SAndroid Build Coastguard Worker return;
403*f6dc9357SAndroid Build Coastguard Worker #endif
404*f6dc9357SAndroid Build Coastguard Worker }
405*f6dc9357SAndroid Build Coastguard Worker
406*f6dc9357SAndroid Build Coastguard Worker UString src = src2;
407*f6dc9357SAndroid Build Coastguard Worker #if WCHAR_MAX > 0xffff
408*f6dc9357SAndroid Build Coastguard Worker {
409*f6dc9357SAndroid Build Coastguard Worker src.Empty();
410*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < src2.Len();)
411*f6dc9357SAndroid Build Coastguard Worker {
412*f6dc9357SAndroid Build Coastguard Worker wchar_t c = src2[i++];
413*f6dc9357SAndroid Build Coastguard Worker if (c >= 0xd800 && c < 0xdc00 && i != src2.Len())
414*f6dc9357SAndroid Build Coastguard Worker {
415*f6dc9357SAndroid Build Coastguard Worker const wchar_t c2 = src2[i];
416*f6dc9357SAndroid Build Coastguard Worker if (c2 >= 0xdc00 && c2 < 0xe000)
417*f6dc9357SAndroid Build Coastguard Worker {
418*f6dc9357SAndroid Build Coastguard Worker #if 1
419*f6dc9357SAndroid Build Coastguard Worker // printf("\nSurragate [%d]: %4x %4x -> ", i, (int)c, (int)c2);
420*f6dc9357SAndroid Build Coastguard Worker c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff);
421*f6dc9357SAndroid Build Coastguard Worker // printf("%4x\n", (int)c);
422*f6dc9357SAndroid Build Coastguard Worker i++;
423*f6dc9357SAndroid Build Coastguard Worker #else
424*f6dc9357SAndroid Build Coastguard Worker // c = '_'; // for debug
425*f6dc9357SAndroid Build Coastguard Worker #endif
426*f6dc9357SAndroid Build Coastguard Worker }
427*f6dc9357SAndroid Build Coastguard Worker }
428*f6dc9357SAndroid Build Coastguard Worker src += c;
429*f6dc9357SAndroid Build Coastguard Worker }
430*f6dc9357SAndroid Build Coastguard Worker }
431*f6dc9357SAndroid Build Coastguard Worker #endif
432*f6dc9357SAndroid Build Coastguard Worker
433*f6dc9357SAndroid Build Coastguard Worker dest.Empty();
434*f6dc9357SAndroid Build Coastguard Worker defaultCharWasUsed = false;
435*f6dc9357SAndroid Build Coastguard Worker if (src.IsEmpty())
436*f6dc9357SAndroid Build Coastguard Worker return;
437*f6dc9357SAndroid Build Coastguard Worker
438*f6dc9357SAndroid Build Coastguard Worker const size_t len = wcstombs(NULL, src, 0);
439*f6dc9357SAndroid Build Coastguard Worker
440*f6dc9357SAndroid Build Coastguard Worker if (len != (size_t)-1)
441*f6dc9357SAndroid Build Coastguard Worker {
442*f6dc9357SAndroid Build Coastguard Worker const unsigned limit = ((unsigned)len);
443*f6dc9357SAndroid Build Coastguard Worker if (limit == len)
444*f6dc9357SAndroid Build Coastguard Worker {
445*f6dc9357SAndroid Build Coastguard Worker char *d = dest.GetBuf(limit);
446*f6dc9357SAndroid Build Coastguard Worker
447*f6dc9357SAndroid Build Coastguard Worker /*
448*f6dc9357SAndroid Build Coastguard Worker {
449*f6dc9357SAndroid Build Coastguard Worker printf("\nwcstombs; len = %d %ls \n", (int)src.Len(), src.Ptr());
450*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < src.Len(); i++)
451*f6dc9357SAndroid Build Coastguard Worker printf (" %02x", (int)src[i]);
452*f6dc9357SAndroid Build Coastguard Worker printf("\n");
453*f6dc9357SAndroid Build Coastguard Worker printf("\ndest Limit = %d \n", limit);
454*f6dc9357SAndroid Build Coastguard Worker }
455*f6dc9357SAndroid Build Coastguard Worker */
456*f6dc9357SAndroid Build Coastguard Worker
457*f6dc9357SAndroid Build Coastguard Worker const size_t len2 = wcstombs(d, src, len + 1);
458*f6dc9357SAndroid Build Coastguard Worker
459*f6dc9357SAndroid Build Coastguard Worker if (len2 != (size_t)-1 && len2 <= limit)
460*f6dc9357SAndroid Build Coastguard Worker {
461*f6dc9357SAndroid Build Coastguard Worker /*
462*f6dc9357SAndroid Build Coastguard Worker printf("\nOK : destLen = %d : %s\n", (int)len, dest.Ptr());
463*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < len2; i++)
464*f6dc9357SAndroid Build Coastguard Worker printf(" %02x", (int)(Byte)dest[i]);
465*f6dc9357SAndroid Build Coastguard Worker printf("\n");
466*f6dc9357SAndroid Build Coastguard Worker */
467*f6dc9357SAndroid Build Coastguard Worker dest.ReleaseBuf_SetEnd((unsigned)len2);
468*f6dc9357SAndroid Build Coastguard Worker return;
469*f6dc9357SAndroid Build Coastguard Worker }
470*f6dc9357SAndroid Build Coastguard Worker }
471*f6dc9357SAndroid Build Coastguard Worker }
472*f6dc9357SAndroid Build Coastguard Worker
473*f6dc9357SAndroid Build Coastguard Worker {
474*f6dc9357SAndroid Build Coastguard Worker const wchar_t *s = (const wchar_t *)src;
475*f6dc9357SAndroid Build Coastguard Worker char *d = dest.GetBuf(src.Len());
476*f6dc9357SAndroid Build Coastguard Worker
477*f6dc9357SAndroid Build Coastguard Worker unsigned i;
478*f6dc9357SAndroid Build Coastguard Worker for (i = 0;;)
479*f6dc9357SAndroid Build Coastguard Worker {
480*f6dc9357SAndroid Build Coastguard Worker wchar_t c = s[i];
481*f6dc9357SAndroid Build Coastguard Worker if (c == 0)
482*f6dc9357SAndroid Build Coastguard Worker break;
483*f6dc9357SAndroid Build Coastguard Worker if (c >=
484*f6dc9357SAndroid Build Coastguard Worker 0x100
485*f6dc9357SAndroid Build Coastguard Worker // 0x80
486*f6dc9357SAndroid Build Coastguard Worker )
487*f6dc9357SAndroid Build Coastguard Worker {
488*f6dc9357SAndroid Build Coastguard Worker c = defaultChar;
489*f6dc9357SAndroid Build Coastguard Worker defaultCharWasUsed = true;
490*f6dc9357SAndroid Build Coastguard Worker }
491*f6dc9357SAndroid Build Coastguard Worker
492*f6dc9357SAndroid Build Coastguard Worker d[i++] = (char)c;
493*f6dc9357SAndroid Build Coastguard Worker }
494*f6dc9357SAndroid Build Coastguard Worker d[i] = 0;
495*f6dc9357SAndroid Build Coastguard Worker dest.ReleaseBuf_SetLen(i);
496*f6dc9357SAndroid Build Coastguard Worker /*
497*f6dc9357SAndroid Build Coastguard Worker printf("\nUnicodeStringToMultiByte2; len = %d \n", (int)src.Len());
498*f6dc9357SAndroid Build Coastguard Worker printf("ERROR: %s\n", dest.Ptr());
499*f6dc9357SAndroid Build Coastguard Worker */
500*f6dc9357SAndroid Build Coastguard Worker }
501*f6dc9357SAndroid Build Coastguard Worker }
502*f6dc9357SAndroid Build Coastguard Worker
503*f6dc9357SAndroid Build Coastguard Worker #endif // _WIN32
504*f6dc9357SAndroid Build Coastguard Worker
505*f6dc9357SAndroid Build Coastguard Worker
MultiByteToUnicodeString(const AString & src,UINT codePage)506*f6dc9357SAndroid Build Coastguard Worker UString MultiByteToUnicodeString(const AString &src, UINT codePage)
507*f6dc9357SAndroid Build Coastguard Worker {
508*f6dc9357SAndroid Build Coastguard Worker UString dest;
509*f6dc9357SAndroid Build Coastguard Worker MultiByteToUnicodeString2(dest, src, codePage);
510*f6dc9357SAndroid Build Coastguard Worker return dest;
511*f6dc9357SAndroid Build Coastguard Worker }
512*f6dc9357SAndroid Build Coastguard Worker
MultiByteToUnicodeString(const char * src,UINT codePage)513*f6dc9357SAndroid Build Coastguard Worker UString MultiByteToUnicodeString(const char *src, UINT codePage)
514*f6dc9357SAndroid Build Coastguard Worker {
515*f6dc9357SAndroid Build Coastguard Worker return MultiByteToUnicodeString(AString(src), codePage);
516*f6dc9357SAndroid Build Coastguard Worker }
517*f6dc9357SAndroid Build Coastguard Worker
518*f6dc9357SAndroid Build Coastguard Worker
UnicodeStringToMultiByte2(AString & dest,const UString & src,UINT codePage)519*f6dc9357SAndroid Build Coastguard Worker void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT codePage)
520*f6dc9357SAndroid Build Coastguard Worker {
521*f6dc9357SAndroid Build Coastguard Worker bool defaultCharWasUsed;
522*f6dc9357SAndroid Build Coastguard Worker UnicodeStringToMultiByte2(dest, src, codePage, k_DefultChar, defaultCharWasUsed);
523*f6dc9357SAndroid Build Coastguard Worker }
524*f6dc9357SAndroid Build Coastguard Worker
UnicodeStringToMultiByte(const UString & src,UINT codePage,char defaultChar,bool & defaultCharWasUsed)525*f6dc9357SAndroid Build Coastguard Worker AString UnicodeStringToMultiByte(const UString &src, UINT codePage, char defaultChar, bool &defaultCharWasUsed)
526*f6dc9357SAndroid Build Coastguard Worker {
527*f6dc9357SAndroid Build Coastguard Worker AString dest;
528*f6dc9357SAndroid Build Coastguard Worker UnicodeStringToMultiByte2(dest, src, codePage, defaultChar, defaultCharWasUsed);
529*f6dc9357SAndroid Build Coastguard Worker return dest;
530*f6dc9357SAndroid Build Coastguard Worker }
531*f6dc9357SAndroid Build Coastguard Worker
UnicodeStringToMultiByte(const UString & src,UINT codePage)532*f6dc9357SAndroid Build Coastguard Worker AString UnicodeStringToMultiByte(const UString &src, UINT codePage)
533*f6dc9357SAndroid Build Coastguard Worker {
534*f6dc9357SAndroid Build Coastguard Worker AString dest;
535*f6dc9357SAndroid Build Coastguard Worker bool defaultCharWasUsed;
536*f6dc9357SAndroid Build Coastguard Worker UnicodeStringToMultiByte2(dest, src, codePage, k_DefultChar, defaultCharWasUsed);
537*f6dc9357SAndroid Build Coastguard Worker return dest;
538*f6dc9357SAndroid Build Coastguard Worker }
539*f6dc9357SAndroid Build Coastguard Worker
540*f6dc9357SAndroid Build Coastguard Worker
541*f6dc9357SAndroid Build Coastguard Worker
542*f6dc9357SAndroid Build Coastguard Worker
543*f6dc9357SAndroid Build Coastguard Worker #if !defined(_WIN32) || defined(ENV_HAVE_LOCALE)
544*f6dc9357SAndroid Build Coastguard Worker
545*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
546*f6dc9357SAndroid Build Coastguard Worker #define U_to_A(a, b, c) UnicodeStringToMultiByte2
547*f6dc9357SAndroid Build Coastguard Worker // #define A_to_U(a, b, c) MultiByteToUnicodeString2
548*f6dc9357SAndroid Build Coastguard Worker #else
549*f6dc9357SAndroid Build Coastguard Worker // void MultiByteToUnicodeString2_Native(UString &dest, const AString &src);
550*f6dc9357SAndroid Build Coastguard Worker #define U_to_A(a, b, c) UnicodeStringToMultiByte2_Native(a, b)
551*f6dc9357SAndroid Build Coastguard Worker // #define A_to_U(a, b, c) MultiByteToUnicodeString2_Native(a, b)
552*f6dc9357SAndroid Build Coastguard Worker #endif
553*f6dc9357SAndroid Build Coastguard Worker
IsNativeUTF8()554*f6dc9357SAndroid Build Coastguard Worker bool IsNativeUTF8()
555*f6dc9357SAndroid Build Coastguard Worker {
556*f6dc9357SAndroid Build Coastguard Worker UString u;
557*f6dc9357SAndroid Build Coastguard Worker AString a, a2;
558*f6dc9357SAndroid Build Coastguard Worker // for (unsigned c = 0x80; c < (UInt32)0x10000; c += (c >> 9) + 1)
559*f6dc9357SAndroid Build Coastguard Worker for (unsigned c = 0x80; c < (UInt32)0xD000; c += (c >> 2) + 1)
560*f6dc9357SAndroid Build Coastguard Worker {
561*f6dc9357SAndroid Build Coastguard Worker u.Empty();
562*f6dc9357SAndroid Build Coastguard Worker u += (wchar_t)c;
563*f6dc9357SAndroid Build Coastguard Worker /*
564*f6dc9357SAndroid Build Coastguard Worker if (Unicode_Is_There_Utf16SurrogateError(u))
565*f6dc9357SAndroid Build Coastguard Worker continue;
566*f6dc9357SAndroid Build Coastguard Worker #ifndef _WIN32
567*f6dc9357SAndroid Build Coastguard Worker if (Unicode_Is_There_BmpEscape(u))
568*f6dc9357SAndroid Build Coastguard Worker continue;
569*f6dc9357SAndroid Build Coastguard Worker #endif
570*f6dc9357SAndroid Build Coastguard Worker */
571*f6dc9357SAndroid Build Coastguard Worker ConvertUnicodeToUTF8(u, a);
572*f6dc9357SAndroid Build Coastguard Worker U_to_A(a2, u, CP_OEMCP);
573*f6dc9357SAndroid Build Coastguard Worker if (a != a2)
574*f6dc9357SAndroid Build Coastguard Worker return false;
575*f6dc9357SAndroid Build Coastguard Worker }
576*f6dc9357SAndroid Build Coastguard Worker return true;
577*f6dc9357SAndroid Build Coastguard Worker }
578*f6dc9357SAndroid Build Coastguard Worker
579*f6dc9357SAndroid Build Coastguard Worker #endif
580*f6dc9357SAndroid Build Coastguard Worker
581*f6dc9357SAndroid Build Coastguard Worker
582*f6dc9357SAndroid Build Coastguard Worker #ifdef ENV_HAVE_LOCALE
583*f6dc9357SAndroid Build Coastguard Worker
GetLocale(void)584*f6dc9357SAndroid Build Coastguard Worker const char *GetLocale(void)
585*f6dc9357SAndroid Build Coastguard Worker {
586*f6dc9357SAndroid Build Coastguard Worker #ifdef ENV_HAVE_LOCALE
587*f6dc9357SAndroid Build Coastguard Worker // printf("\n\nsetlocale(LC_CTYPE, NULL) : return : ");
588*f6dc9357SAndroid Build Coastguard Worker const char *s = setlocale(LC_CTYPE, NULL);
589*f6dc9357SAndroid Build Coastguard Worker if (!s)
590*f6dc9357SAndroid Build Coastguard Worker {
591*f6dc9357SAndroid Build Coastguard Worker // printf("[NULL]\n");
592*f6dc9357SAndroid Build Coastguard Worker s = "C";
593*f6dc9357SAndroid Build Coastguard Worker }
594*f6dc9357SAndroid Build Coastguard Worker else
595*f6dc9357SAndroid Build Coastguard Worker {
596*f6dc9357SAndroid Build Coastguard Worker // ubuntu returns "C" after program start
597*f6dc9357SAndroid Build Coastguard Worker // printf("\"%s\"\n", s);
598*f6dc9357SAndroid Build Coastguard Worker }
599*f6dc9357SAndroid Build Coastguard Worker return s;
600*f6dc9357SAndroid Build Coastguard Worker #elif defined(LOCALE_IS_UTF8)
601*f6dc9357SAndroid Build Coastguard Worker return "utf8";
602*f6dc9357SAndroid Build Coastguard Worker #else
603*f6dc9357SAndroid Build Coastguard Worker return "C";
604*f6dc9357SAndroid Build Coastguard Worker #endif
605*f6dc9357SAndroid Build Coastguard Worker }
606*f6dc9357SAndroid Build Coastguard Worker
607*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
Set_ForceToUTF8(bool)608*f6dc9357SAndroid Build Coastguard Worker static void Set_ForceToUTF8(bool) {}
609*f6dc9357SAndroid Build Coastguard Worker #else
Set_ForceToUTF8(bool val)610*f6dc9357SAndroid Build Coastguard Worker static void Set_ForceToUTF8(bool val) { g_ForceToUTF8 = val; }
611*f6dc9357SAndroid Build Coastguard Worker #endif
612*f6dc9357SAndroid Build Coastguard Worker
Is_Default_Basic_Locale(const char * locale)613*f6dc9357SAndroid Build Coastguard Worker static bool Is_Default_Basic_Locale(const char *locale)
614*f6dc9357SAndroid Build Coastguard Worker {
615*f6dc9357SAndroid Build Coastguard Worker const AString a (locale);
616*f6dc9357SAndroid Build Coastguard Worker if (a.IsEqualTo_Ascii_NoCase("")
617*f6dc9357SAndroid Build Coastguard Worker || a.IsEqualTo_Ascii_NoCase("C")
618*f6dc9357SAndroid Build Coastguard Worker || a.IsEqualTo_Ascii_NoCase("POSIX"))
619*f6dc9357SAndroid Build Coastguard Worker return true;
620*f6dc9357SAndroid Build Coastguard Worker return false;
621*f6dc9357SAndroid Build Coastguard Worker }
622*f6dc9357SAndroid Build Coastguard Worker
Is_Default_Basic_Locale()623*f6dc9357SAndroid Build Coastguard Worker static bool Is_Default_Basic_Locale()
624*f6dc9357SAndroid Build Coastguard Worker {
625*f6dc9357SAndroid Build Coastguard Worker return Is_Default_Basic_Locale(GetLocale());
626*f6dc9357SAndroid Build Coastguard Worker }
627*f6dc9357SAndroid Build Coastguard Worker
628*f6dc9357SAndroid Build Coastguard Worker
MY_SetLocale()629*f6dc9357SAndroid Build Coastguard Worker void MY_SetLocale()
630*f6dc9357SAndroid Build Coastguard Worker {
631*f6dc9357SAndroid Build Coastguard Worker #ifdef ENV_HAVE_LOCALE
632*f6dc9357SAndroid Build Coastguard Worker /*
633*f6dc9357SAndroid Build Coastguard Worker {
634*f6dc9357SAndroid Build Coastguard Worker const char *s = GetLocale();
635*f6dc9357SAndroid Build Coastguard Worker printf("\nGetLocale() : returned : \"%s\"\n", s);
636*f6dc9357SAndroid Build Coastguard Worker }
637*f6dc9357SAndroid Build Coastguard Worker */
638*f6dc9357SAndroid Build Coastguard Worker
639*f6dc9357SAndroid Build Coastguard Worker unsigned start = 0;
640*f6dc9357SAndroid Build Coastguard Worker // unsigned lim = 0;
641*f6dc9357SAndroid Build Coastguard Worker unsigned lim = 3;
642*f6dc9357SAndroid Build Coastguard Worker
643*f6dc9357SAndroid Build Coastguard Worker /*
644*f6dc9357SAndroid Build Coastguard Worker #define MY_SET_LOCALE_FLAGS__FROM_ENV 1
645*f6dc9357SAndroid Build Coastguard Worker #define MY_SET_LOCALE_FLAGS__TRY_UTF8 2
646*f6dc9357SAndroid Build Coastguard Worker
647*f6dc9357SAndroid Build Coastguard Worker unsigned flags =
648*f6dc9357SAndroid Build Coastguard Worker MY_SET_LOCALE_FLAGS__FROM_ENV |
649*f6dc9357SAndroid Build Coastguard Worker MY_SET_LOCALE_FLAGS__TRY_UTF8
650*f6dc9357SAndroid Build Coastguard Worker
651*f6dc9357SAndroid Build Coastguard Worker if (flags != 0)
652*f6dc9357SAndroid Build Coastguard Worker {
653*f6dc9357SAndroid Build Coastguard Worker if (flags & MY_SET_LOCALE_FLAGS__FROM_ENV)
654*f6dc9357SAndroid Build Coastguard Worker lim = (flags & MY_SET_LOCALE_FLAGS__TRY_UTF8) ? 3 : 1;
655*f6dc9357SAndroid Build Coastguard Worker else
656*f6dc9357SAndroid Build Coastguard Worker {
657*f6dc9357SAndroid Build Coastguard Worker start = 1;
658*f6dc9357SAndroid Build Coastguard Worker lim = 2;
659*f6dc9357SAndroid Build Coastguard Worker }
660*f6dc9357SAndroid Build Coastguard Worker }
661*f6dc9357SAndroid Build Coastguard Worker */
662*f6dc9357SAndroid Build Coastguard Worker
663*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = start; i < lim; i++)
664*f6dc9357SAndroid Build Coastguard Worker {
665*f6dc9357SAndroid Build Coastguard Worker /*
666*f6dc9357SAndroid Build Coastguard Worker man7: "If locale is an empty string, "", each part of the locale that
667*f6dc9357SAndroid Build Coastguard Worker should be modified is set according to the environment variables.
668*f6dc9357SAndroid Build Coastguard Worker for glibc: glibc, first from the user's environment variables:
669*f6dc9357SAndroid Build Coastguard Worker 1) the environment variable LC_ALL,
670*f6dc9357SAndroid Build Coastguard Worker 2) environment variable with the same name as the category (see the
671*f6dc9357SAndroid Build Coastguard Worker 3) the environment variable LANG
672*f6dc9357SAndroid Build Coastguard Worker The locale "C" or "POSIX" is a portable locale; it exists on all conforming systems.
673*f6dc9357SAndroid Build Coastguard Worker
674*f6dc9357SAndroid Build Coastguard Worker for WIN32 : MSDN :
675*f6dc9357SAndroid Build Coastguard Worker Sets the locale to the default, which is the user-default
676*f6dc9357SAndroid Build Coastguard Worker ANSI code page obtained from the operating system.
677*f6dc9357SAndroid Build Coastguard Worker The locale name is set to the value returned by GetUserDefaultLocaleName.
678*f6dc9357SAndroid Build Coastguard Worker The code page is set to the value returned by GetACP
679*f6dc9357SAndroid Build Coastguard Worker */
680*f6dc9357SAndroid Build Coastguard Worker const char *newLocale = "";
681*f6dc9357SAndroid Build Coastguard Worker
682*f6dc9357SAndroid Build Coastguard Worker #ifdef __APPLE__
683*f6dc9357SAndroid Build Coastguard Worker
684*f6dc9357SAndroid Build Coastguard Worker /* look also CFLocale
685*f6dc9357SAndroid Build Coastguard Worker there is no C.UTF-8 in macos
686*f6dc9357SAndroid Build Coastguard Worker macos has UTF-8 locale only with some language like en_US.UTF-8
687*f6dc9357SAndroid Build Coastguard Worker what is best way to set UTF-8 locale in macos? */
688*f6dc9357SAndroid Build Coastguard Worker if (i == 1)
689*f6dc9357SAndroid Build Coastguard Worker newLocale = "en_US.UTF-8";
690*f6dc9357SAndroid Build Coastguard Worker
691*f6dc9357SAndroid Build Coastguard Worker /* file open with non-utf8 sequencies return
692*f6dc9357SAndroid Build Coastguard Worker #define EILSEQ 92 // "Illegal byte sequence"
693*f6dc9357SAndroid Build Coastguard Worker */
694*f6dc9357SAndroid Build Coastguard Worker #else
695*f6dc9357SAndroid Build Coastguard Worker // newLocale = "C";
696*f6dc9357SAndroid Build Coastguard Worker if (i == 1)
697*f6dc9357SAndroid Build Coastguard Worker {
698*f6dc9357SAndroid Build Coastguard Worker newLocale = "C.UTF-8"; // main UTF-8 locale in ubuntu
699*f6dc9357SAndroid Build Coastguard Worker // newLocale = ".utf8"; // supported in new Windows 10 build 17134 (April 2018 Update), the Universal C Runtime
700*f6dc9357SAndroid Build Coastguard Worker // newLocale = "en_US.utf8"; // supported by ubuntu ?
701*f6dc9357SAndroid Build Coastguard Worker // newLocale = "en_US.UTF-8";
702*f6dc9357SAndroid Build Coastguard Worker /* setlocale() in ubuntu allows locales with minor chracter changes in strings
703*f6dc9357SAndroid Build Coastguard Worker "en_US.UTF-8" / "en_US.utf8" */
704*f6dc9357SAndroid Build Coastguard Worker }
705*f6dc9357SAndroid Build Coastguard Worker
706*f6dc9357SAndroid Build Coastguard Worker #endif
707*f6dc9357SAndroid Build Coastguard Worker
708*f6dc9357SAndroid Build Coastguard Worker // printf("\nsetlocale(LC_ALL, \"%s\") : returned: ", newLocale);
709*f6dc9357SAndroid Build Coastguard Worker
710*f6dc9357SAndroid Build Coastguard Worker // const char *s =
711*f6dc9357SAndroid Build Coastguard Worker setlocale(LC_ALL, newLocale);
712*f6dc9357SAndroid Build Coastguard Worker
713*f6dc9357SAndroid Build Coastguard Worker /*
714*f6dc9357SAndroid Build Coastguard Worker if (!s)
715*f6dc9357SAndroid Build Coastguard Worker printf("NULL: can't set locale");
716*f6dc9357SAndroid Build Coastguard Worker else
717*f6dc9357SAndroid Build Coastguard Worker printf("\"%s\"\n", s);
718*f6dc9357SAndroid Build Coastguard Worker */
719*f6dc9357SAndroid Build Coastguard Worker
720*f6dc9357SAndroid Build Coastguard Worker // request curent locale of program
721*f6dc9357SAndroid Build Coastguard Worker const char *locale = GetLocale();
722*f6dc9357SAndroid Build Coastguard Worker if (locale)
723*f6dc9357SAndroid Build Coastguard Worker {
724*f6dc9357SAndroid Build Coastguard Worker AString a (locale);
725*f6dc9357SAndroid Build Coastguard Worker a.MakeLower_Ascii();
726*f6dc9357SAndroid Build Coastguard Worker // if (a.Find("utf") >= 0)
727*f6dc9357SAndroid Build Coastguard Worker {
728*f6dc9357SAndroid Build Coastguard Worker if (IsNativeUTF8())
729*f6dc9357SAndroid Build Coastguard Worker {
730*f6dc9357SAndroid Build Coastguard Worker Set_ForceToUTF8(true);
731*f6dc9357SAndroid Build Coastguard Worker return;
732*f6dc9357SAndroid Build Coastguard Worker }
733*f6dc9357SAndroid Build Coastguard Worker }
734*f6dc9357SAndroid Build Coastguard Worker if (!Is_Default_Basic_Locale(locale))
735*f6dc9357SAndroid Build Coastguard Worker {
736*f6dc9357SAndroid Build Coastguard Worker // if there is some non-default and non-utf locale, we want to use it
737*f6dc9357SAndroid Build Coastguard Worker break; // comment it for debug
738*f6dc9357SAndroid Build Coastguard Worker }
739*f6dc9357SAndroid Build Coastguard Worker }
740*f6dc9357SAndroid Build Coastguard Worker }
741*f6dc9357SAndroid Build Coastguard Worker
742*f6dc9357SAndroid Build Coastguard Worker if (IsNativeUTF8())
743*f6dc9357SAndroid Build Coastguard Worker {
744*f6dc9357SAndroid Build Coastguard Worker Set_ForceToUTF8(true);
745*f6dc9357SAndroid Build Coastguard Worker return;
746*f6dc9357SAndroid Build Coastguard Worker }
747*f6dc9357SAndroid Build Coastguard Worker
748*f6dc9357SAndroid Build Coastguard Worker if (Is_Default_Basic_Locale())
749*f6dc9357SAndroid Build Coastguard Worker {
750*f6dc9357SAndroid Build Coastguard Worker Set_ForceToUTF8(true);
751*f6dc9357SAndroid Build Coastguard Worker return;
752*f6dc9357SAndroid Build Coastguard Worker }
753*f6dc9357SAndroid Build Coastguard Worker
754*f6dc9357SAndroid Build Coastguard Worker Set_ForceToUTF8(false);
755*f6dc9357SAndroid Build Coastguard Worker
756*f6dc9357SAndroid Build Coastguard Worker #elif defined(LOCALE_IS_UTF8)
757*f6dc9357SAndroid Build Coastguard Worker // assume LC_CTYPE="utf8"
758*f6dc9357SAndroid Build Coastguard Worker #else
759*f6dc9357SAndroid Build Coastguard Worker // assume LC_CTYPE="C"
760*f6dc9357SAndroid Build Coastguard Worker #endif
761*f6dc9357SAndroid Build Coastguard Worker }
762*f6dc9357SAndroid Build Coastguard Worker #endif
763