/************************************************************************ MeOS - Orienteering Software Copyright (C) 2009-2017 Melin Software HB This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, 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, see . Melin Software HB - software@melin.nu - www.melin.nu Eksoppsvägen 16, SE-75646 UPPSALA, Sweden ************************************************************************/ #include "stdafx.h" #include "localizer.h" #include #include #include "meos_util.h" #include "random.h" #include "oFreeImport.h" class LocalizerImpl { string language; map table; map unknown; void loadTable(const vector &raw, const string &language); mutable oWordList *givenNames; public: const oWordList &getGivenNames() const; void translateAll(const LocalizerImpl &all); const string &translate(const string &str, bool &found); void saveUnknown(const string &file); void saveTable(const string &file); void loadTable(const string &file, const string &language); void loadTable(int resource, const string &language); void clear(); LocalizerImpl(void); ~LocalizerImpl(void); }; Localizer::LocalizerInternal::LocalizerInternal(void) { impl = new LocalizerImpl(); implBase = 0; owning = true; user = 0; } Localizer::LocalizerInternal::~LocalizerInternal(void) { if (user) { user->owning = true; impl = 0; implBase = 0; } else { delete impl; delete implBase; } } void Localizer::LocalizerInternal::set(Localizer &lio) { Localizer::LocalizerInternal &li = *lio.linternal; if (li.user || user) throw std::exception("Runtime error"); if (owning) { delete impl; delete implBase; } implBase = li.implBase; impl = li.impl; li.user = this; } vector Localizer::LocalizerInternal::getLangResource() const { vector v; for (map::const_iterator it = langResource.begin(); it !=langResource.end(); ++it) v.push_back(it->first); return v; } const oWordList &Localizer::LocalizerInternal::getGivenNames() const { return impl->getGivenNames(); } LocalizerImpl::LocalizerImpl(void) { givenNames = 0; } LocalizerImpl::~LocalizerImpl(void) { if (givenNames) delete givenNames; } const string &Localizer::LocalizerInternal::tl(const string &str) const { bool found; const string *ret = &impl->translate(str, found); if (found || !implBase) return *ret; ret = &implBase->translate(str, found); return *ret; } const string &LocalizerImpl::translate(const string &str, bool &found) { found = false; static int i = 0; const int bsize = 17; static string value[bsize]; int len = str.length(); if (len==0) return str; if (str[0]=='#') { i = (i + 1)%bsize; value[i] = str.substr(1); found = true; return value[i]; } if (str[0]==',' || str[0]==' ' || str[0]=='.' || str[0]==':' || str[0]==';' || str[0]=='<' || str[0]=='>' || str[0]=='-' || str[0]==0x96) { unsigned k=1; while(str[k] && (str[k]==' ' || str[k]=='.' || str[k]==':' || str[k]=='<' || str[k]=='>' || str[k]=='-' || str[k]==0x96)) k++; if (k::const_iterator it = table.find(str); if (it != table.end()) { found = true; return it->second; } int subst = str.find_first_of('#'); if (subst != str.npos) { string s = translate(str.substr(0, subst), found); vector split_vec; split(str.substr(subst+1), "#", split_vec); split_vec.push_back(""); const char *subsymb = "XYZW"; size_t subpos = 0; string ret; size_t lastpos = 0; for (size_t k = 0; k=split_vec.size() || subpos>=4) break; if (s[k] == subsymb[subpos]) { if (k>0 && isalnum(s[k-1])) continue; if (k+1 < s.size() && isalnum(s[k+1])) continue; ret += s.substr(lastpos, k-lastpos); ret += split_vec[subpos]; lastpos = k+1; subpos++; } } if (lastpos1) unknown[str] = ""; #endif found = false; i = (i + 1)%bsize; value[i] = str; return value[i]; } string suffix; int pos = str.find_last_not_of(last); while(pos>0) { char last = str[pos]; if (last != ':' && last != ' ' && last != ',' && last != '.' && last != ';' && last != '<' && last != '>' && last != '-' && last != 0x96) break; pos = str.find_last_not_of(last, pos); } suffix = str.substr(pos+1); string key = str.substr(0, str.length()-suffix.length()); it = table.find(key); if (it != table.end()) { i = (i + 1)%bsize; value[i] = it->second + suffix; found = true; return value[i]; } #ifdef _DEBUG if (key.length() > 1) unknown[key] = ""; #endif found = false; i = (i + 1)%bsize; value[i] = str; return value[i]; } const string newline = "\n"; void LocalizerImpl::saveUnknown(const string &file) { if (!unknown.empty()) { ofstream fout(file.c_str(), ios::trunc|ios::out); for (map::iterator it = unknown.begin(); it!=unknown.end(); ++it) { string value = it->second; string key = it->first; if (value.empty()) { value = key; int nl = value.find(newline); int n2 = value.find("."); if (nl!=string::npos || n2!=string::npos) { while (nl!=string::npos) { value.replace(nl, newline.length(), "\\n"); nl = value.find(newline); } key = "help:" + itos(value.length()) + itos(value.find_first_of(".")); } } fout << key << " = " << value << endl; } } } const oWordList &LocalizerImpl::getGivenNames() const { if (givenNames == 0) { char bf[260]; getUserFile(bf, "given.mwd"); givenNames = new oWordList(); try { givenNames->load(bf); } catch(std::exception &) {} } return *givenNames; } #ifndef MEOSDB void Localizer::LocalizerInternal::loadLangResource(const string &name) { map::iterator it = langResource.find(name); if (it == langResource.end()) throw std::exception("Unknown language"); string &res = it->second; int i = atoi(res.c_str()); if (i > 0) impl->loadTable(i, name); else impl->loadTable(res, name); } void Localizer::LocalizerInternal::addLangResource(const string &name, const string &resource) { langResource[name] = resource; if (implBase == 0) { implBase = new LocalizerImpl(); implBase->loadTable(atoi(resource.c_str()), name); } } void Localizer::LocalizerInternal::debugDump(const string &untranslated, const string &translated) const { if (implBase) { impl->translateAll(*implBase); } impl->saveUnknown(untranslated); impl->saveTable(translated); } void LocalizerImpl::translateAll(const LocalizerImpl &all) { map::const_iterator it; bool f; for (it = all.table.begin(); it != all.table.end(); ++it) { translate(it->first, f); if (!f) { unknown[it->first] = it->second; } } } void LocalizerImpl::saveTable(const string &file) { ofstream fout((language+"_"+file).c_str(), ios::trunc|ios::out); for (map::iterator it = table.begin(); it!=table.end(); ++it) { string value = it->second; int nl = value.find(newline); while (nl!=string::npos) { value.replace(nl, newline.length(), "\\n"); nl = value.find(newline); } fout << it->first << " = " << value << endl; } } void LocalizerImpl::loadTable(int id, const string &language) { string sname = "#"+itos(id); const char *name = sname.c_str(); HRSRC hResInfo = FindResource(0, name, "#300"); HGLOBAL hGlobal = LoadResource(0, hResInfo); if (hGlobal==0) throw std::exception("Resource not found"); int size = SizeofResource(0, hResInfo); const char *lang_src = (char *)LockResource(hGlobal); char *lang = new char[size]; memcpy(lang, lang_src, size); char *bf; vector raw; int pos = 0; while (pos < size) { bf = &lang[pos]; while(pos0 && bf[0] != '#') raw.push_back(bf); pos++; if (pos raw; raw.reserve(line); while (!fin.eof()) { bf[0] = 0; fin.getline(bf, 8*1024); if (bf[0]!=0 && bf[0]!='#') raw.push_back(bf); } loadTable(raw, language); } void LocalizerImpl::loadTable(const vector &raw, const string &language) { vector order(raw.size()); for (size_t k = 0; klanguage = language; for (size_t k=0;k0 && s[spos-1]==' ') spos--; while (unsigned(epos)