]> git.lyx.org Git - lyx.git/blobdiff - src/support/Messages.cpp
Bulk cleanup/fix incorrect annotation at the end of namespaces.
[lyx.git] / src / support / Messages.cpp
index 4e8dca17b01e19e976346a97a014b1c245bc5083..26a320b2d243c753c727b19947aade5ebfe0457b 100644 (file)
@@ -3,19 +3,17 @@
  * Licence details can be found in the file COPYING.
  *
  * \author Lars Gullik Bjønnes
+ * \author Jean-Marc Lasgouttes
  *
  * Full author contact details are available in file CREDITS.
  */
 
 /*
-  This is a limited parser for gettext's po files. Several features are
-  not handled for now:
-   * encoding is supposed to be UTF-8 (the charset parameter is not honored)
+  This contains a limited parser for gettext's mo files. Several features are
+  not implemented currently:
+   * encoding is supposed to be UTF-8 (the charset parameter is enforced)
    * context is not handled (implemented differently in LyX)
-   * plural forms not implemented (not used for now in LyX).
-   * The byte endianness of the machine on which the .mo file have been
-     built is expected to be the same as the one of the machine where this
-     code is run.
+   * plural forms are not implemented (not used for now in LyX).
 
   The data is loaded in a std::map object for simplicity.
  */
@@ -89,6 +87,7 @@
 
 #include <cerrno>
 #include <fstream>
+#include <utility>
 
 #ifdef HAVE_SYS_STAT_H
 # include <sys/stat.h>
@@ -105,10 +104,10 @@ void cleanTranslation(docstring & trans)
          Some english words have different translations, depending on
          context. In these cases the original string is augmented by
          context information (e.g. "To:[[as in 'From page x to page
-         y']]" and "To:[[as in 'From format x to format y']]". Also, 
+         y']]" and "To:[[as in 'From format x to format y']]". Also,
          when placeholders are used, the context can indicate what will
          be substituted for the placeholder (e.g. "%1$s[[date]], %1$s
-         [[time]]). This means that we need to filter out everything 
+         [[time]]). This means that we need to filter out everything
          in double square brackets at the end of the string, otherwise
          the user sees bogus messages. If we are unable to honour the
          request we just return what we got in.
@@ -128,7 +127,7 @@ void cleanTranslation(docstring & trans)
        }
 }
 
-} // lyx
+} // namespace lyx
 
 
 #ifdef ENABLE_NLS
@@ -140,7 +139,6 @@ namespace lyx {
 std::string Messages::gui_lang_;
 
 
-// This version use the traditional gettext.
 Messages::Messages(string const & l)
        : lang_(l)
 {
@@ -155,23 +153,12 @@ Messages::Messages(string const & l)
 
 namespace {
 
-string moFile(string const & c)
-{
-       static string const locale_dir
-               = package().locale_dir().toFilesystemEncoding();
-       return locale_dir + "/" + c
-               + "/LC_MESSAGES/" PACKAGE ".mo";
-}
-
-
 // Find the code we have for a given language code. Return empty if not found.
-string realCode(string const & c)
+string realCode(string code)
 {
-       // Qt tries to outsmart us and transforms en_US to C.
-       string code = (c == "C") ? "en" : c;
        // this loops at most twice
        while (true) {
-               if (FileName(moFile(code)).isReadableFile())
+               if (package().messages_file(code).isReadableFile())
                        return code;
                if (contains(code, '_'))
                        code = token(code, '_', 0);
@@ -180,7 +167,7 @@ string realCode(string const & c)
        }
        return string();
 }
-}
+} // namespace
 
 
 bool Messages::available(string const & c)
@@ -194,6 +181,15 @@ string Messages::language() const
        return realCode(lang_);
 }
 
+namespace {
+
+void swapInt(uint32_t & number)
+{
+       unsigned char * num_ar = reinterpret_cast<unsigned char *>(&number);
+       swap(num_ar[0], num_ar[3]);
+       swap(num_ar[1], num_ar[2]);
+}
+
 
 struct MoHeader
 {
@@ -207,19 +203,43 @@ struct MoHeader
        uint32_t O;
        // offset of table with translation strings
        uint32_t T;
-       // there is a hashing table afterwrds, but we ignore it
+       // there is a hash table afterwards, but we ignore it
+
+       // Change the endianness of header data
+       void swapEnd();
 };
 
 
+void MoHeader::swapEnd()
+{
+       swapInt(magic);
+       swapInt(rev);
+       swapInt(N);
+       swapInt(O);
+       swapInt(T);
+}
+
 struct StringTable
 {
        // string length
        uint32_t length;
        // string offset
        uint32_t offset;
+
+       // Change the endianness of string stable data
+       void swapEnd();
 };
 
 
+void StringTable::swapEnd()
+{
+       swapInt(length);
+       swapInt(offset);
+}
+
+
+} // namespace
+
 bool Messages::readMoFile()
 {
        // FIXME:remove
@@ -230,11 +250,11 @@ bool Messages::readMoFile()
 
        string const code = realCode(lang_);
        if (code.empty()) {
-               LYXERR0("Cannot find translation for language " << lang_);
+               LYXERR(Debug::LOCALE, "Cannot find translation for language " << lang_);
                return false;
        }
 
-       string const filen = moFile(code);
+       string const filen = package().messages_file(code).toSafeFilesystemEncoding();
 
        // get file size
        struct stat buf;
@@ -251,16 +271,28 @@ bool Messages::readMoFile()
                return false;
        }
 
-       MoHeader const * header = reinterpret_cast<MoHeader const *>(&moData[0]);
+       MoHeader * header = reinterpret_cast<MoHeader *>(&moData[0]);
+
+       bool doSwap = false;
+       if (header->magic == 0xde120495) {
+               header->swapEnd();
+               doSwap = true;
+       }
+
        if (header->magic != 0x950412de) {
                LYXERR0("Wrong magic number for file " << filen
-                       << ".\nExpected 0x950412de, got " << std::hex << header->magic);
+                       << ".\nExpected 0x950412de, got 0x" << std::hex << header->magic << std::dec);
                return false;
        }
 
-       StringTable const * orig = reinterpret_cast<StringTable const *>(&moData[0] + header->O);
-       StringTable const * trans = reinterpret_cast<StringTable const *>(&moData[0] + header->T);
+       StringTable * orig = reinterpret_cast<StringTable *>(&moData[0] + header->O);
+       StringTable * trans = reinterpret_cast<StringTable *>(&moData[0] + header->T);
        // First the header
+       if (doSwap) {
+               // Handle endiannness change
+               orig[0].swapEnd();
+               trans[0].swapEnd();
+       }
        string const info = string(&moData[0] + trans[0].offset, trans[0].length);
        size_t pos = info.find("charset=");
        if (pos != string::npos) {
@@ -282,6 +314,11 @@ bool Messages::readMoFile()
        }
 
        for (size_t i = 1; i < header->N; ++i) {
+               if (doSwap) {
+                       // Handle endiannness change
+                       orig[i].swapEnd();
+                       trans[i].swapEnd();
+               }
                // Note that in theory the strings may contain NUL characters.
                // This may be the case with plural forms
                string const ostr(&moData[0] + orig[i].offset, orig[i].length);
@@ -317,12 +354,9 @@ docstring const Messages::get(string const & m) const
 
 namespace lyx {
 
-Messages::Messages(string const & /* l */) {}
-
-void Messages::init()
-{
-}
+std::string Messages::gui_lang_;
 
+Messages::Messages(string const & /* l */) {}
 
 docstring const Messages::get(string const & m) const
 {
@@ -332,9 +366,9 @@ docstring const Messages::get(string const & m) const
 }
 
 std::string Messages::language() const
-    {
-        return string();
-    }
+{
+       return string();
+}
 
 bool Messages::available(string const & /* c */)
 {