• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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