Fixed wrong "top-edge" tiles in data/levels/bonus2/level11.stl ("The long cave")
[supertux.git] / src / tinygettext / tinygettext.cpp
index 9ffd17c..e248801 100644 (file)
@@ -1,7 +1,7 @@
 //  $Id$
-// 
-//  TinyGetText - A small flexible gettext() replacement
-//  Copyright (C) 2004 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  TinyGetText
+//  Copyright (C) 2006 Ingo Ruhnke <grumbel@gmx.de>
 //
 //  This program is free software; you can redistribute it and/or
 //  modify it under the terms of the GNU General Public License
 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 //  GNU General Public License for more details.
-// 
+//
 //  You should have received a copy of the GNU General Public License
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
 #include <config.h>
 
 #include <sys/types.h>
 #include <iconv.h>
-#include <dirent.h>
 #include <fstream>
 #include <iostream>
 #include <ctype.h>
 #include <errno.h>
-#include "tinygettext.h"
+
+#include "tinygettext.hpp"
+#include "log.hpp"
+#include "physfs/physfs_stream.hpp"
+#include "log.hpp"
 
 //#define TRANSLATION_DEBUG
 
@@ -34,7 +38,7 @@ namespace TinyGetText {
 /** Convert \a which is in \a from_charset to \a to_charset and return it */
 std::string convert(const std::string& text,
                     const std::string& from_charset,
-                    const std::string& to_charset)           
+                    const std::string& to_charset)
 {
   if (from_charset == to_charset)
     return text;
@@ -42,14 +46,14 @@ std::string convert(const std::string& text,
   iconv_t cd = iconv_open(to_charset.c_str(), from_charset.c_str());
   
   size_t in_len = text.length();
-  size_t out_len = text.length()*3; // FIXME: cross fingers that this is enough        
+  size_t out_len = text.length()*3; // FIXME: cross fingers that this is enough
 
   char*  out_orig = new char[out_len];
   char*  in_orig  = new char[in_len+1];
   strcpy(in_orig, text.c_str());
 
   char* out = out_orig;
-  char* in  = in_orig;
+  ICONV_CONST char* in  = in_orig;
   size_t out_len_temp = out_len; // iconv is counting down the bytes it has
                                  // written from this...
 
@@ -57,9 +61,8 @@ std::string convert(const std::string& text,
   out_len -= out_len_temp; // see above
   if (retval == (size_t) -1)
     {
-      std::cerr << strerror(errno) << std::endl;
-      std::cerr << "Error: conversion from " << from_charset
-                << " to " << to_charset << " went wrong: " << retval << std::endl;
+      log_warning << strerror(errno) << std::endl;
+      log_warning << "Error: conversion from " << from_charset << " to " << to_charset << " went wrong: " << retval << std::endl;
       return "";
     }
   iconv_close(cd);
@@ -235,7 +238,7 @@ DictionaryManager::get_dictionary(const std::string& spec)
     }
   else // Dictionary for languages lang isn't loaded, so we load it
     {
-      //std::cout << "get_dictionary: " << lang << std::endl;
+      //log_debug << "get_dictionary: " << lang << std::endl;
       Dictionary& dict = dictionaries[lang];
 
       dict.set_language(get_language_def(lang));
@@ -244,31 +247,27 @@ DictionaryManager::get_dictionary(const std::string& spec)
 
       for (SearchPath::iterator p = search_path.begin(); p != search_path.end(); ++p)
         {
-          DIR* dir = opendir(p->c_str());
-          if (!dir)
+          char** files = PHYSFS_enumerateFiles(p->c_str());
+          if(!files) 
             {
-              std::cerr << "Error: opendir() failed on " << *p << std::endl;
+              log_warning << "Error: enumerateFiles() failed on " << *p << std::endl;
             }
           else
             {
-              struct dirent* ent;
-              while((ent = readdir(dir)))
-                {
-                  if (std::string(ent->d_name) == lang + ".po")
-                    {
-                      std::string pofile = *p + "/" + ent->d_name;
-                      std::ifstream in(pofile.c_str());
-                      if (!in)
-                        {
-                          std::cerr << "Error: Failure file opening: " << pofile << std::endl;
-                        }
-                      else
-                        {
-                          read_po_file(dict, in);
-                        }
-                    }
+              for(const char* const* filename = files;
+                      *filename != 0; filename++) {
+                if(std::string(*filename) == lang + ".po") {
+                  std::string pofile = *p + "/" + *filename;
+                  try {
+                      IFileStream in(pofile);
+                      read_po_file(dict, in);
+                  } catch(std::exception& e) {
+                      log_warning << "Error: Failure file opening: " << pofile << std::endl;
+                      log_warning << e.what() << "" << std::endl;
+                  }
                 }
-              closedir(dir);
+              }
+              PHYSFS_freeList(files);
             }
         }
 
@@ -283,23 +282,20 @@ DictionaryManager::get_languages()
 
   for (SearchPath::iterator p = search_path.begin(); p != search_path.end(); ++p)
     {
-      DIR* dir = opendir(p->c_str());
-      if (!dir)
+      char** files = PHYSFS_enumerateFiles(p->c_str());
+      if (!files)
         {
-          std::cerr << "Error: opendir() failed on " << *p << std::endl;
+          log_warning << "Error: opendir() failed on " << *p << std::endl;
         }
       else
         {
-          struct dirent* ent;
-          while((ent = readdir(dir)))
-            {
-              if (has_suffix(ent->d_name, ".po"))
-                {
-                  std::string filename = ent->d_name;
+          for(const char* const* file = files; *file != 0; file++) {
+              if(has_suffix(*file, ".po")) {
+                  std::string filename = *file;
                   languages.insert(filename.substr(0, filename.length()-3));
-                }
-            }
-          closedir(dir);
+              }
+          }
+          PHYSFS_freeList(files);
         }
     }  
   return languages;
@@ -312,6 +308,12 @@ DictionaryManager::set_language(const std::string& lang)
   current_dict = & (get_dictionary(language));
 }
 
+const std::string&
+DictionaryManager::get_language() const
+{
+  return language;
+}
+
 void
 DictionaryManager::set_charset(const std::string& charset)
 {
@@ -404,10 +406,10 @@ Dictionary::translate(const std::string& msgid, const std::string& msgid2, int n
   else
     {
 #ifdef TRANSLATION_DEBUG
-      std::cerr << "Warning: Couldn't translate: " << msgid << std::endl;
-      std::cerr << "Candidates: " << std::endl;
+      log_warning << "Couldn't translate: " << msgid << std::endl;
+      log_warning << "Candidates: " << std::endl;
       for (PluralEntries::iterator i = plural_entries.begin(); i != plural_entries.end(); ++i)
-        std::cout << "'" << i->first << "'" << std::endl;
+        log_debug << "'" << i->first << "'" << std::endl;
 #endif
 
       if (plural2_1(num)) // default to english rules
@@ -417,35 +419,38 @@ Dictionary::translate(const std::string& msgid, const std::string& msgid2, int n
     }
 }
 
-std::string
-Dictionary::translate(const std::string& msgid) 
+const char*
+Dictionary::translate(const char* msgid)
 {
   Entries::iterator i = entries.find(msgid);
   if (i != entries.end() && !i->second.empty())
     {
-      return i->second;
+      return i->second.c_str();
     }
   else
     {
 #ifdef TRANSLATION_DBEUG
-      std::cout << "Error: Couldn't translate: " << msgid << std::endl;
+      log_warning << "Couldn't translate: " << msgid << std::endl;
 #endif
       return msgid;
     }
 }
 
-const char*
-Dictionary::translate(const char* msgid)
+std::string
+Dictionary::translate(const std::string& msgid) 
 {
   Entries::iterator i = entries.find(msgid);
-  if(i == entries.end() || i->second.empty()) {
+  if (i != entries.end() && !i->second.empty())
+    {
+      return i->second;
+    }
+  else
+    {
 #ifdef TRANSLATION_DBEUG
-    std::cout << "Error: Couldn't translate: " << msgid << std::endl;
-#endif                                                                     
-    return msgid;
-  }
-
-  return i->second.c_str();
+      log_warning << "Couldn't translate: " << msgid << std::endl;
+#endif
+      return msgid;
+    }
 }
   
 void
@@ -493,10 +498,10 @@ public:
     line_num = 0;
     char c = in.get();
     if(c == (char) 0xef) { // skip UTF-8 intro that some texteditors produce
-      in.get();
-      in.get();
+        in.get();
+        in.get();
     } else {
-      in.unget();
+        in.unget();
     }
     tokenize_po(in);
   }
@@ -526,14 +531,14 @@ public:
 
     if (from_charset.empty() || from_charset == "CHARSET")
       {
-        std::cerr << "Error: Charset not specified for .po, fallback to ISO-8859-1" << std::endl;
+        log_warning << "Error: Charset not specified for .po, fallback to ISO-8859-1" << std::endl;
         from_charset = "ISO-8859-1";
       }
 
     to_charset = dict.get_charset();
     if (to_charset.empty())
-      { // No charset requested from the dict, so we use the one from the .po 
-        to_charset = from_charset;
+      { // No charset requested from the dict, use utf-8
+        to_charset = "utf-8";
         dict.set_charset(from_charset);
       }
   }
@@ -550,12 +555,11 @@ public:
           }
         else if (token.keyword.empty())
           {
-            //std::cerr << "Got EOF, everything looks ok." << std::endl;
+            //log_warning << "Got EOF, everything looks ok." << std::endl;
           }
         else
           {
-            std::cerr << "tinygettext: expected 'msgid' keyword, got " << token.keyword 
-                      << " at line " << line_num << std::endl;
+            log_warning << "tinygettext: expected 'msgid' keyword, got " << token.keyword << " at line " << line_num << std::endl;
           }
         break;
     
@@ -587,8 +591,7 @@ public:
           } 
         else
           {
-            std::cerr << "tinygettext: expected 'msgstr' keyword, got " << token.keyword 
-                      << " at line " << line_num << std::endl;
+            log_warning << "tinygettext: expected 'msgstr' keyword, got " << token.keyword << " at line " << line_num << std::endl;
           }
         break;
 
@@ -598,7 +601,7 @@ public:
             int num;
             if (sscanf(token.keyword.c_str(), "msgstr[%d]", &num) != 1) 
               {
-                std::cerr << "Error: Couldn't parse: " << token.keyword << std::endl;
+                log_warning << "Error: Couldn't parse: " << token.keyword << std::endl;
               } 
             else 
               {
@@ -637,7 +640,7 @@ public:
 
     while((c = getchar(in)) != EOF)
       {
-        //std::cout << "Lexing char: " << char(c) << " " << state << std::endl;
+        //log_debug << "Lexing char: " << char(c) << " " << state << std::endl;
         switch(state)
           {
           case READ_KEYWORD:
@@ -688,12 +691,12 @@ public:
                   else if (c == '"') token.content += '"';
                   else
                     {
-                      std::cout << "Unhandled escape character: " << char(c) << std::endl;
+                      log_warning << "Unhandled escape character: " << char(c) << std::endl;
                     }
                 }
               else
                 {
-                  std::cout << "Unterminated string" << std::endl;
+                  log_warning << "Unterminated string" << std::endl;
                 }
             } else if (c == '"') { // Content string is terminated
               state = READ_CONTENT;