#include "wx/hashset.h"
#include "wx/filesys.h"
-#if defined(__WXMAC__)
- #include "wx/mac/private.h" // includes mac headers
-#endif
-
#if defined(__DARWIN__)
- #include "wx/mac/corefoundation/cfref.h"
- #include <CoreFoundation/CFLocale.h>
- #include "wx/mac/corefoundation/cfstring.h"
+ #include "wx/mac/corefoundation/cfref.h"
+ #include <CoreFoundation/CFLocale.h>
+ #include "wx/mac/corefoundation/cfstring.h"
#endif
// ----------------------------------------------------------------------------
bool wxPluralFormsScanner::nextToken()
{
wxPluralFormsToken::Type type = wxPluralFormsToken::T_ERROR;
- while (isspace(*m_s))
+ while (isspace((unsigned char) *m_s))
{
++m_s;
}
{
type = wxPluralFormsToken::T_EOF;
}
- else if (isdigit(*m_s))
+ else if (isdigit((unsigned char) *m_s))
{
wxPluralFormsToken::Number number = *m_s++ - '0';
- while (isdigit(*m_s))
+ while (isdigit((unsigned char) *m_s))
{
number = number * 10 + (*m_s++ - '0');
}
m_token.setNumber(number);
type = wxPluralFormsToken::T_NUMBER;
}
- else if (isalpha(*m_s))
+ else if (isalpha((unsigned char) *m_s))
{
const char* begin = m_s++;
- while (isalnum(*m_s))
+ while (isalnum((unsigned char) *m_s))
{
++m_s;
}
class wxMsgCatalog
{
public:
+#if !wxUSE_UNICODE
wxMsgCatalog() { m_conv = NULL; }
~wxMsgCatalog();
+#endif
// load the catalog from disk (szDirPrefix corresponds to language)
bool Load(const wxString& dirPrefix, const wxString& name,
wxMessagesHash m_messages; // all messages in the catalog
wxString m_name; // name of the domain
+#if !wxUSE_UNICODE
// the conversion corresponding to this catalog charset if we installed it
// as the global one
wxCSConv *m_conv;
+#endif
wxPluralFormsCalculatorPtr m_pluralFormsCalculator;
};
// implementation
// ============================================================================
+// ----------------------------------------------------------------------------
+// wxLanguageInfo
+// ----------------------------------------------------------------------------
+
+#ifdef __WXMSW__
+
+// helper used by wxLanguageInfo::GetLocaleName() and elsewhere to determine
+// whether the locale is Unicode-only (it is if this function returns empty
+// string)
+static wxString wxGetANSICodePageForLocale(LCID lcid)
+{
+ wxString cp;
+
+ wxChar buffer[16];
+ if ( ::GetLocaleInfo(lcid, LOCALE_IDEFAULTANSICODEPAGE,
+ buffer, WXSIZEOF(buffer)) > 0 )
+ {
+ if ( buffer[0] != _T('0') || buffer[1] != _T('\0') )
+ cp = buffer;
+ //else: this locale doesn't use ANSI code page
+ }
+
+ return cp;
+}
+
+wxUint32 wxLanguageInfo::GetLCID() const
+{
+ return MAKELCID(MAKELANGID(WinLang, WinSublang), SORT_DEFAULT);
+}
+
+wxString wxLanguageInfo::GetLocaleName() const
+{
+ wxString locale;
+
+ const LCID lcid = GetLCID();
+
+ wxChar buffer[256];
+ buffer[0] = _T('\0');
+ if ( !::GetLocaleInfo(lcid, LOCALE_SENGLANGUAGE, buffer, WXSIZEOF(buffer)) )
+ {
+ wxLogLastError(_T("GetLocaleInfo(LOCALE_SENGLANGUAGE)"));
+ return locale;
+ }
+
+ locale << buffer;
+ if ( ::GetLocaleInfo(lcid, LOCALE_SENGCOUNTRY,
+ buffer, WXSIZEOF(buffer)) > 0 )
+ {
+ locale << _T('_') << buffer;
+ }
+
+ const wxString cp = wxGetANSICodePageForLocale(lcid);
+ if ( !cp.empty() )
+ {
+ locale << _T('.') << cp;
+ }
+
+ return locale;
+}
+
+#endif // __WXMSW__
+
// ----------------------------------------------------------------------------
// wxMsgCatalogFile class
// ----------------------------------------------------------------------------
// wxMsgCatalog class
// ----------------------------------------------------------------------------
+#if !wxUSE_UNICODE
wxMsgCatalog::~wxMsgCatalog()
{
if ( m_conv )
delete m_conv;
}
}
+#endif // !wxUSE_UNICODE
bool wxMsgCatalog::Load(const wxString& dirPrefix, const wxString& name,
const wxString& msgIdCharset, bool bConvertEncoding)
file.FillHash(m_messages, msgIdCharset, bConvertEncoding);
+#if !wxUSE_UNICODE
// we should use a conversion compatible with the message catalog encoding
// in the GUI if we don't convert the strings to the current conversion but
// as the encoding is global, only change it once, otherwise we could get
wxConvUI =
m_conv = new wxCSConv(file.GetCharset());
}
+#endif // !wxUSE_UNICODE
return true;
}
wxS("no locale to set in wxLocale::Init()") );
}
-#ifdef __WXWINCE__
- // FIXME: I'm guessing here
- wxChar localeName[256];
- int ret = GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SLANGUAGE, localeName,
- 256);
- if (ret != 0)
- {
- m_pszOldLocale = wxStrdup(wxConvLibc.cWC2MB(localeName));
- }
- else
- m_pszOldLocale = NULL;
-
- // TODO: how to find languageId
- // SetLocaleInfo(languageId, SORT_DEFAULT, localeName);
-#else
const char *oldLocale = wxSetlocale(LC_ALL, szLocale);
if ( oldLocale )
m_pszOldLocale = wxStrdup(oldLocale);
else
m_pszOldLocale = NULL;
-#endif
if ( m_pszOldLocale == NULL )
wxLogError(_("locale '%s' can not be set."), szLocale);
#endif // __AIX__
#elif defined(__WIN32__)
-
- #if wxUSE_UNICODE && (defined(__VISUALC__) || defined(__MINGW32__))
- // NB: setlocale() from msvcrt.dll (used by VC++ and Mingw)
- // can't set locale to language that can only be written using
- // Unicode. Therefore wxSetlocale call failed, but we don't want
- // to report it as an error -- so that at least message catalogs
- // can be used. Watch for code marked with
- // #ifdef SETLOCALE_FAILS_ON_UNICODE_LANGS bellow.
- #define SETLOCALE_FAILS_ON_UNICODE_LANGS
- #endif
-
const char *retloc = "C";
- if (language != wxLANGUAGE_DEFAULT)
+ if ( language != wxLANGUAGE_DEFAULT )
{
- if (info->WinLang == 0)
+ if ( info->WinLang == 0 )
{
wxLogWarning(wxS("Locale '%s' not supported by OS."), name.c_str());
// retloc already set to "C"
}
- else
+ else // language supported by Windows
{
- int codepage
- #ifdef SETLOCALE_FAILS_ON_UNICODE_LANGS
- = -1
- #endif
- ;
- wxUint32 lcid = MAKELCID(MAKELANGID(info->WinLang, info->WinSublang),
- SORT_DEFAULT);
- // FIXME
+ // Windows CE doesn't have SetThreadLocale() and there doesn't seem
+ // to be any equivalent
#ifndef __WXWINCE__
- SetThreadLocale(lcid);
-#endif
- // NB: we must translate LCID to CRT's setlocale string ourselves,
- // because SetThreadLocale does not modify change the
- // interpretation of setlocale(LC_ALL, "") call:
- wxChar buffer[256];
- buffer[0] = wxS('\0');
- GetLocaleInfo(lcid, LOCALE_SENGLANGUAGE, buffer, 256);
- locale << buffer;
- if (GetLocaleInfo(lcid, LOCALE_SENGCOUNTRY, buffer, 256) > 0)
- locale << wxS("_") << buffer;
- if (GetLocaleInfo(lcid, LOCALE_IDEFAULTANSICODEPAGE, buffer, 256) > 0)
- {
- codepage = wxAtoi(buffer);
- if (codepage != 0)
- locale << wxS(".") << buffer;
- }
- if (locale.empty())
+ const wxUint32 lcid = info->GetLCID();
+
+ // change locale used by Windows functions
+ ::SetThreadLocale(lcid);
+#endif
+
+ // and also call setlocale() to change locale used by the CRT
+ locale = info->GetLocaleName();
+ if ( locale.empty() )
{
- wxLogLastError(wxS("SetThreadLocale"));
ret = false;
}
- else
+ else // have a valid locale
{
- // FIXME
-#ifndef __WXWINCE__
retloc = wxSetlocale(LC_ALL, locale);
-#endif
-#ifdef SETLOCALE_FAILS_ON_UNICODE_LANGS
- if (codepage == 0 && retloc == NULL)
- {
- retloc = "C";
- }
-#endif
}
}
}
- else
+ else // language == wxLANGUAGE_DEFAULT
{
- // FIXME
-#ifndef __WXWINCE__
retloc = wxSetlocale(LC_ALL, wxEmptyString);
-#else
- retloc = NULL;
-#endif
-#ifdef SETLOCALE_FAILS_ON_UNICODE_LANGS
- if (retloc == NULL)
+ }
+
+#if wxUSE_UNICODE && (defined(__VISUALC__) || defined(__MINGW32__))
+ // VC++ setlocale() (also used by Mingw) can't set locale to languages that
+ // can only be written using Unicode, therefore wxSetlocale() call fails
+ // for such languages but we don't want to report it as an error -- so that
+ // at least message catalogs can be used.
+ if ( !retloc )
+ {
+ if ( wxGetANSICodePageForLocale(LOCALE_USER_DEFAULT).empty() )
{
- wxChar buffer[16];
- if (GetLocaleInfo(LOCALE_USER_DEFAULT,
- LOCALE_IDEFAULTANSICODEPAGE, buffer, 16) > 0 &&
- wxStrcmp(buffer, wxS("0")) == 0)
- {
- retloc = "C";
- }
+ // we set the locale to a Unicode-only language, don't treat the
+ // inability of CRT to use it as an error
+ retloc = "C";
}
-#endif
}
+#endif // CRT not handling Unicode-only languages
if ( !retloc )
ret = false;
wxString langFull;
#ifdef __WXMAC__
wxCFRef<CFLocaleRef> userLocaleRef(CFLocaleCopyCurrent());
-
- // because the locale identifier (kCFLocaleIdentifier) is formatted a little bit differently, eg
+
+ // because the locale identifier (kCFLocaleIdentifier) is formatted a little bit differently, eg
// az_Cyrl_AZ@calendar=buddhist;currency=JPY we just recreate the base info as expected by wx here
-
+
wxCFStringRef str(wxCFRetain((CFStringRef)CFLocaleGetValue(userLocaleRef, kCFLocaleLanguageCode)));
langFull = str.AsString()+"_";
str.reset(wxCFRetain((CFStringRef)CFLocaleGetValue(userLocaleRef, kCFLocaleCountryCode)));
// for now we don't use the encoding, although we probably should (doing
// translations of the msg catalogs on the fly as required) (TODO)
//
- // we don't use the modifiers neither but we probably should translate
- // "euro" into iso885915
+ // we need the modified for languages like Valencian: ca_ES@valencia
+ // though, remember it
+ wxString modifier;
+ size_t posModifier = langFull.find_first_of(wxS("@"));
+ if ( posModifier != wxString::npos )
+ modifier = langFull.Mid(posModifier);
+
size_t posEndLang = langFull.find_first_of(wxS("@."));
if ( posEndLang != wxString::npos )
{
}
// 1. Try to find the language either as is:
- for ( i = 0; i < count; i++ )
+ // a) With modifier if set
+ if ( !modifier.empty() )
{
- if ( ms_languagesDB->Item(i).CanonicalName == langFull )
+ wxString langFullWithModifier = langFull + modifier;
+ for ( i = 0; i < count; i++ )
{
- break;
+ if ( ms_languagesDB->Item(i).CanonicalName == langFullWithModifier )
+ break;
+ }
+ }
+
+ // b) Without modifier
+ if ( modifier.empty() || i == count )
+ {
+ for ( i = 0; i < count; i++ )
+ {
+ if ( ms_languagesDB->Item(i).CanonicalName == langFull )
+ break;
}
}
return wxFONTENCODING_CP950;
}
#elif defined(__WXMAC__)
- TextEncoding encoding = 0 ;
+ CFStringEncoding encoding = 0 ;
encoding = CFStringGetSystemEncoding() ;
return wxMacGetFontEncFromSystemEnc( encoding ) ;
#elif defined(__UNIX_LIKE__) && wxUSE_FONTMAP
wxString wxLocale::GetSysName() const
{
- // FIXME
-#ifndef __WXWINCE__
return wxSetlocale(LC_ALL, NULL);
-#else
- return wxEmptyString;
-#endif
}
// clean up
// restore old locale pointer
wxSetLocale(m_pOldLocale);
- // FIXME
-#ifndef __WXWINCE__
wxSetlocale(LC_ALL, m_pszOldLocale);
-#endif
free((wxChar *)m_pszOldLocale); // const_cast
}
if ( !info->WinLang )
return false;
- if ( !::IsValidLocale
- (
- MAKELCID(MAKELANGID(info->WinLang, info->WinSublang),
- SORT_DEFAULT),
- LCID_INSTALLED
- ) )
+ if ( !::IsValidLocale(info->GetLCID(), LCID_INSTALLED) )
return false;
#elif defined(__UNIX__)
/* static */
wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory WXUNUSED(cat))
{
+ wxUint32 lcid = LOCALE_USER_DEFAULT;
+
+ if (wxGetLocale())
+ {
+ const wxLanguageInfo *info = GetLanguageInfo(wxGetLocale()->GetLanguage());
+ if ( info )
+ lcid = info->GetLCID();
+ }
+
wxString str;
wxChar buffer[256];
size_t count;
switch (index)
{
case wxLOCALE_DECIMAL_POINT:
- count = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, buffer, 256);
+ count = ::GetLocaleInfo(lcid, LOCALE_SDECIMAL, buffer, 256);
if (!count)
str << wxS(".");
else
break;
#if 0
case wxSYS_LIST_SEPARATOR:
- count = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SLIST, buffer, 256);
+ count = ::GetLocaleInfo(lcid, LOCALE_SLIST, buffer, 256);
if (!count)
str << wxS(",");
else
str << buffer;
break;
case wxSYS_LEADING_ZERO: // 0 means no leading zero, 1 means leading zero
- count = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ILZERO, buffer, 256);
+ count = ::GetLocaleInfo(lcid, LOCALE_ILZERO, buffer, 256);
if (!count)
str << wxS("0");
else
/* static */
wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory WXUNUSED(cat))
{
- wxCFRef<CFLocaleRef> userLocaleRef(CFLocaleCopyCurrent());
- CFTypeRef cfstr;
+ CFLocaleRef userLocaleRefRaw;
+ if ( wxGetLocale() )
+ {
+ userLocaleRefRaw = CFLocaleCreate
+ (
+ kCFAllocatorDefault,
+ wxCFStringRef(wxGetLocale()->GetCanonicalName())
+ );
+ }
+ else // no current locale, use the default one
+ {
+ userLocaleRefRaw = CFLocaleCopyCurrent();
+ }
+
+ wxCFRef<CFLocaleRef> userLocaleRef(userLocaleRefRaw);
+
+ CFStringRef cfstr = 0;
switch ( index )
{
case wxLOCALE_THOUSANDS_SEP:
- cfstr = CFLocaleGetValue(userLocaleRef, kCFLocaleGroupingSeparator);
+ cfstr = (CFStringRef) CFLocaleGetValue(userLocaleRef, kCFLocaleGroupingSeparator);
break;
case wxLOCALE_DECIMAL_POINT:
- cfstr = CFLocaleGetValue(userLocaleRef, kCFLocaleDecimalSeparator);
+ cfstr = (CFStringRef) CFLocaleGetValue(userLocaleRef, kCFLocaleDecimalSeparator);
break;
default:
wxFAIL_MSG( "Unknown locale info" );
+ cfstr = CFSTR("");
+ break;
}
- wxCFStringRef
- str(CFStringCreateCopy(NULL, static_cast<CFStringRef>(cfstr)));
+ wxCFStringRef str(wxCFRetain(cfstr));
return str.AsString();
}
LNG(wxLANGUAGE_FRENCH_SWISS, "fr_CH", LANG_FRENCH , SUBLANG_FRENCH_SWISS , wxLayout_LeftToRight, "French (Swiss)")
LNG(wxLANGUAGE_FRISIAN, "fy" , 0 , 0 , wxLayout_LeftToRight, "Frisian")
LNG(wxLANGUAGE_GALICIAN, "gl_ES", 0 , 0 , wxLayout_LeftToRight, "Galician")
- LNG(wxLANGUAGE_GEORGIAN, "ka" , LANG_GEORGIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Georgian")
+ LNG(wxLANGUAGE_GEORGIAN, "ka_GE", LANG_GEORGIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Georgian")
LNG(wxLANGUAGE_GERMAN, "de_DE", LANG_GERMAN , SUBLANG_GERMAN , wxLayout_LeftToRight, "German")
LNG(wxLANGUAGE_GERMAN_AUSTRIAN, "de_AT", LANG_GERMAN , SUBLANG_GERMAN_AUSTRIAN , wxLayout_LeftToRight, "German (Austrian)")
LNG(wxLANGUAGE_GERMAN_BELGIUM, "de_BE", 0 , 0 , wxLayout_LeftToRight, "German (Belgium)")
LNG(wxLANGUAGE_KIRUNDI, "rn" , 0 , 0 , wxLayout_LeftToRight, "Kirundi")
LNG(wxLANGUAGE_KONKANI, "" , LANG_KONKANI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Konkani")
LNG(wxLANGUAGE_KOREAN, "ko_KR", LANG_KOREAN , SUBLANG_KOREAN , wxLayout_LeftToRight, "Korean")
- LNG(wxLANGUAGE_KURDISH, "ku" , 0 , 0 , wxLayout_LeftToRight, "Kurdish")
+ LNG(wxLANGUAGE_KURDISH, "ku_TR", 0 , 0 , wxLayout_LeftToRight, "Kurdish")
LNG(wxLANGUAGE_LAOTHIAN, "lo" , 0 , 0 , wxLayout_LeftToRight, "Laothian")
LNG(wxLANGUAGE_LATIN, "la" , 0 , 0 , wxLayout_LeftToRight, "Latin")
LNG(wxLANGUAGE_LATVIAN, "lv_LV", LANG_LATVIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Latvian")
LNG(wxLANGUAGE_MOLDAVIAN, "mo" , 0 , 0 , wxLayout_LeftToRight, "Moldavian")
LNG(wxLANGUAGE_MONGOLIAN, "mn" , 0 , 0 , wxLayout_LeftToRight, "Mongolian")
LNG(wxLANGUAGE_NAURU, "na" , 0 , 0 , wxLayout_LeftToRight, "Nauru")
- LNG(wxLANGUAGE_NEPALI, "ne" , LANG_NEPALI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Nepali")
+ LNG(wxLANGUAGE_NEPALI, "ne_NP", LANG_NEPALI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Nepali")
LNG(wxLANGUAGE_NEPALI_INDIA, "ne_IN", LANG_NEPALI , SUBLANG_NEPALI_INDIA , wxLayout_LeftToRight, "Nepali (India)")
LNG(wxLANGUAGE_NORWEGIAN_BOKMAL, "nb_NO", LANG_NORWEGIAN , SUBLANG_NORWEGIAN_BOKMAL , wxLayout_LeftToRight, "Norwegian (Bokmal)")
LNG(wxLANGUAGE_NORWEGIAN_NYNORSK, "nn_NO", LANG_NORWEGIAN , SUBLANG_NORWEGIAN_NYNORSK , wxLayout_LeftToRight, "Norwegian (Nynorsk)")
LNG(wxLANGUAGE_SANGHO, "sg" , 0 , 0 , wxLayout_LeftToRight, "Sangho")
LNG(wxLANGUAGE_SANSKRIT, "sa" , LANG_SANSKRIT , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Sanskrit")
LNG(wxLANGUAGE_SCOTS_GAELIC, "gd" , 0 , 0 , wxLayout_LeftToRight, "Scots Gaelic")
+ LNG(wxLANGUAGE_SERBIAN, "sr_SR", LANG_SERBIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Serbian")
+ LNG(wxLANGUAGE_SERBIAN_CYRILLIC, "sr_SR", LANG_SERBIAN , SUBLANG_SERBIAN_CYRILLIC , wxLayout_LeftToRight, "Serbian (Cyrillic)")
+ LNG(wxLANGUAGE_SERBIAN_LATIN, "sr_SR@latin", LANG_SERBIAN , SUBLANG_SERBIAN_LATIN , wxLayout_LeftToRight, "Serbian (Latin)")
LNG(wxLANGUAGE_SERBIAN_CYRILLIC, "sr_YU", LANG_SERBIAN , SUBLANG_SERBIAN_CYRILLIC , wxLayout_LeftToRight, "Serbian (Cyrillic)")
- LNG(wxLANGUAGE_SERBIAN_LATIN, "sr_YU", LANG_SERBIAN , SUBLANG_SERBIAN_LATIN , wxLayout_LeftToRight, "Serbian (Latin)")
+ LNG(wxLANGUAGE_SERBIAN_LATIN, "sr_YU@latin", LANG_SERBIAN , SUBLANG_SERBIAN_LATIN , wxLayout_LeftToRight, "Serbian (Latin)")
LNG(wxLANGUAGE_SERBO_CROATIAN, "sh" , 0 , 0 , wxLayout_LeftToRight, "Serbo-Croatian")
LNG(wxLANGUAGE_SESOTHO, "st" , 0 , 0 , wxLayout_LeftToRight, "Sesotho")
LNG(wxLANGUAGE_SETSWANA, "tn" , 0 , 0 , wxLayout_LeftToRight, "Setswana")
LNG(wxLANGUAGE_UZBEK, "uz" , LANG_UZBEK , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Uzbek")
LNG(wxLANGUAGE_UZBEK_CYRILLIC, "uz" , LANG_UZBEK , SUBLANG_UZBEK_CYRILLIC , wxLayout_LeftToRight, "Uzbek (Cyrillic)")
LNG(wxLANGUAGE_UZBEK_LATIN, "uz" , LANG_UZBEK , SUBLANG_UZBEK_LATIN , wxLayout_LeftToRight, "Uzbek (Latin)")
+ LNG(wxLANGUAGE_VALENCIAN, "ca_ES@valencia", 0 , 0 , wxLayout_LeftToRight, "Valencian")
LNG(wxLANGUAGE_VIETNAMESE, "vi_VN", LANG_VIETNAMESE, SUBLANG_DEFAULT , wxLayout_LeftToRight, "Vietnamese")
LNG(wxLANGUAGE_VOLAPUK, "vo" , 0 , 0 , wxLayout_LeftToRight, "Volapuk")
LNG(wxLANGUAGE_WELSH, "cy" , 0 , 0 , wxLayout_LeftToRight, "Welsh")