// Created: 29/01/98
// RCS-ID: $Id$
// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
-// Licence: wxWidgets licence
+// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// Plural forms parser
// ----------------------------------------------------------------------------
-/*
+/*
Simplified Grammar
Expression:
MultiplicativeExpression ">=" MultiplicativeExpression
MultiplicativeExpression "<=" MultiplicativeExpression
MultiplicativeExpression
-
+
MultiplicativeExpression:
PmExpression '%' PmExpression
PmExpression
wxPluralFormsToken m_token;
wxPluralFormsNodePtr m_nodes[3];
};
-
+
wxPluralFormsNodePtr::~wxPluralFormsNodePtr()
{
delete m_p;
{
public:
wxPluralFormsCalculator() : m_nplurals(0), m_plural(0) {}
-
+
// input: number, returns msgstr index
int evaluate(int n) const;
void init(wxPluralFormsToken::Number nplurals, wxPluralFormsNode* plural);
wxString getString() const;
-
+
private:
wxPluralFormsToken::Number m_nplurals;
wxPluralFormsNodePtr m_plural;
wxPluralFormsScanner& m_scanner;
const wxPluralFormsToken& token() const;
bool nextToken();
-
+
wxPluralFormsNode* expression();
wxPluralFormsNode* logicalOrExpression();
wxPluralFormsNode* logicalAndExpression();
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
*m_pTransTable; // translated
wxString m_charset;
-
+
// swap the 2 halves of 32 bit integer if needed
size_t32 Swap(size_t32 ui) const
{
}
return (const char *)(m_pData + ofsString);
- }
+ }
bool m_bSwapped; // wrong endianness?
{
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; }
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:
}
}
// else: incorrectly filled Content-Type header
-
+
// Extract plural forms:
begin = header.Find(wxT("Plural-Forms:"));
if (begin != wxNOT_FOUND)
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;
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 )
{
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);
}
#if wxUSE_WCHAR_T
+ delete sourceConv;
delete csConv;
#endif
}
// ----------------------------------------------------------------------------
bool wxMsgCatalog::Load(const wxChar *szDirPrefix, const wxChar *szName,
- bool bConvertEncoding)
+ const wxChar *msgIdCharset, bool bConvertEncoding)
{
wxMsgCatalogFile file;
if ( file.Load(szDirPrefix, szName, m_pluralFormsCalculator) )
{
- file.FillHash(m_messages, bConvertEncoding);
+ file.FillHash(m_messages, msgIdCharset, bConvertEncoding);
return TRUE;
}
{
wxASSERT_MSG( !m_initialized,
_T("you can't call wxLocale::Init more than once") );
-
+
m_initialized = true;
m_strLocale = szName;
m_strShort = szShort;
256);
if (ret != 0)
{
- m_pszOldLocale = wxStrdup(localeName);
+ m_pszOldLocale = wxStrdup(localeName);
}
else
m_pszOldLocale = NULL;
// #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)
{
}
else
{
- int codepage
+ int codepage
#ifdef SETLOCALE_FAILS_ON_UNICODE_LANGS
= -1
#endif
// 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()
// 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");
}
// 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;
}
}
default:
return wxEmptyString;
}
-}
+}
#endif // __WXMSW__/!__WXMSW__