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