xref: /trunk/main/sal/osl/w32/nlsupport.c (revision 534d93521fb9d960038706348aeef53f37423a94)
1647f063dSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3647f063dSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4647f063dSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5647f063dSAndrew Rist  * distributed with this work for additional information
6647f063dSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7647f063dSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8647f063dSAndrew Rist  * "License"); you may not use this file except in compliance
9647f063dSAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11647f063dSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13647f063dSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14647f063dSAndrew Rist  * software distributed under the License is distributed on an
15647f063dSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16647f063dSAndrew Rist  * KIND, either express or implied.  See the License for the
17647f063dSAndrew Rist  * specific language governing permissions and limitations
18647f063dSAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20647f063dSAndrew Rist  *************************************************************/
21647f063dSAndrew Rist 
22647f063dSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #define UNICODE
25cdf0e10cSrcweir #ifdef _MSC_VER
26cdf0e10cSrcweir #pragma warning(push,1) /* disable warnings within system headers */
27cdf0e10cSrcweir #endif
28cdf0e10cSrcweir #include <windows.h>
29cdf0e10cSrcweir #ifdef _MSC_VER
30cdf0e10cSrcweir #pragma warning(pop)
31cdf0e10cSrcweir #endif
32cdf0e10cSrcweir #include <wchar.h>
33cdf0e10cSrcweir 
34cdf0e10cSrcweir #include <osl/mutex.h>
35cdf0e10cSrcweir #include <osl/nlsupport.h>
36cdf0e10cSrcweir #include <osl/diagnose.h>
37cdf0e10cSrcweir #include <osl/process.h>
38cdf0e10cSrcweir #include <rtl/tencinfo.h>
39cdf0e10cSrcweir 
40cdf0e10cSrcweir struct EnumLocalesParams
41cdf0e10cSrcweir {
42cdf0e10cSrcweir     WCHAR Language[3];
43cdf0e10cSrcweir     WCHAR Country[3];
44cdf0e10cSrcweir     LCID  Locale;
45cdf0e10cSrcweir };
46cdf0e10cSrcweir 
47cdf0e10cSrcweir static DWORD g_dwTLSLocaleEncId = (DWORD) -1;
48cdf0e10cSrcweir 
49cdf0e10cSrcweir /*****************************************************************************/
50cdf0e10cSrcweir /* callback function test
51cdf0e10cSrcweir /*
52cdf0e10cSrcweir /* osl_getTextEncodingFromLocale calls EnumSystemLocalesA, so that we don't
53cdf0e10cSrcweir /* need to provide a unicode wrapper for this function under Win9x
54cdf0e10cSrcweir /* that means the callback function has an ansi prototype and receives
55cdf0e10cSrcweir /* the locale strings as ansi strings
56cdf0e10cSrcweir /*****************************************************************************/
57cdf0e10cSrcweir 
EnumLocalesProcA(LPSTR lpLocaleStringA)58cdf0e10cSrcweir BOOL CALLBACK EnumLocalesProcA( LPSTR lpLocaleStringA )
59cdf0e10cSrcweir {
60cdf0e10cSrcweir     struct EnumLocalesParams * params;
61cdf0e10cSrcweir 
62cdf0e10cSrcweir     LCID  localeId;
63cdf0e10cSrcweir     LPSTR pszEndA;
64cdf0e10cSrcweir 
65cdf0e10cSrcweir     WCHAR langCode[4];
66cdf0e10cSrcweir 
67cdf0e10cSrcweir     /* convert hex-string to LCID */
68cdf0e10cSrcweir     localeId = strtol( lpLocaleStringA, &pszEndA, 16 );
69cdf0e10cSrcweir 
70cdf0e10cSrcweir     /* check params received via TLS */
71cdf0e10cSrcweir     params = (struct EnumLocalesParams *) TlsGetValue( g_dwTLSLocaleEncId );
72cdf0e10cSrcweir     if( NULL == params || '\0' == params->Language[0] )
73cdf0e10cSrcweir         return FALSE;
74cdf0e10cSrcweir 
75cdf0e10cSrcweir     /*
76cdf0e10cSrcweir         get the ISO language code for this locale
77cdf0e10cSrcweir 
78*86e1cf34SPedro Giffuni         remember: we call the GetLocaleInfoW function
79cdf0e10cSrcweir         because the ansi version of this function returns
80cdf0e10cSrcweir         an error under WinNT/2000 when called with an
81cdf0e10cSrcweir         unicode only lcid
82cdf0e10cSrcweir     */
83cdf0e10cSrcweir     if( GetLocaleInfo( localeId, LOCALE_SISO639LANGNAME , langCode, 4 ) )
84cdf0e10cSrcweir     {
85cdf0e10cSrcweir         WCHAR ctryCode[4];
86cdf0e10cSrcweir 
87cdf0e10cSrcweir         /* continue if language code does not match */
88cdf0e10cSrcweir         if( 0 != wcscmp( langCode, params->Language ) )
89cdf0e10cSrcweir             return TRUE;
90cdf0e10cSrcweir 
91cdf0e10cSrcweir         /* check if country code is set and equals the current locale */
92cdf0e10cSrcweir         if( '\0' != params->Country[0] && GetLocaleInfo( localeId, LOCALE_SISO3166CTRYNAME , ctryCode, 4 ) )
93cdf0e10cSrcweir         {
94cdf0e10cSrcweir             /* save return value in TLS and break if  found desired locale */
95cdf0e10cSrcweir             if( 0 == wcscmp( ctryCode, params->Country ) )
96cdf0e10cSrcweir             {
97cdf0e10cSrcweir                 params->Locale = localeId;
98cdf0e10cSrcweir                 return FALSE;
99cdf0e10cSrcweir             }
100cdf0e10cSrcweir         }
101cdf0e10cSrcweir         else
102cdf0e10cSrcweir         {
103cdf0e10cSrcweir             /* fill with default values for that language */
104cdf0e10cSrcweir             LANGID langId = LANGIDFROMLCID( localeId );
105cdf0e10cSrcweir 
106cdf0e10cSrcweir             /* exchange sublanguage with SUBLANG_NEUTRAL */
107cdf0e10cSrcweir             langId = MAKELANGID( PRIMARYLANGID( langId ), SUBLANG_NEUTRAL );
108cdf0e10cSrcweir 
109cdf0e10cSrcweir             /* and use default sorting order */
110cdf0e10cSrcweir             params->Locale = MAKELCID( langId, SORT_DEFAULT );
111cdf0e10cSrcweir 
112cdf0e10cSrcweir             return FALSE;
113cdf0e10cSrcweir         }
114cdf0e10cSrcweir     }
115cdf0e10cSrcweir 
116cdf0e10cSrcweir     /* retry by going on */
117cdf0e10cSrcweir     return TRUE;
118cdf0e10cSrcweir }
119cdf0e10cSrcweir 
120cdf0e10cSrcweir 
121cdf0e10cSrcweir /*****************************************************************************/
122cdf0e10cSrcweir /* GetTextEncodingFromLCID
123cdf0e10cSrcweir /*****************************************************************************/
124cdf0e10cSrcweir 
GetTextEncodingFromLCID(LCID localeId)125cdf0e10cSrcweir rtl_TextEncoding GetTextEncodingFromLCID( LCID localeId )
126cdf0e10cSrcweir {
127cdf0e10cSrcweir     rtl_TextEncoding Encoding = RTL_TEXTENCODING_DONTKNOW;
128cdf0e10cSrcweir     WCHAR ansiCP[6];
129cdf0e10cSrcweir 
130cdf0e10cSrcweir     /* query ansi codepage for given locale */
131cdf0e10cSrcweir     if( localeId && GetLocaleInfo( localeId, LOCALE_IDEFAULTANSICODEPAGE, ansiCP, 6 ) )
132cdf0e10cSrcweir     {
133cdf0e10cSrcweir         /* if GetLocaleInfo returns "0", it is a UNICODE only locale */
134cdf0e10cSrcweir         if( 0 != wcscmp( ansiCP, L"0" ) )
135cdf0e10cSrcweir         {
136cdf0e10cSrcweir             WCHAR *pwcEnd;
137cdf0e10cSrcweir             UINT  codepage;
138cdf0e10cSrcweir 
139cdf0e10cSrcweir             /* values returned from GetLocaleInfo are dezimal based */
140cdf0e10cSrcweir             codepage = wcstol( ansiCP, &pwcEnd, 10 );
141cdf0e10cSrcweir 
142cdf0e10cSrcweir             /* find matching rtl encoding */
143cdf0e10cSrcweir             Encoding = rtl_getTextEncodingFromWindowsCodePage( codepage );
144cdf0e10cSrcweir         }
145cdf0e10cSrcweir         else
146cdf0e10cSrcweir             Encoding = RTL_TEXTENCODING_UNICODE;
147cdf0e10cSrcweir     }
148cdf0e10cSrcweir 
149cdf0e10cSrcweir     return Encoding;
150cdf0e10cSrcweir }
151cdf0e10cSrcweir 
152cdf0e10cSrcweir 
153cdf0e10cSrcweir /*****************************************************************************/
154cdf0e10cSrcweir /* osl_getTextEncodingFromLocale
155cdf0e10cSrcweir /*****************************************************************************/
156cdf0e10cSrcweir 
osl_getTextEncodingFromLocale(rtl_Locale * pLocale)157cdf0e10cSrcweir rtl_TextEncoding SAL_CALL osl_getTextEncodingFromLocale( rtl_Locale * pLocale )
158cdf0e10cSrcweir {
159cdf0e10cSrcweir     struct EnumLocalesParams params = { L"", L"", 0 };
160cdf0e10cSrcweir 
161cdf0e10cSrcweir     /* initialise global TLS id */
162cdf0e10cSrcweir     if( (DWORD) -1 == g_dwTLSLocaleEncId )
163cdf0e10cSrcweir     {
164cdf0e10cSrcweir         oslMutex globalMutex = * osl_getGlobalMutex();
165cdf0e10cSrcweir 
166cdf0e10cSrcweir         /* initializing must be thread save */
167cdf0e10cSrcweir         osl_acquireMutex( globalMutex );
168cdf0e10cSrcweir 
169cdf0e10cSrcweir         if( (DWORD) -1 == g_dwTLSLocaleEncId )
170cdf0e10cSrcweir             g_dwTLSLocaleEncId = TlsAlloc();
171cdf0e10cSrcweir 
172cdf0e10cSrcweir         osl_releaseMutex( globalMutex );
173cdf0e10cSrcweir     }
174cdf0e10cSrcweir 
175cdf0e10cSrcweir     /* if pLocale is NULL, use process locale as default */
176cdf0e10cSrcweir     if( NULL == pLocale )
177cdf0e10cSrcweir         osl_getProcessLocale( &pLocale );
178cdf0e10cSrcweir 
179cdf0e10cSrcweir     /* copy in parameters to structure */
180cdf0e10cSrcweir     if( pLocale && pLocale->Language )
181cdf0e10cSrcweir     {
182cdf0e10cSrcweir         wcscpy( params.Language, pLocale->Language->buffer );
183cdf0e10cSrcweir 
184cdf0e10cSrcweir         if( pLocale->Country )
185cdf0e10cSrcweir             wcscpy( params.Country, pLocale->Country->buffer );
186cdf0e10cSrcweir 
187cdf0e10cSrcweir         /* save pointer to local structure in TLS */
188cdf0e10cSrcweir         TlsSetValue( g_dwTLSLocaleEncId, &params );
189cdf0e10cSrcweir 
190cdf0e10cSrcweir         /* enum all locales known to Windows */
191cdf0e10cSrcweir         EnumSystemLocalesA( EnumLocalesProcA, LCID_SUPPORTED );
192cdf0e10cSrcweir 
193cdf0e10cSrcweir         /* use the LCID found in iteration */
194cdf0e10cSrcweir         return GetTextEncodingFromLCID( params.Locale );
195cdf0e10cSrcweir     }
196cdf0e10cSrcweir 
197cdf0e10cSrcweir     return RTL_TEXTENCODING_DONTKNOW;
198cdf0e10cSrcweir }
199cdf0e10cSrcweir 
200cdf0e10cSrcweir /*****************************************************************************/
201cdf0e10cSrcweir /* imp_getProcessLocale
202cdf0e10cSrcweir /*****************************************************************************/
203cdf0e10cSrcweir 
_imp_getProcessLocale(rtl_Locale ** ppLocale)204cdf0e10cSrcweir void _imp_getProcessLocale( rtl_Locale ** ppLocale )
205cdf0e10cSrcweir {
206cdf0e10cSrcweir     WCHAR langCode[4];
207cdf0e10cSrcweir     WCHAR ctryCode[4];
208cdf0e10cSrcweir     LCID  localeId;
209cdf0e10cSrcweir 
210cdf0e10cSrcweir     OSL_ASSERT( ppLocale );
211cdf0e10cSrcweir 
212cdf0e10cSrcweir     /* get the LCID to retrieve information from */
213cdf0e10cSrcweir     localeId = GetUserDefaultLCID();
214cdf0e10cSrcweir 
215cdf0e10cSrcweir     /* call GetLocaleInfo to retrieve the iso codes */
216cdf0e10cSrcweir     if( GetLocaleInfo( localeId, LOCALE_SISO639LANGNAME , langCode, 4 )  &&
217cdf0e10cSrcweir         GetLocaleInfo( localeId, LOCALE_SISO3166CTRYNAME , ctryCode, 4 ) )
218cdf0e10cSrcweir     {
219cdf0e10cSrcweir         *ppLocale = rtl_locale_register( langCode, ctryCode, L"" );
220cdf0e10cSrcweir     }
221cdf0e10cSrcweir     else
222cdf0e10cSrcweir     {
223cdf0e10cSrcweir         *ppLocale = rtl_locale_register( L"C", L"", L"" );
224cdf0e10cSrcweir     }
225cdf0e10cSrcweir }
226