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