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 "lcid.hpp"
10 #include <string.h>
11 #include <string>
12 #include <sstream>
13 #include <map>
14 
15 #include "../util/locale_data.hpp"
16 
17 #ifndef NOMINMAX
18 #define NOMINMAX
19 #endif
20 #include <windows.h>
21 
22 #include <boost/thread/mutex.hpp>
23 
24 namespace boost {
25 namespace locale {
26 namespace impl_win {
27 
28 typedef std::map<std::string,unsigned> table_type;
29 
30 static table_type * volatile table = 0;
31 
lcid_table_mutex()32 boost::mutex &lcid_table_mutex()
33 {
34     static boost::mutex m;
35     return m;
36 }
37 
real_lcid_table()38 table_type &real_lcid_table()
39 {
40     static table_type table;
41     return table;
42 }
43 
proc(char * s)44 BOOL CALLBACK proc(char *s)
45 {
46     table_type &tbl = real_lcid_table();
47     try {
48         std::istringstream ss;
49         ss.str(s);
50         ss >> std::hex;
51 
52         unsigned lcid ;
53         ss >>lcid;
54         if(ss.fail() || !ss.eof()) {
55             return FALSE;
56         }
57 
58         char iso_639_lang[16];
59         char iso_3166_country[16];
60         if(GetLocaleInfoA(lcid,LOCALE_SISO639LANGNAME,iso_639_lang,sizeof(iso_639_lang))==0)
61             return FALSE;
62         std::string lc_name = iso_639_lang;
63         if(GetLocaleInfoA(lcid,LOCALE_SISO3166CTRYNAME,iso_3166_country,sizeof(iso_3166_country))!=0) {
64             lc_name += "_";
65             lc_name += iso_3166_country;
66         }
67         table_type::iterator p = tbl.find(lc_name);
68         if(p!=tbl.end()) {
69             if(p->second > lcid)
70                 p->second = lcid;
71         }
72         else {
73             tbl[lc_name]=lcid;
74         }
75     }
76     catch(...) {
77         tbl.clear();
78         return FALSE;
79     }
80     return TRUE;
81 }
82 
83 
get_ready_lcid_table()84 table_type  const &get_ready_lcid_table()
85 {
86     if(table)
87         return *table;
88     else {
89         boost::unique_lock<boost::mutex> lock(lcid_table_mutex());
90         if(table)
91             return *table;
92         EnumSystemLocalesA(proc,LCID_INSTALLED);
93         table = &real_lcid_table();
94         return *table;
95     }
96 }
97 
locale_to_lcid(std::string const & locale_name)98 unsigned locale_to_lcid(std::string const &locale_name)
99 {
100     if(locale_name.empty()) {
101         return LOCALE_USER_DEFAULT;
102     }
103     boost::locale::util::locale_data d;
104     d.parse(locale_name);
105     std::string id = d.language;
106 
107     if(!d.country.empty()) {
108         id+="_"+d.country;
109     }
110     if(!d.variant.empty()) {
111         id+="@" + d.variant;
112     }
113 
114     table_type const &tbl = get_ready_lcid_table();
115     table_type::const_iterator p = tbl.find(id);
116 
117     unsigned lcid = 0;
118     if(p!=tbl.end())
119         lcid = p->second;
120     return lcid;
121 }
122 
123 
124 } // impl_win
125 } // locale
126 } // boost
127 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
128