blob: 2a4ac7a3de48107dda0d0d47857edebc6f425224 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#define UNICODE
#ifdef _MSC_VER
#pragma warning(push,1) /* disable warnings within system headers */
#endif
#include <windows.h>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include <wchar.h>
#include <osl/mutex.h>
#include <osl/nlsupport.h>
#include <osl/diagnose.h>
#include <osl/process.h>
#include <rtl/tencinfo.h>
struct EnumLocalesParams
{
WCHAR Language[3];
WCHAR Country[3];
LCID Locale;
};
static DWORD g_dwTLSLocaleEncId = (DWORD) -1;
/*****************************************************************************/
/* callback function test
/*
/* osl_getTextEncodingFromLocale calls EnumSystemLocalesA, so that we don't
/* need to provide a unicode wrapper for this function under Win9x
/* that means the callback function has an ansi prototype and receives
/* the locale strings as ansi strings
/*****************************************************************************/
BOOL CALLBACK EnumLocalesProcA( LPSTR lpLocaleStringA )
{
struct EnumLocalesParams * params;
LCID localeId;
LPSTR pszEndA;
WCHAR langCode[4];
/* convert hex-string to LCID */
localeId = strtol( lpLocaleStringA, &pszEndA, 16 );
/* check params received via TLS */
params = (struct EnumLocalesParams *) TlsGetValue( g_dwTLSLocaleEncId );
if( NULL == params || '\0' == params->Language[0] )
return FALSE;
/*
get the ISO language code for this locale
remeber: we call the GetLocaleInfoW function
because the ansi version of this function returns
an error under WinNT/2000 when called with an
unicode only lcid
*/
if( GetLocaleInfo( localeId, LOCALE_SISO639LANGNAME , langCode, 4 ) )
{
WCHAR ctryCode[4];
/* continue if language code does not match */
if( 0 != wcscmp( langCode, params->Language ) )
return TRUE;
/* check if country code is set and equals the current locale */
if( '\0' != params->Country[0] && GetLocaleInfo( localeId, LOCALE_SISO3166CTRYNAME , ctryCode, 4 ) )
{
/* save return value in TLS and break if found desired locale */
if( 0 == wcscmp( ctryCode, params->Country ) )
{
params->Locale = localeId;
return FALSE;
}
}
else
{
/* fill with default values for that language */
LANGID langId = LANGIDFROMLCID( localeId );
/* exchange sublanguage with SUBLANG_NEUTRAL */
langId = MAKELANGID( PRIMARYLANGID( langId ), SUBLANG_NEUTRAL );
/* and use default sorting order */
params->Locale = MAKELCID( langId, SORT_DEFAULT );
return FALSE;
}
}
/* retry by going on */
return TRUE;
}
/*****************************************************************************/
/* GetTextEncodingFromLCID
/*****************************************************************************/
rtl_TextEncoding GetTextEncodingFromLCID( LCID localeId )
{
rtl_TextEncoding Encoding = RTL_TEXTENCODING_DONTKNOW;
WCHAR ansiCP[6];
/* query ansi codepage for given locale */
if( localeId && GetLocaleInfo( localeId, LOCALE_IDEFAULTANSICODEPAGE, ansiCP, 6 ) )
{
/* if GetLocaleInfo returns "0", it is a UNICODE only locale */
if( 0 != wcscmp( ansiCP, L"0" ) )
{
WCHAR *pwcEnd;
UINT codepage;
/* values returned from GetLocaleInfo are dezimal based */
codepage = wcstol( ansiCP, &pwcEnd, 10 );
/* find matching rtl encoding */
Encoding = rtl_getTextEncodingFromWindowsCodePage( codepage );
}
else
Encoding = RTL_TEXTENCODING_UNICODE;
}
return Encoding;
}
/*****************************************************************************/
/* osl_getTextEncodingFromLocale
/*****************************************************************************/
rtl_TextEncoding SAL_CALL osl_getTextEncodingFromLocale( rtl_Locale * pLocale )
{
struct EnumLocalesParams params = { L"", L"", 0 };
/* initialise global TLS id */
if( (DWORD) -1 == g_dwTLSLocaleEncId )
{
oslMutex globalMutex = * osl_getGlobalMutex();
/* initializing must be thread save */
osl_acquireMutex( globalMutex );
if( (DWORD) -1 == g_dwTLSLocaleEncId )
g_dwTLSLocaleEncId = TlsAlloc();
osl_releaseMutex( globalMutex );
}
/* if pLocale is NULL, use process locale as default */
if( NULL == pLocale )
osl_getProcessLocale( &pLocale );
/* copy in parameters to structure */
if( pLocale && pLocale->Language )
{
wcscpy( params.Language, pLocale->Language->buffer );
if( pLocale->Country )
wcscpy( params.Country, pLocale->Country->buffer );
/* save pointer to local structure in TLS */
TlsSetValue( g_dwTLSLocaleEncId, &params );
/* enum all locales known to Windows */
EnumSystemLocalesA( EnumLocalesProcA, LCID_SUPPORTED );
/* use the LCID found in iteration */
return GetTextEncodingFromLCID( params.Locale );
}
return RTL_TEXTENCODING_DONTKNOW;
}
/*****************************************************************************/
/* imp_getProcessLocale
/*****************************************************************************/
void _imp_getProcessLocale( rtl_Locale ** ppLocale )
{
WCHAR langCode[4];
WCHAR ctryCode[4];
LCID localeId;
OSL_ASSERT( ppLocale );
/* get the LCID to retrieve information from */
localeId = GetUserDefaultLCID();
/* call GetLocaleInfo to retrieve the iso codes */
if( GetLocaleInfo( localeId, LOCALE_SISO639LANGNAME , langCode, 4 ) &&
GetLocaleInfo( localeId, LOCALE_SISO3166CTRYNAME , ctryCode, 4 ) )
{
*ppLocale = rtl_locale_register( langCode, ctryCode, L"" );
}
else
{
*ppLocale = rtl_locale_register( L"C", L"", L"" );
}
}