X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/655719367ac5e131d9642e5783f3ecf64d1a3385..6dfd822aca402038843a9a74cdcb7af0928c372a:/src/common/intl.cpp?ds=inline diff --git a/src/common/intl.cpp b/src/common/intl.cpp index 5f6f95a85d..c4e098da1a 100644 --- a/src/common/intl.cpp +++ b/src/common/intl.cpp @@ -163,7 +163,7 @@ static inline wxString ExtractNotLang(const wxString& langFull) // Plural forms parser // ---------------------------------------------------------------------------- -/* +/* Simplified Grammar Expression: @@ -189,7 +189,7 @@ RelationalExpression: MultiplicativeExpression ">=" MultiplicativeExpression MultiplicativeExpression "<=" MultiplicativeExpression MultiplicativeExpression - + MultiplicativeExpression: PmExpression '%' PmExpression PmExpression @@ -401,7 +401,7 @@ private: wxPluralFormsToken m_token; wxPluralFormsNodePtr m_nodes[3]; }; - + wxPluralFormsNodePtr::~wxPluralFormsNodePtr() { delete m_p; @@ -486,7 +486,7 @@ class wxPluralFormsCalculator { public: wxPluralFormsCalculator() : m_nplurals(0), m_plural(0) {} - + // input: number, returns msgstr index int evaluate(int n) const; @@ -499,7 +499,7 @@ public: void init(wxPluralFormsToken::Number nplurals, wxPluralFormsNode* plural); wxString getString() const; - + private: wxPluralFormsToken::Number m_nplurals; wxPluralFormsNodePtr m_plural; @@ -541,7 +541,7 @@ private: wxPluralFormsScanner& m_scanner; const wxPluralFormsToken& token() const; bool nextToken(); - + wxPluralFormsNode* expression(); wxPluralFormsNode* logicalOrExpression(); wxPluralFormsNode* logicalAndExpression(); @@ -887,7 +887,8 @@ public: wxPluralFormsCalculatorPtr& rPluralFormsCalculator); // fills the hash with string-translation pairs - void FillHash(wxMessagesHash& hash, bool convertEncoding) const; + void FillHash(wxMessagesHash& hash, const wxString& msgIdCharset, + bool convertEncoding) const; private: // this implementation is binary compatible with GNU gettext() version 0.10 @@ -923,7 +924,7 @@ private: *m_pTransTable; // translated wxString m_charset; - + // swap the 2 halves of 32 bit integer if needed size_t32 Swap(size_t32 ui) const { @@ -944,7 +945,7 @@ private: } return (const char *)(m_pData + ofsString); - } + } bool m_bSwapped; // wrong endianness? @@ -963,7 +964,8 @@ class wxMsgCatalog { public: // load the catalog from disk (szDirPrefix corresponds to language) - bool Load(const wxChar *szDirPrefix, const wxChar *szName, bool bConvertEncoding = FALSE); + bool Load(const wxChar *szDirPrefix, const wxChar *szName, + const wxChar *msgIdCharset = NULL, bool bConvertEncoding = false); // get name of the catalog wxString GetName() const { return m_name; } @@ -1076,7 +1078,7 @@ bool wxMsgCatalogFile::Load(const wxChar *szDirPrefix, const wxChar *szName0, FIXME: UNICODE SUPPORT: must use CHARSET specifier! */ wxString szName = szName0; - if(szName.Find(wxT('.')) != -1) // contains a dot + if(szName.Find(wxT('.')) != wxNOT_FOUND) // contains a dot szName = szName.Left(szName.Find(wxT('.'))); wxString searchPath = GetFullSearchPath(szDirPrefix); @@ -1106,7 +1108,7 @@ bool wxMsgCatalogFile::Load(const wxChar *szDirPrefix, const wxChar *szName0, wxString strFullName; if ( !wxFindFileInPath(&strFullName, searchPath, strFile) ) { wxLogVerbose(_("catalog file for domain '%s' not found."), szName.c_str()); - return FALSE; + return false; } // open file @@ -1115,22 +1117,22 @@ bool wxMsgCatalogFile::Load(const wxChar *szDirPrefix, const wxChar *szName0, wxFile fileMsg(strFullName); if ( !fileMsg.IsOpened() ) - return FALSE; + return false; // get the file size - off_t nSize = fileMsg.Length(); + wxFileSize_t nSize = fileMsg.Length(); if ( nSize == wxInvalidOffset ) - return FALSE; + return false; // read the whole file in memory m_pData = new size_t8[nSize]; if ( fileMsg.Read(m_pData, nSize) != nSize ) { wxDELETEA(m_pData); - return FALSE; + return false; } // examine header - bool bValid = (size_t)nSize > sizeof(wxMsgCatalogHeader); + bool bValid = nSize > sizeof(wxMsgCatalogHeader); wxMsgCatalogHeader *pHeader = (wxMsgCatalogHeader *)m_pData; if ( bValid ) { @@ -1146,7 +1148,7 @@ bool wxMsgCatalogFile::Load(const wxChar *szDirPrefix, const wxChar *szName0, wxLogWarning(_("'%s' is not a valid message catalog."), strFullName.c_str()); wxDELETEA(m_pData); - return FALSE; + return false; } // initialize @@ -1156,7 +1158,7 @@ bool wxMsgCatalogFile::Load(const wxChar *szDirPrefix, const wxChar *szName0, m_pTransTable = (wxMsgTableEntry *)(m_pData + Swap(pHeader->ofsTransTable)); m_nSize = nSize; - + // now parse catalog's header and try to extract catalog charset and // plural forms formula from it: @@ -1181,7 +1183,7 @@ bool wxMsgCatalogFile::Load(const wxChar *szDirPrefix, const wxChar *szName0, } } // else: incorrectly filled Content-Type header - + // Extract plural forms: begin = header.Find(wxT("Plural-Forms:")); if (begin != wxNOT_FOUND) @@ -1214,23 +1216,33 @@ bool wxMsgCatalogFile::Load(const wxChar *szDirPrefix, const wxChar *szName0, return true; } -void wxMsgCatalogFile::FillHash(wxMessagesHash& hash, bool convertEncoding) const +void wxMsgCatalogFile::FillHash(wxMessagesHash& hash, + const wxString& msgIdCharset, + bool convertEncoding) const { #if wxUSE_WCHAR_T wxCSConv *csConv = NULL; - if ( !!m_charset ) + if ( !m_charset.IsEmpty() ) csConv = new wxCSConv(m_charset); wxMBConv& inputConv = csConv ? *((wxMBConv*)csConv) : *wxConvCurrent; + + wxCSConv *sourceConv = NULL; + if ( !msgIdCharset.empty() && (m_charset != msgIdCharset) ) + sourceConv = new wxCSConv(msgIdCharset); + #elif wxUSE_FONTMAP + wxASSERT_MSG( msgIdCharset == NULL, + _T("non-ASCII msgid languages only supported if wxUSE_WCHAR_T=1") ); + wxEncodingConverter converter; if ( convertEncoding ) { wxFontEncoding targetEnc = wxFONTENCODING_SYSTEM; - wxFontEncoding enc = wxFontMapper::Get()->CharsetToEncoding(m_charset, FALSE); + wxFontEncoding enc = wxFontMapper::Get()->CharsetToEncoding(m_charset, false); if ( enc == wxFONTENCODING_SYSTEM ) { - convertEncoding = FALSE; // unknown encoding + convertEncoding = false; // unknown encoding } else { @@ -1240,10 +1252,10 @@ void wxMsgCatalogFile::FillHash(wxMessagesHash& hash, bool convertEncoding) cons wxFontEncodingArray a = wxEncodingConverter::GetPlatformEquivalents(enc); if (a[0] == enc) // no conversion needed, locale uses native encoding - convertEncoding = FALSE; + convertEncoding = false; if (a.GetCount() == 0) // we don't know common equiv. under this platform - convertEncoding = FALSE; + convertEncoding = false; targetEnc = a[0]; } } @@ -1259,11 +1271,17 @@ void wxMsgCatalogFile::FillHash(wxMessagesHash& hash, bool convertEncoding) cons for (size_t i = 0; i < m_numStrings; i++) { const char *data = StringAtOfs(m_pOrigTable, i); -#if wxUSE_WCHAR_T +#if wxUSE_UNICODE wxString msgid(data, inputConv); #else - wxString msgid(data); + wxString msgid; +#if wxUSE_WCHAR_T + if ( convertEncoding && sourceConv ) + msgid = wxString(inputConv.cMB2WC(data), *sourceConv); + else #endif + msgid = data; +#endif // wxUSE_UNICODE data = StringAtOfs(m_pTransTable, i); size_t length = Swap(m_pTransTable[i].nLen); @@ -1300,6 +1318,7 @@ void wxMsgCatalogFile::FillHash(wxMessagesHash& hash, bool convertEncoding) cons } #if wxUSE_WCHAR_T + delete sourceConv; delete csConv; #endif } @@ -1310,7 +1329,7 @@ void wxMsgCatalogFile::FillHash(wxMessagesHash& hash, bool convertEncoding) cons // ---------------------------------------------------------------------------- bool wxMsgCatalog::Load(const wxChar *szDirPrefix, const wxChar *szName, - bool bConvertEncoding) + const wxChar *msgIdCharset, bool bConvertEncoding) { wxMsgCatalogFile file; @@ -1318,11 +1337,11 @@ bool wxMsgCatalog::Load(const wxChar *szDirPrefix, const wxChar *szName, if ( file.Load(szDirPrefix, szName, m_pluralFormsCalculator) ) { - file.FillHash(m_messages, bConvertEncoding); - return TRUE; + file.FillHash(m_messages, msgIdCharset, bConvertEncoding); + return true; } - return FALSE; + return false; } const wxChar *wxMsgCatalog::GetString(const wxChar *sz, size_t n) const @@ -1393,7 +1412,7 @@ bool wxLocale::Init(const wxChar *szName, { wxASSERT_MSG( !m_initialized, _T("you can't call wxLocale::Init more than once") ); - + m_initialized = true; m_strLocale = szName; m_strShort = szShort; @@ -1406,7 +1425,7 @@ bool wxLocale::Init(const wxChar *szName, // the argument to setlocale() szLocale = szShort; - wxCHECK_MSG( szLocale, FALSE, _T("no locale to set in wxLocale::Init()") ); + wxCHECK_MSG( szLocale, false, _T("no locale to set in wxLocale::Init()") ); } #ifdef __WXWINCE__ @@ -1416,7 +1435,7 @@ bool wxLocale::Init(const wxChar *szName, 256); if (ret != 0) { - m_pszOldLocale = wxStrdup(localeName); + m_pszOldLocale = wxStrdup(localeName); } else m_pszOldLocale = NULL; @@ -1452,7 +1471,7 @@ bool wxLocale::Init(const wxChar *szName, // load the default catalog with wxWidgets standard messages m_pMsgCat = NULL; - bool bOk = TRUE; + bool bOk = true; if ( bLoadDefault ) bOk = AddCatalog(wxT("wxstd")); @@ -1460,30 +1479,30 @@ bool wxLocale::Init(const wxChar *szName, } -#if defined(__UNIX__) && wxUSE_UNICODE +#if defined(__UNIX__) && wxUSE_UNICODE && !defined(__WXMAC__) static wxWCharBuffer wxSetlocaleTryUTF(int c, const wxChar *lc) { wxMB2WXbuf l = wxSetlocale(c, lc); if ( !l && lc && lc[0] != 0 ) { - wxString buf(lc); + wxString buf(lc); wxString buf2; - buf2 = buf + wxT(".UTF-8"); - l = wxSetlocale(c, buf2.c_str()); + buf2 = buf + wxT(".UTF-8"); + l = wxSetlocale(c, buf2.c_str()); if ( !l ) { buf2 = buf + wxT(".utf-8"); - l = wxSetlocale(c, buf2.c_str()); + l = wxSetlocale(c, buf2.c_str()); } if ( !l ) { buf2 = buf + wxT(".UTF8"); - l = wxSetlocale(c, buf2.c_str()); + l = wxSetlocale(c, buf2.c_str()); } if ( !l ) { buf2 = buf + wxT(".utf8"); - l = wxSetlocale(c, buf2.c_str()); + l = wxSetlocale(c, buf2.c_str()); } } return l; @@ -1504,7 +1523,7 @@ bool wxLocale::Init(int language, int flags) // We failed to detect system language, so we will use English: if (lang == wxLANGUAGE_UNKNOWN) { - return FALSE; + return false; } const wxLanguageInfo *info = GetLanguageInfo(lang); @@ -1513,7 +1532,7 @@ bool wxLocale::Init(int language, int flags) if (info == NULL) { wxLogError(wxT("Unknown language %i."), lang); - return FALSE; + return false; } wxString name = info->Description; @@ -1561,7 +1580,7 @@ bool wxLocale::Init(int language, int flags) if ( !retloc ) { wxLogError(wxT("Cannot set locale to '%s'."), locale.c_str()); - return FALSE; + return false; } #elif defined(__WIN32__) @@ -1574,7 +1593,10 @@ bool wxLocale::Init(int language, int flags) // #ifdef SETLOCALE_FAILS_ON_UNICODE_LANGS bellow. #define SETLOCALE_FAILS_ON_UNICODE_LANGS #endif - + +#if !wxUSE_UNICODE + const +#endif wxMB2WXbuf retloc = wxT("C"); if (language != wxLANGUAGE_DEFAULT) { @@ -1585,7 +1607,7 @@ bool wxLocale::Init(int language, int flags) } else { - int codepage + int codepage #ifdef SETLOCALE_FAILS_ON_UNICODE_LANGS = -1 #endif @@ -1615,7 +1637,7 @@ bool wxLocale::Init(int language, int flags) { wxLogLastError(wxT("SetThreadLocale")); wxLogError(wxT("Cannot set locale to language %s."), name.c_str()); - return FALSE; + return false; } else { @@ -1657,12 +1679,12 @@ bool wxLocale::Init(int language, int flags) if ( !retloc ) { wxLogError(wxT("Cannot set locale to language %s."), name.c_str()); - return FALSE; + return false; } #elif defined(__WXMAC__) || defined(__WXPM__) wxMB2WXbuf retloc = wxSetlocale(LC_ALL , wxEmptyString); #else - return FALSE; + return false; #define WX_NO_LOCALE_SUPPORT #endif @@ -2148,7 +2170,7 @@ void wxLocale::AddCatalogLookupPathPrefix(const wxString& prefix) // this is a bit strange as under Windows we get the encoding name using its // numeric value and under Unix we do it the other way round, but this just -// reflects the way different systems provide he encoding info +// reflects the way different systems provide the encoding info /* static */ wxString wxLocale::GetSystemEncodingName() @@ -2180,8 +2202,18 @@ wxString wxLocale::GetSystemEncodingName() // ISO-646, i.e. 7 bit ASCII // // and recent glibc call it ANSI_X3.4-1968... - if ( strcmp(alang, "646") == 0 || - strcmp(alang, "ANSI_X3.4-1968") == 0 ) + // + // HP-UX uses HP-Roman8 cset which is not the same as ASCII (see RFC + // 1345 for its definition) but must be recognized as otherwise HP + // users get a warning about it on each program startup, so handle it + // here -- but it would be obviously better to add real supprot to it, + // of course! + if ( strcmp(alang, "646") == 0 + || strcmp(alang, "ANSI_X3.4-1968") == 0 +#ifdef __HPUX__ + || strcmp(alang, "roman8") == 0 +#endif // __HPUX__ + ) { encname = _T("US-ASCII"); } @@ -2253,11 +2285,11 @@ wxFontEncoding wxLocale::GetSystemEncoding() return wxFONTENCODING_CP950; } #elif defined(__WXMAC__) - TextEncoding encoding = 0 ; + TextEncoding encoding = 0 ; #if TARGET_CARBON - encoding = CFStringGetSystemEncoding() ; + encoding = CFStringGetSystemEncoding() ; #else - UpgradeScriptInfoToTextEncoding ( smSystemScript , kTextLanguageDontCare , kTextRegionDontCare , NULL , &encoding ) ; + UpgradeScriptInfoToTextEncoding ( smSystemScript , kTextLanguageDontCare , kTextRegionDontCare , NULL , &encoding ) ; #endif return wxMacGetFontEncFromSystemEnc( encoding ) ; #elif defined(__UNIX_LIKE__) && wxUSE_FONTMAP @@ -2265,7 +2297,7 @@ wxFontEncoding wxLocale::GetSystemEncoding() if ( !encname.empty() ) { wxFontEncoding enc = wxFontMapper::Get()-> - CharsetToEncoding(encname, FALSE /* not interactive */); + CharsetToEncoding(encname, false /* not interactive */); // on some modern Linux systems (RedHat 8) the default system locale // is UTF8 -- but it isn't supported by wxGTK in ANSI build at all so @@ -2307,6 +2339,11 @@ const wxLanguageInfo *wxLocale::GetLanguageInfo(int lang) { CreateLanguagesDB(); + // calling GetLanguageInfo(wxLANGUAGE_DEFAULT) is a natural thing to do, so + // make it work + if ( lang == wxLANGUAGE_DEFAULT ) + lang = GetSystemLanguage(); + const size_t count = ms_languagesDB->GetCount(); for ( size_t i = 0; i < count; i++ ) { @@ -2465,6 +2502,58 @@ const wxChar *wxLocale::GetString(const wxChar *szOrigString, return pszTrans; } +wxString wxLocale::GetHeaderValue( const wxChar* szHeader, + const wxChar* szDomain ) const +{ + if ( wxIsEmpty(szHeader) ) + return wxEmptyString; + + wxChar const * pszTrans = NULL; + wxMsgCatalog *pMsgCat; + + if ( szDomain != NULL ) + { + pMsgCat = FindCatalog(szDomain); + + // does the catalog exist? + if ( pMsgCat == NULL ) + return wxEmptyString; + + pszTrans = pMsgCat->GetString(wxT(""), (size_t)-1); + } + else + { + // search in all domains + for ( pMsgCat = m_pMsgCat; pMsgCat != NULL; pMsgCat = pMsgCat->m_pNext ) + { + pszTrans = pMsgCat->GetString(wxT(""), (size_t)-1); + if ( pszTrans != NULL ) // take the first found + break; + } + } + + if ( wxIsEmpty(pszTrans) ) + return wxEmptyString; + + wxChar const * pszFound = wxStrstr(pszTrans, szHeader); + if ( pszFound == NULL ) + return wxEmptyString; + + pszFound += wxStrlen(szHeader) + 2 /* ': ' */; + + // Every header is separated by \n + + wxChar const * pszEndLine = wxStrchr(pszFound, wxT('\n')); + if ( pszEndLine == NULL ) pszEndLine = pszFound + wxStrlen(pszFound); + + + // wxString( wxChar*, length); + wxString retVal( pszFound, pszEndLine - pszFound ); + + return retVal; +} + + // find catalog by name in a linked list, return NULL if !found wxMsgCatalog *wxLocale::FindCatalog(const wxChar *szDomain) const { @@ -2487,27 +2576,47 @@ bool wxLocale::IsLoaded(const wxChar *szDomain) const // add a catalog to our linked list bool wxLocale::AddCatalog(const wxChar *szDomain) +{ + return AddCatalog(szDomain, wxLANGUAGE_ENGLISH, NULL); +} + +// add a catalog to our linked list +bool wxLocale::AddCatalog(const wxChar *szDomain, + wxLanguage msgIdLanguage, + const wxChar *msgIdCharset) + { wxMsgCatalog *pMsgCat = new wxMsgCatalog; - if ( pMsgCat->Load(m_strShort, szDomain, m_bConvertEncoding) ) { + if ( pMsgCat->Load(m_strShort, szDomain, msgIdCharset, m_bConvertEncoding) ) { // add it to the head of the list so that in GetString it will // be searched before the catalogs added earlier pMsgCat->m_pNext = m_pMsgCat; m_pMsgCat = pMsgCat; - return TRUE; + return true; } else { // don't add it because it couldn't be loaded anyway delete pMsgCat; - // it's OK to not load English catalog, the texts are embedded in - // the program: - if (m_strShort.Mid(0, 2) == wxT("en")) - return TRUE; + // It is OK to not load catalog if the msgid language and m_language match, + // in which case we can directly display the texts embedded in program's + // source code: + if (m_language == msgIdLanguage) + return true; - return FALSE; + // If there's no exact match, we may still get partial match where the + // (basic) language is same, but the country differs. For example, it's + // permitted to use en_US strings from sources even if m_language is en_GB: + const wxLanguageInfo *msgIdLangInfo = GetLanguageInfo(msgIdLanguage); + if ( msgIdLangInfo && + msgIdLangInfo->CanonicalName.Mid(0, 2) == m_strShort.Mid(0, 2) ) + { + return true; + } + + return false; } } @@ -2590,7 +2699,7 @@ wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory cat) default: return wxEmptyString; } -} +} #endif // __WXMSW__/!__WXMSW__ @@ -2627,7 +2736,7 @@ class wxLocaleModule: public wxModule DECLARE_DYNAMIC_CLASS(wxLocaleModule) public: wxLocaleModule() {} - bool OnInit() { return TRUE; } + bool OnInit() { return true; } void OnExit() { wxLocale::DestroyLanguagesDB(); } };