/* * This file is a part of Winix * and is not publicly distributed * * Copyright (c) 2010-2012, Tomasz Sowa * All rights reserved. * */ #include #include "locale.h" #include "core/log.h" #include "utf8/utf8.h" Locale::Locale() { locale_files.push_back(L"en"); loc_tab.resize(locale_files.size()); loc_tab_multi.resize(locale_files.size()); default_lang = 0; current_lang = 0; input_as_utf8 = false; } void Locale::SetLocaleFiles(const std::vector & files) { locale_files = files; if( locale_files.empty() ) locale_files.push_back(L"en"); loc_tab.resize(locale_files.size()); loc_tab_multi.resize(locale_files.size()); } void Locale::ReadFile(const char * dir, const char * dir_def, size_t lang, const char * file) { if( lang >= loc_tab.size() ) return; loc_tab[lang].clear(); bool read = false; if( dir_def && ReadFile(dir_def, lang, file) ) read = true; if( dir && ReadFile(dir, lang, file) ) read = true; if( !read ) log << log1 << "Locale: can't open locale's file: " << file << logend; } bool Locale::ReadFile(const char * dir, size_t lang, const char * file) { bool read = false; file_name = dir; file_name += '/'; file_name += file; // !! dodac sprawdzenie poprawnosci nazwy pliku (czy nie zawiera specjalnych znakow) loc_parser.SplitSingle(true); loc_parser.UTF8(input_as_utf8); loc_parser.SetSpace(space); if( loc_parser.Parse(file_name) == PT::SpaceParser::ok ) { read = true; AddLocale(lang); log << log3 << "Locale: read locale from: " << file_name << logend; } return read; } void Locale::AddLocale(size_t lang) { PT::Space::TableSingle::iterator i = space.table_single.begin(); for( ; i != space.table_single.end() ; ++i) loc_tab[lang][i->first] = i->second; // lists PT::Space::Table::iterator i2 = space.table.begin(); for( ; i2 != space.table.end() ; ++i2) loc_tab_multi[lang][i2->first] = i2->second; } void Locale::ReadSubstTable(const char * dir, const char * dir_def) { bool read = false; subst_url.clear(); subst_smalllet.clear(); subst_capitallet.clear(); subst_sort.clear(); if( dir_def && ReadSubstTable(dir_def) ) read = true; if( dir && ReadSubstTable(dir) ) read = true; if( !read ) log << log1 << "Locale: can't open file for characters substitution" << logend; } bool Locale::ReadSubstTable(const char * dir) { bool read = false; file_name = dir; file_name += '/'; file_name += "substitute"; loc_parser.SplitSingle(true); loc_parser.UTF8(input_as_utf8); if( loc_parser.Parse(file_name) == PT::SpaceParser::ok ) { read = true; CreateSubstVector(subst_url, space.table_single[L"url_original"], space.table_single[L"url_changeto"]); CreateSubstVector(subst_smalllet, space.table_single[L"smallleters"], space.table_single[L"capitalics"]); CreateSubstVector(subst_capitallet, space.table_single[L"capitalics"], space.table_single[L"smallleters"]); CreateSubstSortVector(subst_sort, space.table[L"sort"]); log << log3 << "Locale: read characters substitution tables from: " << file_name << logend; } return read; } void Locale::CreateSubstVector(std::vector & vect, const std::wstring & tab1, const std::wstring & tab2) { size_t i, min_size = (tab1.size() < tab2.size()) ? tab1.size() : tab2.size(); SubstItem s; vect.clear(); if( min_size == 0 ) return; vect.reserve(min_size); for(i=0 ; i & vect, std::vector & tab) { SubstItem s; vect.clear(); if( tab.empty() ) return; vect.reserve(tab.size()); for(size_t i=0 ; i= 3 ) { s.from = tab[i][0]; s.to = tab[i][1]; s.index = Toi(&tab[i][2]); vect.push_back(s); } } std::sort(vect.begin(), vect.end()); } void Locale::Read(const char * dir, const char * dir_def) { for(size_t i=0 ; i= loc_tab.size() ) current_lang = loc_tab.size() - 1; } size_t Locale::GetLang() const { return current_lang; } void Locale::SetLangDef(size_t lang) { default_lang = lang; if( default_lang >= loc_tab.size() ) default_lang = loc_tab.size() - 1; } size_t Locale::GetLangDef() const { return default_lang; } bool Locale::IsKey(const wchar_t * key) { key_str = key; return IsKey(key_str); } bool Locale::IsKey(const wchar_t * key, size_t lang) { key_str = key; return IsKey(key_str, lang); } bool Locale::IsKey(const std::wstring & key) const { return IsKey(key, current_lang); } bool Locale::IsKey(const std::wstring & key, size_t lang) const { if( lang >= loc_tab.size() ) return false; // looking in the 'lang' language PT::Space::TableSingle::const_iterator i = loc_tab[lang].find(key); if( i != loc_tab[lang].end() ) return true; if( lang == default_lang ) return false; if( default_lang >= loc_tab.size() ) return false; // looking in a default language i = loc_tab[default_lang].find(key); if( i != loc_tab[default_lang].end() ) return true; // there is no such a key return false; } bool Locale::IsKeyLang(const wchar_t * key, size_t lang) { key_str = key; return IsKeyLang(key_str, lang); } bool Locale::IsKeyLang(const std::wstring & key, size_t lang) const { if( lang >= loc_tab.size() ) return false; // looking in the 'lang' language PT::Space::TableSingle::const_iterator i = loc_tab[lang].find(key); return i != loc_tab[lang].end(); } const std::wstring & Locale::Get(const wchar_t * key) { key_str = key; return Get(key_str); } const std::wstring & Locale::Get(const wchar_t * key, size_t lang) { key_str = key; return Get(key_str, lang); } const std::wstring & Locale::Get(const std::wstring & key) const { return Get(key, current_lang); } const std::wstring & Locale::Get(const std::wstring & key, size_t lang) const { if( lang >= loc_tab.size() ) return empty; // looking in the 'lang' language PT::Space::TableSingle::const_iterator i = loc_tab[lang].find(key); if( i != loc_tab[lang].end() ) return i->second; if( lang == default_lang ) return empty; if( default_lang >= loc_tab.size() ) return empty; // looking in a default language i = loc_tab[default_lang].find(key); if( i != loc_tab[default_lang].end() ) return i->second; // there is no such a key return empty; } bool Locale::IsKeyLangList(const wchar_t * key, size_t lang) { key_str = key; return IsKeyLangList(key_str, lang); } bool Locale::IsKeyLangList(const std::wstring & key, size_t lang) const { if( lang >= loc_tab_multi.size() ) return false; // looking in the 'lang' language PT::Space::Table::const_iterator i = loc_tab_multi[lang].find(key); return i != loc_tab_multi[lang].end(); } const std::vector & Locale::GetList(const std::wstring & key) const { return GetList(key, current_lang); } const std::vector & Locale::GetList(const std::wstring & key, size_t lang) const { if( lang >= loc_tab_multi.size() ) return empty_list; // looking in the 'lang' language PT::Space::Table::const_iterator i = loc_tab_multi[lang].find(key); if( i != loc_tab_multi[lang].end() ) return i->second; if( lang == default_lang ) return empty_list; if( default_lang >= loc_tab_multi.size() ) return empty_list; // looking in a default language i = loc_tab_multi[default_lang].find(key); if( i != loc_tab_multi[default_lang].end() ) return i->second; // there is no such a key return empty_list; } size_t Locale::FileNameToLang(const std::wstring & str) const { for(size_t i=0 ; i=locale_files.size() ) return empty; return locale_files[lang]; } void Locale::UTF8(bool utf) { input_as_utf8 = utf; } /* binary search in vect vect should be sorted by 'from' if the 'val' is found in vect[].from then its index is returned (index to vect table) else vect.size() is returned */ size_t Locale::SubstFindIndex(const std::vector & vect, wchar_t val) { if( vect.empty() ) return vect.size(); size_t o1 = 0; size_t o2 = vect.size() - 1; if( val < vect[o1].from ) return vect.size(); if( val == vect[o1].from ) return o1; if( val > vect[o2].from ) return vect.size(); if( val == vect[o2].from ) return o2; while( o1 + 1 < o2 ) { size_t o = (o1 + o2) / 2; if( val == vect[o].from ) return o; if( val < vect[o].from ) o2 = o; else o1 = o; } return vect.size(); } /* binary search in vect vect should be sorted by 'from' if the 'val' is found in vect[].from then vect[].to is returned else 'val' is returned */ wchar_t Locale::SubstFind(const std::vector & vect, wchar_t val) { size_t i = SubstFindIndex(vect, val); if( i == vect.size() ) { return val; } else { return vect[i].to; } } wchar_t Locale::UrlSubst(wchar_t c) { return SubstFind(subst_url, c); } void Locale::UrlSubst(std::wstring & str) { for(size_t i=0 ; i='A' && c<='Z' ) return c - 'A' + 'a'; return SubstFind(subst_capitallet, c); } void Locale::ToSmall(std::wstring & str) { for(size_t i=0 ; i='a' && c<='z' ) return c - 'a' + 'A'; return SubstFind(subst_smalllet, c); } void Locale::ToCapital(std::wstring & str) { for(size_t i=0 ; i='a' && c1<='z') || (c1>='A' && c1<='Z')) ) { size_t i1 = SubstFindIndex(subst_sort, c1); if( i1 < subst_sort.size() ) { s1.to = subst_sort[i1].to; s1.index = subst_sort[i1].index; } } if( !((c2>='a' && c2<='z') || (c2>='A' && c2<='Z')) ) { size_t i2 = SubstFindIndex(subst_sort, c2); if( i2 < subst_sort.size() ) { s2.to = subst_sort[i2].to; s2.index = subst_sort[i2].index; } } wchar_t small1 = ToSmall(s1.to); wchar_t small2 = ToSmall(s2.to); if( small1 == small2 ) { if( s1.index != s2.index ) return s1.index - s2.index; // this will sort capital letters at the end (after small ones) return s1.to - s2.to; } return small1 - small2; } /* comparing lexicographically two strings return value: less than 0 if str1 is 'less' than str2 zero if they are equal greater than 0 if str1 is 'greater' than str2 */ int Locale::Compare(const std::wstring & str1, const std::wstring & str2) { size_t i1 = 0; size_t i2 = 0; for( ; i1 < str1.size() && i2 < str2.size() ; ++i1, ++i2) { int res = Compare(str1[i1], str2[i2]); if( res != 0 ) return res; } if( str1.size() < str2.size() ) return -1; if( str1.size() > str2.size() ) return 1; return 0; }