Added ugly default key for console (Ctrl-c then F1) that works even if console is...
[supertux.git] / src / tinygettext / tinygettext.cpp
index a9bb964..ffaaf71 100644 (file)
 #include <config.h>
 
 #include <sys/types.h>
-#include <iconv.h>
 #include <fstream>
 #include <iostream>
+#include <algorithm>
 #include <ctype.h>
 #include <errno.h>
 
+#include "SDL.h"
+
 #include "tinygettext.hpp"
 #include "log.hpp"
 #include "physfs/physfs_stream.hpp"
-#include "log.hpp"
 #include "findlocale.hpp"
 
 //#define TRANSLATION_DEBUG
@@ -44,7 +45,20 @@ std::string convert(const std::string& text,
   if (from_charset == to_charset)
     return text;
 
-  iconv_t cd = iconv_open(to_charset.c_str(), from_charset.c_str());
+  char *in = new char[text.length() + 1];
+  strcpy(in, text.c_str());
+  char *out = SDL_iconv_string(to_charset.c_str(), from_charset.c_str(), in, text.length() + 1);
+  delete[] in; 
+  if(out == 0)
+  {
+    log_warning << "Error: conversion from " << from_charset << " to " << to_charset << " failed" << std::endl;
+    return "";
+  }
+  std::string ret(out);
+  SDL_free(out);
+  return ret;
+#if 0
+  iconv_t cd = SDL_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
@@ -58,7 +72,7 @@ std::string convert(const std::string& text,
   size_t out_len_temp = out_len; // iconv is counting down the bytes it has
                                  // written from this...
 
-  size_t retval = iconv(cd, &in, &in_len, &out, &out_len_temp);
+  size_t retval = SDL_iconv(cd, &in, &in_len, &out, &out_len_temp);
   out_len -= out_len_temp; // see above
   if (retval == (size_t) -1)
     {
@@ -66,12 +80,13 @@ std::string convert(const std::string& text,
       log_warning << "Error: conversion from " << from_charset << " to " << to_charset << " went wrong: " << retval << std::endl;
       return "";
     }
-  iconv_close(cd);
+  SDL_iconv_close(cd);
 
   std::string ret(out_orig, out_len);
   delete[] out_orig;
   delete[] in_orig;
   return ret;
+#endif
 }
 
 bool has_suffix(const std::string& lhs, const std::string rhs)
@@ -190,8 +205,13 @@ DictionaryManager::DictionaryManager()
   // use findlocale to setup language
   FL_Locale *locale;
   FL_FindLocale( &locale, FL_MESSAGES );
-      if( locale->lang)
-        set_language( locale->lang );
+  if(locale->lang) {
+    if (locale->country) {
+      set_language( std::string(locale->lang)+"_"+std::string(locale->country) );
+    } else {
+      set_language( std::string(locale->lang) );
+    }
+  }
   FL_FreeLocale( &locale );
 }
 
@@ -203,7 +223,7 @@ DictionaryManager::parseLocaleAliases()
 
   char c = ' ';
   while(in.good() && !in.eof()) {
-    while(isspace(c) && !in.eof())
+    while(isspace(static_cast<unsigned char>(c)) && !in.eof())
       in.get(c);
 
     if(c == '#') { // skip comments
@@ -213,14 +233,14 @@ DictionaryManager::parseLocaleAliases()
     }
 
     std::string alias;
-    while(!isspace(c) && !in.eof()) {
+    while(!isspace(static_cast<unsigned char>(c)) && !in.eof()) {
       alias += c;
       in.get(c);
     }
-    while(isspace(c) && !in.eof())
+    while(isspace(static_cast<unsigned char>(c)) && !in.eof())
       in.get(c);
     std::string language;
-    while(!isspace(c) && !in.eof()) {
+    while(!isspace(static_cast<unsigned char>(c)) && !in.eof()) {
       language += c;
       in.get(c);
     }
@@ -234,7 +254,13 @@ DictionaryManager::parseLocaleAliases()
 Dictionary&
 DictionaryManager::get_dictionary(const std::string& spec)
 {
+
+  //log_debug << "Dictionary for language \"" << spec << "\" requested" << std::endl;
+
   std::string lang = get_language_from_spec(spec);
+
+  //log_debug << "...normalized as \"" << lang << "\"" << std::endl;
+
   Dictionaries::iterator i = dictionaries.find(get_language_from_spec(lang));
   if (i != dictionaries.end())
     {
@@ -260,7 +286,25 @@ DictionaryManager::get_dictionary(const std::string& spec)
             {
               for(const char* const* filename = files;
                       *filename != 0; filename++) {
-                if(std::string(*filename) == lang + ".po") {
+
+                // check if filename matches requested language
+               std::string fname = std::string(*filename);
+               std::string load_from_file = "";
+                if(fname == lang + ".po") {
+                 load_from_file = fname;
+               } else {
+                  std::string::size_type s = lang.find("_");
+                  if(s != std::string::npos) {
+                    std::string lang_short = std::string(lang, 0, s);
+                   if (fname == lang_short + ".po") {
+                     load_from_file = lang_short;
+                   }
+                  }
+               }
+
+               // if it matched, load dictionary
+               if (load_from_file != "") {
+                  //log_debug << "Loading dictionary for language \"" << lang << "\" from \"" << filename << "\"" << std::endl;
                   std::string pofile = *p + "/" + *filename;
                   try {
                       IFileStream in(pofile);
@@ -270,6 +314,7 @@ DictionaryManager::get_dictionary(const std::string& spec)
                       log_warning << e.what() << "" << std::endl;
                   }
                 }
+
               }
               PHYSFS_freeList(files);
             }
@@ -308,7 +353,9 @@ DictionaryManager::get_languages()
 void
 DictionaryManager::set_language(const std::string& lang)
 {
+  //log_debug << "set_language \"" << lang << "\"" << std::endl;
   language = get_language_from_spec(lang);
+  //log_debug << "==> \"" << language << "\"" << std::endl;
   current_dict = & (get_dictionary(language));
 }
 
@@ -342,11 +389,20 @@ DictionaryManager::get_language_from_spec(const std::string& spec)
     lang = i->second;
   }
 
-  std::string::size_type s = lang.find_first_of("_.");
-  if(s == std::string::npos)
-    return lang;
+  std::string::size_type s = lang.find(".");
+  if(s != std::string::npos) {
+    lang = std::string(lang, 0, s);
+  }
+
+  s = lang.find("_");
+  if(s == std::string::npos) {
+    std::string lang_big = lang;
+    std::transform (lang_big.begin(), lang_big.end(), lang_big.begin(), toupper);
+    lang += "_" + lang_big;
+  }
+
+  return lang;
 
-  return std::string(lang, 0, s);
 }
 
 void
@@ -652,6 +708,9 @@ public:
               {
                 state = SKIP_COMMENT;
               }
+            else if (c == '\n')
+              {
+              }
             else
               {
                 // Read a new token
@@ -659,7 +718,7 @@ public:
 
                 do { // Read keyword
                   token.keyword += c;
-                } while((c = getchar(in)) != EOF && !isspace(c));
+                } while((c = getchar(in)) != EOF && !isspace(static_cast<unsigned char>(c)));
                 in.unget();
 
                 state = READ_CONTENT;
@@ -673,12 +732,13 @@ public:
                   // Found start of content
                   state = READ_CONTENT_IN_STRING;
                   break;
-                } else if (isspace(c)) {
+                } else if (isspace(static_cast<unsigned char>(c))) {
                   // skip
                 } else { // Read something that may be a keyword
                   in.unget();
                   state = READ_KEYWORD;
                   add_token(token);
+                  token = Token();
                   break;
                 }
               }
@@ -693,6 +753,7 @@ public:
                   else if (c == 't') token.content += '\t';
                   else if (c == 'r') token.content += '\r';
                   else if (c == '"') token.content += '"';
+                  else if (c == '\\') token.content += '\\';
                   else
                     {
                       log_warning << "Unhandled escape character: " << char(c) << std::endl;
@@ -716,6 +777,7 @@ public:
           }
       }
     add_token(token);
+    token = Token();
   }
 };