xref: /aoo41x/main/sal/osl/w32/nlsupport.c (revision 647f063d)
1*647f063dSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*647f063dSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*647f063dSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*647f063dSAndrew Rist  * distributed with this work for additional information
6*647f063dSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*647f063dSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*647f063dSAndrew Rist  * "License"); you may not use this file except in compliance
9*647f063dSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*647f063dSAndrew Rist  *
11*647f063dSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*647f063dSAndrew Rist  *
13*647f063dSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*647f063dSAndrew Rist  * software distributed under the License is distributed on an
15*647f063dSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*647f063dSAndrew Rist  * KIND, either express or implied.  See the License for the
17*647f063dSAndrew Rist  * specific language governing permissions and limitations
18*647f063dSAndrew Rist  * under the License.
19*647f063dSAndrew Rist  *
20*647f063dSAndrew Rist  *************************************************************/
21*647f063dSAndrew Rist 
22*647f063dSAndrew 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 
78cdf0e10cSrcweir         remeber: 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 }
226cdf0e10cSrcweir 
227cdf0e10cSrcweir 
228