/************************************************************** * * 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 INCL_WIN #include "svpm.h" #include #include #include #include #include /***************************************************************************** typedefs *****************************************************************************/ typedef struct { const char *key; const rtl_TextEncoding value; } _pair; /***************************************************************************** compare function for binary search *****************************************************************************/ static int _pair_compare (const char *key, const _pair *pair) { int result = rtl_str_compareIgnoreAsciiCase( key, pair->key ); return result; } /***************************************************************************** binary search on encoding tables *****************************************************************************/ static const _pair* _pair_search (const char *key, const _pair *base, unsigned int member ) { unsigned int lower = 0; unsigned int upper = member; unsigned int current; int comparison; /* check for validity of input */ if ( (key == NULL) || (base == NULL) || (member == 0) ) return NULL; /* binary search */ while ( lower < upper ) { current = (lower + upper) / 2; comparison = _pair_compare( key, base + current ); if (comparison < 0) upper = current; else if (comparison > 0) lower = current + 1; else return base + current; } return NULL; } /***************************************************************************** convert rtl_Locale to locale string *****************************************************************************/ static char * _compose_locale( rtl_Locale * pLocale, char * buffer, size_t n ) { /* check if a valid locale is specified */ if( pLocale && pLocale->Language && (pLocale->Language->length == 2) ) { size_t offset = 0; /* convert language code to ascii */ { rtl_String *pLanguage = NULL; rtl_uString2String( &pLanguage, pLocale->Language->buffer, pLocale->Language->length, RTL_TEXTENCODING_ASCII_US, OUSTRING_TO_OSTRING_CVTFLAGS ); if( pLanguage->length < n ) { strcpy( buffer, pLanguage->buffer ); offset = pLanguage->length; } rtl_string_release( pLanguage ); } /* convert country code to ascii */ if( pLocale->Country && (pLocale->Country->length == 2) ) { rtl_String *pCountry = NULL; rtl_uString2String( &pCountry, pLocale->Country->buffer, pLocale->Country->length, RTL_TEXTENCODING_ASCII_US, OUSTRING_TO_OSTRING_CVTFLAGS ); if( offset + pCountry->length + 1 < n ) { strcpy( buffer + offset++, "_" ); strcpy( buffer + offset, pCountry->buffer ); offset += pCountry->length; } rtl_string_release( pCountry ); } /* convert variant to ascii - check if there is enough space for the variant string */ if( pLocale->Variant && pLocale->Variant->length && ( pLocale->Variant->length < n - 6 ) ) { rtl_String *pVariant = NULL; rtl_uString2String( &pVariant, pLocale->Variant->buffer, pLocale->Variant->length, RTL_TEXTENCODING_ASCII_US, OUSTRING_TO_OSTRING_CVTFLAGS ); if( offset + pVariant->length + 1 < n ) { strcpy( buffer + offset, pVariant->buffer ); offset += pVariant->length; } rtl_string_release( pVariant ); } return buffer; } return NULL; } /***************************************************************************** convert locale string to rtl_Locale *****************************************************************************/ static rtl_Locale * _parse_locale( const char * locale ) { static sal_Unicode c_locale[2] = { (sal_Unicode) 'C', 0 }; /* check if locale contains a valid string */ if( locale ) { size_t len = strlen( locale ); if( len >= 2 ) { rtl_uString * pLanguage = NULL; rtl_uString * pCountry = NULL; rtl_uString * pVariant = NULL; size_t offset = 2; /* convert language code to unicode */ rtl_string2UString( &pLanguage, locale, 2, RTL_TEXTENCODING_ASCII_US, OSTRING_TO_OUSTRING_CVTFLAGS ); OSL_ASSERT(pLanguage != NULL); /* convert country code to unicode */ if( len >= 5 && '_' == locale[2] ) { rtl_string2UString( &pCountry, locale + 3, 2, RTL_TEXTENCODING_ASCII_US, OSTRING_TO_OUSTRING_CVTFLAGS ); OSL_ASSERT(pCountry != NULL); offset = 5; } /* convert variant code to unicode - do not rely on "." as delimiter */ if( len > offset ) { rtl_string2UString( &pVariant, locale + offset, len - offset, RTL_TEXTENCODING_ASCII_US, OSTRING_TO_OUSTRING_CVTFLAGS ); OSL_ASSERT(pVariant != NULL); } rtl_Locale * ret = rtl_locale_register( pLanguage->buffer, pCountry ? pCountry->buffer : c_locale + 1, pVariant ? pVariant->buffer : c_locale + 1 ); if (pVariant) rtl_uString_release(pVariant); if (pCountry) rtl_uString_release(pCountry); if (pLanguage) rtl_uString_release(pLanguage); return ret; } else return rtl_locale_register( c_locale, c_locale + 1, c_locale + 1 ); } return NULL; } /* * This implementation of osl_getTextEncodingFromLocale maps * from the ISO language codes. */ const _pair _full_locale_list[] = { { "ja_JP.eucJP", RTL_TEXTENCODING_EUC_JP }, { "ja_JP.EUC", RTL_TEXTENCODING_EUC_JP }, { "ko_KR.EUC", RTL_TEXTENCODING_EUC_KR }, { "zh_CN.EUC", RTL_TEXTENCODING_EUC_CN }, { "zh_TW.EUC", RTL_TEXTENCODING_EUC_TW } }; const _pair _locale_extension_list[] = { { "big5", RTL_TEXTENCODING_BIG5 }, { "big5hk", RTL_TEXTENCODING_BIG5_HKSCS }, { "gb18030", RTL_TEXTENCODING_GB_18030 }, { "euc", RTL_TEXTENCODING_EUC_JP }, { "iso8859-1", RTL_TEXTENCODING_ISO_8859_1 }, { "iso8859-10", RTL_TEXTENCODING_ISO_8859_10 }, { "iso8859-13", RTL_TEXTENCODING_ISO_8859_13 }, { "iso8859-14", RTL_TEXTENCODING_ISO_8859_14 }, { "iso8859-15", RTL_TEXTENCODING_ISO_8859_15 }, { "iso8859-2", RTL_TEXTENCODING_ISO_8859_2 }, { "iso8859-3", RTL_TEXTENCODING_ISO_8859_3 }, { "iso8859-4", RTL_TEXTENCODING_ISO_8859_4 }, { "iso8859-5", RTL_TEXTENCODING_ISO_8859_5 }, { "iso8859-6", RTL_TEXTENCODING_ISO_8859_6 }, { "iso8859-7", RTL_TEXTENCODING_ISO_8859_7 }, { "iso8859-8", RTL_TEXTENCODING_ISO_8859_8 }, { "iso8859-9", RTL_TEXTENCODING_ISO_8859_9 }, { "koi8-r", RTL_TEXTENCODING_KOI8_R }, { "koi8-u", RTL_TEXTENCODING_KOI8_U }, { "pck", RTL_TEXTENCODING_MS_932 }, #if (0) { "sun_eu_greek", RTL_TEXTENCODING_DONTKNOW }, #endif { "utf-16", RTL_TEXTENCODING_UNICODE }, { "utf-7", RTL_TEXTENCODING_UTF7 }, { "utf-8", RTL_TEXTENCODING_UTF8 } }; const _pair _iso_language_list[] = { { "af", RTL_TEXTENCODING_ISO_8859_1 }, { "ar", RTL_TEXTENCODING_ISO_8859_6 }, { "az", RTL_TEXTENCODING_ISO_8859_9 }, { "be", RTL_TEXTENCODING_ISO_8859_5 }, { "bg", RTL_TEXTENCODING_ISO_8859_5 }, { "ca", RTL_TEXTENCODING_ISO_8859_1 }, { "cs", RTL_TEXTENCODING_ISO_8859_2 }, { "da", RTL_TEXTENCODING_ISO_8859_1 }, { "de", RTL_TEXTENCODING_ISO_8859_1 }, { "el", RTL_TEXTENCODING_ISO_8859_7 }, { "en", RTL_TEXTENCODING_ISO_8859_1 }, { "es", RTL_TEXTENCODING_ISO_8859_1 }, { "et", RTL_TEXTENCODING_ISO_8859_4 }, { "eu", RTL_TEXTENCODING_ISO_8859_1 }, { "fa", RTL_TEXTENCODING_ISO_8859_6 }, { "fi", RTL_TEXTENCODING_ISO_8859_1 }, { "fo", RTL_TEXTENCODING_ISO_8859_1 }, { "fr", RTL_TEXTENCODING_ISO_8859_1 }, { "gr", RTL_TEXTENCODING_ISO_8859_7 }, { "he", RTL_TEXTENCODING_ISO_8859_8 }, { "hi", RTL_TEXTENCODING_DONTKNOW }, { "hr", RTL_TEXTENCODING_ISO_8859_2 }, { "hu", RTL_TEXTENCODING_ISO_8859_2 }, { "hy", RTL_TEXTENCODING_DONTKNOW }, { "id", RTL_TEXTENCODING_ISO_8859_1 }, { "is", RTL_TEXTENCODING_ISO_8859_1 }, { "it", RTL_TEXTENCODING_ISO_8859_1 }, { "iw", RTL_TEXTENCODING_ISO_8859_8 }, { "ja", RTL_TEXTENCODING_EUC_JP }, { "ka", RTL_TEXTENCODING_DONTKNOW }, { "kk", RTL_TEXTENCODING_ISO_8859_5 }, { "ko", RTL_TEXTENCODING_EUC_KR }, { "lt", RTL_TEXTENCODING_ISO_8859_4 }, { "lv", RTL_TEXTENCODING_ISO_8859_4 }, { "mk", RTL_TEXTENCODING_ISO_8859_5 }, { "mr", RTL_TEXTENCODING_DONTKNOW }, { "ms", RTL_TEXTENCODING_ISO_8859_1 }, { "nl", RTL_TEXTENCODING_ISO_8859_1 }, { "no", RTL_TEXTENCODING_ISO_8859_1 }, { "pl", RTL_TEXTENCODING_ISO_8859_2 }, { "pt", RTL_TEXTENCODING_ISO_8859_1 }, { "ro", RTL_TEXTENCODING_ISO_8859_2 }, { "ru", RTL_TEXTENCODING_ISO_8859_5 }, { "sa", RTL_TEXTENCODING_DONTKNOW }, { "sk", RTL_TEXTENCODING_ISO_8859_2 }, { "sl", RTL_TEXTENCODING_ISO_8859_2 }, { "sq", RTL_TEXTENCODING_ISO_8859_2 }, { "sv", RTL_TEXTENCODING_ISO_8859_1 }, { "sw", RTL_TEXTENCODING_ISO_8859_1 }, { "ta", RTL_TEXTENCODING_DONTKNOW }, { "th", RTL_TEXTENCODING_DONTKNOW }, { "tr", RTL_TEXTENCODING_ISO_8859_9 }, { "tt", RTL_TEXTENCODING_ISO_8859_5 }, { "uk", RTL_TEXTENCODING_ISO_8859_5 }, { "ur", RTL_TEXTENCODING_ISO_8859_6 }, { "uz", RTL_TEXTENCODING_ISO_8859_9 }, { "vi", RTL_TEXTENCODING_DONTKNOW }, { "zh", RTL_TEXTENCODING_BIG5 } }; /***************************************************************************** return the text encoding corresponding to the given locale *****************************************************************************/ rtl_TextEncoding osl_getTextEncodingFromLocale( rtl_Locale * pLocale ) { const _pair *language = NULL; char locale_buf[64] = ""; char *cp; WinMessageBox(HWND_DESKTOP,HWND_DESKTOP, "Please contact technical support and report above informations.\n\n", "Critical error: osl_getTextEncodingFromLocale", 0, MB_ERROR | MB_OK | MB_MOVEABLE); /* default to process locale if pLocale == NULL */ if( NULL == pLocale ) osl_getProcessLocale( &pLocale ); /* convert rtl_Locale to locale string */ if( _compose_locale( pLocale, locale_buf, 64 ) ) { /* check special handling list (EUC) first */ const unsigned int members = sizeof( _full_locale_list ) / sizeof( _pair ); language = _pair_search( locale_buf, _full_locale_list, members); if( NULL == language ) { /* * check if there is a charset qualifier at the end of the given locale string * e.g. de.ISO8859-15 or de.ISO8859-15@euro which strongly indicates what * charset to use */ cp = strrchr( locale_buf, '.' ); if( NULL != cp ) { const unsigned int members = sizeof( _locale_extension_list ) / sizeof( _pair ); language = _pair_search( cp + 1, _locale_extension_list, members); } } /* use iso language code to determine the charset */ if( NULL == language ) { const unsigned int members = sizeof( _iso_language_list ) / sizeof( _pair ); /* iso lang codes have 2 charaters */ locale_buf[2] = '\0'; language = _pair_search( locale_buf, _iso_language_list, members); } } /* a matching item in our list provides a mapping from codeset to * rtl-codeset */ if ( language != NULL ) return language->value; return RTL_TEXTENCODING_DONTKNOW; } /***************************************************************************** return the current process locale *****************************************************************************/ void _imp_getProcessLocale( rtl_Locale ** ppLocale ) { /* simulate behavior off setlocale */ char * locale = getenv( "LC_ALL" ); if( NULL == locale ) locale = getenv( "LC_CTYPE" ); if( NULL == locale ) locale = getenv( "LANG" ); if( NULL == locale ) locale = "C"; *ppLocale = _parse_locale( locale ); } /***************************************************************************** set the current process locale *****************************************************************************/ int _imp_setProcessLocale( rtl_Locale * pLocale ) { char locale_buf[64]; /* convert rtl_Locale to locale string */ if( NULL != _compose_locale( pLocale, locale_buf, 64 ) ) { /* only change env vars that exist already */ if( getenv( "LC_ALL" ) ) { #if defined( FREEBSD ) || defined( NETBSD ) || defined( MACOSX ) || defined( __EMX__ ) setenv( "LC_ALL", locale_buf, 1); #else setenv( "LC_ALL", locale_buf ); #endif } if( getenv( "LC_CTYPE" ) ) { #if defined( FREEBSD ) || defined( NETBSD ) || defined( MACOSX ) || defined( __EMX__ ) setenv("LC_CTYPE", locale_buf, 1 ); #else setenv( "LC_CTYPE", locale_buf ); #endif } if( getenv( "LANG" ) ) { #if defined( FREEBSD ) || defined( NETBSD ) || defined( MACOSX ) || defined( __EMX__ ) setenv("LC_CTYPE", locale_buf, 1 ); #else setenv( "LANG", locale_buf ); #endif } } return 0; }