xref: /AOO41X/main/sal/osl/w32/nlsupport.c (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir #define UNICODE
29*cdf0e10cSrcweir #ifdef _MSC_VER
30*cdf0e10cSrcweir #pragma warning(push,1) /* disable warnings within system headers */
31*cdf0e10cSrcweir #endif
32*cdf0e10cSrcweir #include <windows.h>
33*cdf0e10cSrcweir #ifdef _MSC_VER
34*cdf0e10cSrcweir #pragma warning(pop)
35*cdf0e10cSrcweir #endif
36*cdf0e10cSrcweir #include <wchar.h>
37*cdf0e10cSrcweir 
38*cdf0e10cSrcweir #include <osl/mutex.h>
39*cdf0e10cSrcweir #include <osl/nlsupport.h>
40*cdf0e10cSrcweir #include <osl/diagnose.h>
41*cdf0e10cSrcweir #include <osl/process.h>
42*cdf0e10cSrcweir #include <rtl/tencinfo.h>
43*cdf0e10cSrcweir 
44*cdf0e10cSrcweir struct EnumLocalesParams
45*cdf0e10cSrcweir {
46*cdf0e10cSrcweir 	WCHAR Language[3];
47*cdf0e10cSrcweir 	WCHAR Country[3];
48*cdf0e10cSrcweir 	LCID  Locale;
49*cdf0e10cSrcweir };
50*cdf0e10cSrcweir 
51*cdf0e10cSrcweir static DWORD g_dwTLSLocaleEncId = (DWORD) -1;
52*cdf0e10cSrcweir 
53*cdf0e10cSrcweir /*****************************************************************************/
54*cdf0e10cSrcweir /* callback function test
55*cdf0e10cSrcweir /*
56*cdf0e10cSrcweir /* osl_getTextEncodingFromLocale calls EnumSystemLocalesA, so that we don't
57*cdf0e10cSrcweir /* need to provide a unicode wrapper for this function under Win9x
58*cdf0e10cSrcweir /* that means the callback function has an ansi prototype and receives
59*cdf0e10cSrcweir /* the locale strings as ansi strings
60*cdf0e10cSrcweir /*****************************************************************************/
61*cdf0e10cSrcweir 
62*cdf0e10cSrcweir BOOL CALLBACK EnumLocalesProcA( LPSTR lpLocaleStringA )
63*cdf0e10cSrcweir {
64*cdf0e10cSrcweir 	struct EnumLocalesParams * params;
65*cdf0e10cSrcweir 
66*cdf0e10cSrcweir 	LCID  localeId;
67*cdf0e10cSrcweir 	LPSTR pszEndA;
68*cdf0e10cSrcweir 
69*cdf0e10cSrcweir 	WCHAR langCode[4];
70*cdf0e10cSrcweir 
71*cdf0e10cSrcweir 	/* convert hex-string to LCID */
72*cdf0e10cSrcweir     localeId = strtol( lpLocaleStringA, &pszEndA, 16 );
73*cdf0e10cSrcweir 
74*cdf0e10cSrcweir 	/* check params received via TLS */
75*cdf0e10cSrcweir 	params = (struct EnumLocalesParams *) TlsGetValue( g_dwTLSLocaleEncId );
76*cdf0e10cSrcweir 	if( NULL == params || '\0' == params->Language[0] )
77*cdf0e10cSrcweir 		return FALSE;
78*cdf0e10cSrcweir 
79*cdf0e10cSrcweir 	/*
80*cdf0e10cSrcweir         get the ISO language code for this locale
81*cdf0e10cSrcweir 
82*cdf0e10cSrcweir         remeber: we call the GetLocaleInfoW function
83*cdf0e10cSrcweir         because the ansi version of this function returns
84*cdf0e10cSrcweir         an error under WinNT/2000 when called with an
85*cdf0e10cSrcweir         unicode only lcid
86*cdf0e10cSrcweir     */
87*cdf0e10cSrcweir 	if( GetLocaleInfo( localeId, LOCALE_SISO639LANGNAME , langCode, 4 ) )
88*cdf0e10cSrcweir 	{
89*cdf0e10cSrcweir 		WCHAR ctryCode[4];
90*cdf0e10cSrcweir 
91*cdf0e10cSrcweir 		/* continue if language code does not match */
92*cdf0e10cSrcweir 		if( 0 != wcscmp( langCode, params->Language ) )
93*cdf0e10cSrcweir 			return TRUE;
94*cdf0e10cSrcweir 
95*cdf0e10cSrcweir 		/* check if country code is set and equals the current locale */
96*cdf0e10cSrcweir 		if( '\0' != params->Country[0] && GetLocaleInfo( localeId, LOCALE_SISO3166CTRYNAME , ctryCode, 4 ) )
97*cdf0e10cSrcweir 		{
98*cdf0e10cSrcweir 			/* save return value in TLS and break if  found desired locale */
99*cdf0e10cSrcweir 			if( 0 == wcscmp( ctryCode, params->Country ) )
100*cdf0e10cSrcweir 			{
101*cdf0e10cSrcweir 				params->Locale = localeId;
102*cdf0e10cSrcweir 				return FALSE;
103*cdf0e10cSrcweir 			}
104*cdf0e10cSrcweir 		}
105*cdf0e10cSrcweir 		else
106*cdf0e10cSrcweir 		{
107*cdf0e10cSrcweir 			/* fill with default values for that language */
108*cdf0e10cSrcweir 			LANGID langId = LANGIDFROMLCID( localeId );
109*cdf0e10cSrcweir 
110*cdf0e10cSrcweir 			/* exchange sublanguage with SUBLANG_NEUTRAL */
111*cdf0e10cSrcweir 			langId = MAKELANGID( PRIMARYLANGID( langId ), SUBLANG_NEUTRAL );
112*cdf0e10cSrcweir 
113*cdf0e10cSrcweir 			/* and use default sorting order */
114*cdf0e10cSrcweir 			params->Locale = MAKELCID( langId, SORT_DEFAULT );
115*cdf0e10cSrcweir 
116*cdf0e10cSrcweir 			return FALSE;
117*cdf0e10cSrcweir 		}
118*cdf0e10cSrcweir 	}
119*cdf0e10cSrcweir 
120*cdf0e10cSrcweir 	/* retry by going on */
121*cdf0e10cSrcweir 	return TRUE;
122*cdf0e10cSrcweir }
123*cdf0e10cSrcweir 
124*cdf0e10cSrcweir 
125*cdf0e10cSrcweir /*****************************************************************************/
126*cdf0e10cSrcweir /* GetTextEncodingFromLCID
127*cdf0e10cSrcweir /*****************************************************************************/
128*cdf0e10cSrcweir 
129*cdf0e10cSrcweir rtl_TextEncoding GetTextEncodingFromLCID( LCID localeId )
130*cdf0e10cSrcweir {
131*cdf0e10cSrcweir 	rtl_TextEncoding Encoding = RTL_TEXTENCODING_DONTKNOW;
132*cdf0e10cSrcweir 	WCHAR ansiCP[6];
133*cdf0e10cSrcweir 
134*cdf0e10cSrcweir 	/* query ansi codepage for given locale */
135*cdf0e10cSrcweir 	if( localeId && GetLocaleInfo( localeId, LOCALE_IDEFAULTANSICODEPAGE, ansiCP, 6 ) )
136*cdf0e10cSrcweir 	{
137*cdf0e10cSrcweir 		/* if GetLocaleInfo returns "0", it is a UNICODE only locale */
138*cdf0e10cSrcweir 		if( 0 != wcscmp( ansiCP, L"0" ) )
139*cdf0e10cSrcweir 		{
140*cdf0e10cSrcweir 			WCHAR *pwcEnd;
141*cdf0e10cSrcweir 			UINT  codepage;
142*cdf0e10cSrcweir 
143*cdf0e10cSrcweir 			/* values returned from GetLocaleInfo are dezimal based */
144*cdf0e10cSrcweir 			codepage = wcstol( ansiCP, &pwcEnd, 10 );
145*cdf0e10cSrcweir 
146*cdf0e10cSrcweir 			/* find matching rtl encoding */
147*cdf0e10cSrcweir 			Encoding = rtl_getTextEncodingFromWindowsCodePage( codepage );
148*cdf0e10cSrcweir 		}
149*cdf0e10cSrcweir 		else
150*cdf0e10cSrcweir 			Encoding = RTL_TEXTENCODING_UNICODE;
151*cdf0e10cSrcweir 	}
152*cdf0e10cSrcweir 
153*cdf0e10cSrcweir 	return Encoding;
154*cdf0e10cSrcweir }
155*cdf0e10cSrcweir 
156*cdf0e10cSrcweir 
157*cdf0e10cSrcweir /*****************************************************************************/
158*cdf0e10cSrcweir /* osl_getTextEncodingFromLocale
159*cdf0e10cSrcweir /*****************************************************************************/
160*cdf0e10cSrcweir 
161*cdf0e10cSrcweir rtl_TextEncoding SAL_CALL osl_getTextEncodingFromLocale( rtl_Locale * pLocale )
162*cdf0e10cSrcweir {
163*cdf0e10cSrcweir 	struct EnumLocalesParams params = { L"", L"", 0 };
164*cdf0e10cSrcweir 
165*cdf0e10cSrcweir 	/* initialise global TLS id */
166*cdf0e10cSrcweir 	if( (DWORD) -1 == g_dwTLSLocaleEncId )
167*cdf0e10cSrcweir 	{
168*cdf0e10cSrcweir 		oslMutex globalMutex = * osl_getGlobalMutex();
169*cdf0e10cSrcweir 
170*cdf0e10cSrcweir 		/* initializing must be thread save */
171*cdf0e10cSrcweir 		osl_acquireMutex( globalMutex );
172*cdf0e10cSrcweir 
173*cdf0e10cSrcweir 		if( (DWORD) -1 == g_dwTLSLocaleEncId )
174*cdf0e10cSrcweir 			g_dwTLSLocaleEncId = TlsAlloc();
175*cdf0e10cSrcweir 
176*cdf0e10cSrcweir 		osl_releaseMutex( globalMutex );
177*cdf0e10cSrcweir 	}
178*cdf0e10cSrcweir 
179*cdf0e10cSrcweir     /* if pLocale is NULL, use process locale as default */
180*cdf0e10cSrcweir     if( NULL == pLocale )
181*cdf0e10cSrcweir         osl_getProcessLocale( &pLocale );
182*cdf0e10cSrcweir 
183*cdf0e10cSrcweir 	/* copy in parameters to structure */
184*cdf0e10cSrcweir 	if( pLocale && pLocale->Language )
185*cdf0e10cSrcweir 	{
186*cdf0e10cSrcweir 		wcscpy( params.Language, pLocale->Language->buffer );
187*cdf0e10cSrcweir 
188*cdf0e10cSrcweir 		if( pLocale->Country )
189*cdf0e10cSrcweir 			wcscpy( params.Country, pLocale->Country->buffer );
190*cdf0e10cSrcweir 
191*cdf0e10cSrcweir 		/* save pointer to local structure in TLS */
192*cdf0e10cSrcweir 		TlsSetValue( g_dwTLSLocaleEncId, &params );
193*cdf0e10cSrcweir 
194*cdf0e10cSrcweir 		/* enum all locales known to Windows */
195*cdf0e10cSrcweir 		EnumSystemLocalesA( EnumLocalesProcA, LCID_SUPPORTED );
196*cdf0e10cSrcweir 
197*cdf0e10cSrcweir 		/* use the LCID found in iteration */
198*cdf0e10cSrcweir 		return GetTextEncodingFromLCID( params.Locale );
199*cdf0e10cSrcweir 	}
200*cdf0e10cSrcweir 
201*cdf0e10cSrcweir 	return RTL_TEXTENCODING_DONTKNOW;
202*cdf0e10cSrcweir }
203*cdf0e10cSrcweir 
204*cdf0e10cSrcweir /*****************************************************************************/
205*cdf0e10cSrcweir /* imp_getProcessLocale
206*cdf0e10cSrcweir /*****************************************************************************/
207*cdf0e10cSrcweir 
208*cdf0e10cSrcweir void _imp_getProcessLocale( rtl_Locale ** ppLocale )
209*cdf0e10cSrcweir {
210*cdf0e10cSrcweir 	WCHAR langCode[4];
211*cdf0e10cSrcweir 	WCHAR ctryCode[4];
212*cdf0e10cSrcweir     LCID  localeId;
213*cdf0e10cSrcweir 
214*cdf0e10cSrcweir     OSL_ASSERT( ppLocale );
215*cdf0e10cSrcweir 
216*cdf0e10cSrcweir     /* get the LCID to retrieve information from */
217*cdf0e10cSrcweir     localeId = GetUserDefaultLCID();
218*cdf0e10cSrcweir 
219*cdf0e10cSrcweir     /* call GetLocaleInfo to retrieve the iso codes */
220*cdf0e10cSrcweir 	if( GetLocaleInfo( localeId, LOCALE_SISO639LANGNAME , langCode, 4 )  &&
221*cdf0e10cSrcweir         GetLocaleInfo( localeId, LOCALE_SISO3166CTRYNAME , ctryCode, 4 ) )
222*cdf0e10cSrcweir 	{
223*cdf0e10cSrcweir         *ppLocale = rtl_locale_register( langCode, ctryCode, L"" );
224*cdf0e10cSrcweir     }
225*cdf0e10cSrcweir     else
226*cdf0e10cSrcweir 	{
227*cdf0e10cSrcweir         *ppLocale = rtl_locale_register( L"C", L"", L"" );
228*cdf0e10cSrcweir     }
229*cdf0e10cSrcweir }
230*cdf0e10cSrcweir 
231*cdf0e10cSrcweir 
232