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