+wxPluralFormsNode* wxPluralFormsParser::pmExpression()
+{
+ wxPluralFormsNodePtr n;
+ if (token().type() == wxPluralFormsToken::T_N
+ || token().type() == wxPluralFormsToken::T_NUMBER)
+ {
+ n.reset(new wxPluralFormsNode(token()));
+ if (!nextToken())
+ {
+ return NULL;
+ }
+ }
+ else if (token().type() == wxPluralFormsToken::T_LEFT_BRACKET) {
+ if (!nextToken())
+ {
+ return NULL;
+ }
+ wxPluralFormsNode* p = expression();
+ if (p == NULL)
+ {
+ return NULL;
+ }
+ n.reset(p);
+ if (token().type() != wxPluralFormsToken::T_RIGHT_BRACKET)
+ {
+ return NULL;
+ }
+ if (!nextToken())
+ {
+ return NULL;
+ }
+ }
+ else
+ {
+ return NULL;
+ }
+ return n.release();
+}
+
+wxPluralFormsCalculator* wxPluralFormsCalculator::make(const char* s)
+{
+ wxPluralFormsCalculatorPtr calculator(new wxPluralFormsCalculator);
+ if (s != NULL)
+ {
+ wxPluralFormsScanner scanner(s);
+ wxPluralFormsParser p(scanner);
+ if (!p.parse(*calculator))
+ {
+ return NULL;
+ }
+ }
+ return calculator.release();
+}
+
+
+
+
+// ----------------------------------------------------------------------------
+// wxMsgCatalogFile corresponds to one disk-file message catalog.
+//
+// This is a "low-level" class and is used only by wxMsgCatalog
+// ----------------------------------------------------------------------------
+
+WX_DECLARE_EXPORTED_STRING_HASH_MAP(wxString, wxMessagesHash);
+
+class wxMsgCatalogFile
+{
+public:
+ // ctor & dtor
+ wxMsgCatalogFile();
+ ~wxMsgCatalogFile();
+
+ // load the catalog from disk (szDirPrefix corresponds to language)
+ bool Load(const wxChar *szDirPrefix, const wxChar *szName,
+ wxPluralFormsCalculatorPtr& rPluralFormsCalculator);
+
+ // fills the hash with string-translation pairs
+ void FillHash(wxMessagesHash& hash, bool convertEncoding) const;
+
+private:
+ // this implementation is binary compatible with GNU gettext() version 0.10
+
+ // an entry in the string table
+ struct wxMsgTableEntry
+ {
+ size_t32 nLen; // length of the string
+ size_t32 ofsString; // pointer to the string
+ };
+
+ // header of a .mo file
+ struct wxMsgCatalogHeader
+ {
+ size_t32 magic, // offset +00: magic id
+ revision, // +04: revision
+ numStrings; // +08: number of strings in the file
+ size_t32 ofsOrigTable, // +0C: start of original string table
+ ofsTransTable; // +10: start of translated string table
+ size_t32 nHashSize, // +14: hash table size
+ ofsHashTable; // +18: offset of hash table start
+ };
+
+ // all data is stored here, NULL if no data loaded
+ size_t8 *m_pData;
+
+ // amount of memory pointed to by m_pData.
+ size_t32 m_nSize;
+
+ // data description
+ size_t32 m_numStrings; // number of strings in this domain
+ wxMsgTableEntry *m_pOrigTable, // pointer to original strings
+ *m_pTransTable; // translated
+
+ wxString m_charset;
+
+ // swap the 2 halves of 32 bit integer if needed
+ size_t32 Swap(size_t32 ui) const
+ {
+ return m_bSwapped ? (ui << 24) | ((ui & 0xff00) << 8) |
+ ((ui >> 8) & 0xff00) | (ui >> 24)
+ : ui;
+ }
+
+ const char *StringAtOfs(wxMsgTableEntry *pTable, size_t32 n) const
+ {
+ const wxMsgTableEntry * const ent = pTable + n;
+
+ // this check could fail for a corrupt message catalog
+ size_t32 ofsString = Swap(ent->ofsString);
+ if ( ofsString + Swap(ent->nLen) > m_nSize)
+ {
+ return NULL;
+ }
+
+ return (const char *)(m_pData + ofsString);
+ }
+
+ bool m_bSwapped; // wrong endianness?
+
+ DECLARE_NO_COPY_CLASS(wxMsgCatalogFile)
+};
+
+
+// ----------------------------------------------------------------------------
+// wxMsgCatalog corresponds to one loaded message catalog.
+//
+// This is a "low-level" class and is used only by wxLocale (that's why
+// it's designed to be stored in a linked list)
+// ----------------------------------------------------------------------------
+
+class wxMsgCatalog
+{
+public:
+ // load the catalog from disk (szDirPrefix corresponds to language)
+ bool Load(const wxChar *szDirPrefix, const wxChar *szName, bool bConvertEncoding = FALSE);
+
+ // get name of the catalog
+ wxString GetName() const { return m_name; }
+
+ // get the translated string: returns NULL if not found
+ const wxChar *GetString(const wxChar *sz, size_t n = size_t(-1)) const;
+
+ // public variable pointing to the next element in a linked list (or NULL)
+ wxMsgCatalog *m_pNext;
+
+private:
+ wxMessagesHash m_messages; // all messages in the catalog
+ wxString m_name; // name of the domain
+ wxPluralFormsCalculatorPtr m_pluralFormsCalculator;
+};
+
+// ----------------------------------------------------------------------------
+// global variables
+// ----------------------------------------------------------------------------
+
+// the list of the directories to search for message catalog files
+static wxArrayString s_searchPrefixes;
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// wxMsgCatalogFile class
+// ----------------------------------------------------------------------------
+
+wxMsgCatalogFile::wxMsgCatalogFile()