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 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 remeber: 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 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 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, ¶ms ); 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 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