1 // 2 // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) 3 // 4 // Distributed under the Boost Software License, Version 1.0. (See 5 // accompanying file LICENSE_1_0.txt or copy at 6 // http://www.boost.org/LICENSE_1_0.txt) 7 // 8 #define BOOST_LOCALE_SOURCE 9 #include <boost/locale/localization_backend.hpp> 10 #include <boost/locale/gnu_gettext.hpp> 11 #include "all_generator.hpp" 12 #include "../util/locale_data.hpp" 13 #include "../util/gregorian.hpp" 14 #include <boost/locale/util.hpp> 15 #include <algorithm> 16 #include <iterator> 17 18 #if defined(BOOST_WINDOWS) 19 # ifndef NOMINMAX 20 # define NOMINMAX 21 # endif 22 # include <windows.h> 23 # include "../encoding/conv.hpp" 24 # include "../win32/lcid.hpp" 25 #endif 26 27 #include "std_backend.hpp" 28 29 namespace boost { 30 namespace locale { 31 namespace impl_std { 32 33 class std_localization_backend : public localization_backend { 34 public: std_localization_backend()35 std_localization_backend() : 36 invalid_(true), 37 use_ansi_encoding_(false) 38 { 39 } std_localization_backend(std_localization_backend const & other)40 std_localization_backend(std_localization_backend const &other) : 41 localization_backend(), 42 paths_(other.paths_), 43 domains_(other.domains_), 44 locale_id_(other.locale_id_), 45 invalid_(true), 46 use_ansi_encoding_(other.use_ansi_encoding_) 47 { 48 } clone() const49 virtual std_localization_backend *clone() const 50 { 51 return new std_localization_backend(*this); 52 } 53 set_option(std::string const & name,std::string const & value)54 void set_option(std::string const &name,std::string const &value) 55 { 56 invalid_ = true; 57 if(name=="locale") 58 locale_id_ = value; 59 else if(name=="message_path") 60 paths_.push_back(value); 61 else if(name=="message_application") 62 domains_.push_back(value); 63 else if(name=="use_ansi_encoding") 64 use_ansi_encoding_ = value == "true"; 65 66 } clear_options()67 void clear_options() 68 { 69 invalid_ = true; 70 use_ansi_encoding_ = false; 71 locale_id_.clear(); 72 paths_.clear(); 73 domains_.clear(); 74 } 75 prepare_data()76 void prepare_data() 77 { 78 if(!invalid_) 79 return; 80 invalid_ = false; 81 std::string lid=locale_id_; 82 if(lid.empty()) { 83 bool use_utf8 = ! use_ansi_encoding_; 84 lid = util::get_system_locale(use_utf8); 85 } 86 in_use_id_ = lid; 87 data_.parse(lid); 88 name_ = "C"; 89 utf_mode_ = utf8_none; 90 91 #if defined(BOOST_WINDOWS) 92 std::pair<std::string,int> wl_inf = to_windows_name(lid); 93 std::string win_name = wl_inf.first; 94 int win_codepage = wl_inf.second; 95 #endif 96 97 if(!data_.utf8) { 98 if(loadable(lid)) { 99 name_ = lid; 100 utf_mode_ = utf8_none; 101 } 102 #if defined(BOOST_WINDOWS) 103 else if(loadable(win_name) 104 && win_codepage == conv::impl::encoding_to_windows_codepage(data_.encoding.c_str())) 105 { 106 name_ = win_name; 107 utf_mode_ = utf8_none; 108 } 109 #endif 110 } 111 else { 112 if(loadable(lid)) { 113 name_ = lid; 114 utf_mode_ = utf8_native_with_wide; 115 } 116 #if defined(BOOST_WINDOWS) 117 else if(loadable(win_name)) { 118 name_ = win_name; 119 utf_mode_ = utf8_from_wide; 120 } 121 #endif 122 } 123 } 124 125 #if defined(BOOST_WINDOWS) to_windows_name(std::string const & l)126 std::pair<std::string,int> to_windows_name(std::string const &l) 127 { 128 std::pair<std::string,int> res("C",0); 129 unsigned lcid = impl_win::locale_to_lcid(l); 130 char win_lang[256] = {0}; 131 char win_country[256] = {0}; 132 char win_codepage[10] = {0}; 133 if(GetLocaleInfoA(lcid,LOCALE_SENGLANGUAGE,win_lang,sizeof(win_lang))==0) 134 return res; 135 std::string lc_name = win_lang; 136 if(GetLocaleInfoA(lcid,LOCALE_SENGCOUNTRY,win_country,sizeof(win_country))!=0) { 137 lc_name += "_"; 138 lc_name += win_country; 139 } 140 141 res.first = lc_name; 142 143 if(GetLocaleInfoA(lcid,LOCALE_IDEFAULTANSICODEPAGE,win_codepage,sizeof(win_codepage))!=0) 144 res.second = atoi(win_codepage); 145 return res; 146 } 147 #endif 148 loadable(std::string name)149 bool loadable(std::string name) 150 { 151 try { 152 std::locale l(name.c_str()); 153 return true; 154 } 155 catch(std::exception const &/*e*/) { 156 return false; 157 } 158 } 159 install(std::locale const & base,locale_category_type category,character_facet_type type=nochar_facet)160 virtual std::locale install(std::locale const &base, 161 locale_category_type category, 162 character_facet_type type = nochar_facet) 163 { 164 prepare_data(); 165 166 switch(category) { 167 case convert_facet: 168 return create_convert(base,name_,type,utf_mode_); 169 case collation_facet: 170 return create_collate(base,name_,type,utf_mode_); 171 case formatting_facet: 172 return create_formatting(base,name_,type,utf_mode_); 173 case parsing_facet: 174 return create_parsing(base,name_,type,utf_mode_); 175 case codepage_facet: 176 return create_codecvt(base,name_,type,utf_mode_); 177 case calendar_facet: 178 return util::install_gregorian_calendar(base,data_.country); 179 case message_facet: 180 { 181 gnu_gettext::messages_info minf; 182 minf.language = data_.language; 183 minf.country = data_.country; 184 minf.variant = data_.variant; 185 minf.encoding = data_.encoding; 186 std::copy(domains_.begin(),domains_.end(),std::back_inserter<gnu_gettext::messages_info::domains_type>(minf.domains)); 187 minf.paths = paths_; 188 switch(type) { 189 case char_facet: 190 return std::locale(base,gnu_gettext::create_messages_facet<char>(minf)); 191 case wchar_t_facet: 192 return std::locale(base,gnu_gettext::create_messages_facet<wchar_t>(minf)); 193 #ifdef BOOST_LOCALE_ENABLE_CHAR16_T 194 case char16_t_facet: 195 return std::locale(base,gnu_gettext::create_messages_facet<char16_t>(minf)); 196 #endif 197 #ifdef BOOST_LOCALE_ENABLE_CHAR32_T 198 case char32_t_facet: 199 return std::locale(base,gnu_gettext::create_messages_facet<char32_t>(minf)); 200 #endif 201 default: 202 return base; 203 } 204 } 205 case information_facet: 206 return util::create_info(base,in_use_id_); 207 default: 208 return base; 209 } 210 } 211 212 private: 213 214 std::vector<std::string> paths_; 215 std::vector<std::string> domains_; 216 std::string locale_id_; 217 218 util::locale_data data_; 219 std::string name_; 220 std::string in_use_id_; 221 utf8_support utf_mode_; 222 bool invalid_; 223 bool use_ansi_encoding_; 224 }; 225 create_localization_backend()226 localization_backend *create_localization_backend() 227 { 228 return new std_localization_backend(); 229 } 230 231 } // impl icu 232 } // locale 233 } // boost 234 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 235