// // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_LOCALE_IMPL_WIN32_API_HPP #define BOOST_LOCALE_IMPL_WIN32_API_HPP #include #include #include #include #include #include #include "lcid.hpp" #ifndef NOMINMAX #define NOMINMAX #endif #ifndef UNICODE #define UNICODE #endif #include #include #include #define BOOST_LOCALE_WINDOWS_2000_API #if defined(_WIN32_NT) && _WIN32_NT >= 0x600 && !defined(BOOST_LOCALE_WINDOWS_2000_API) #define BOOST_LOCALE_WINDOWS_VISTA_API #else #define BOOST_LOCALE_WINDOWS_2000_API #endif namespace boost { namespace locale { namespace impl_win { struct numeric_info { std::wstring thousands_sep; std::wstring decimal_point; std::string grouping; }; inline DWORD collation_level_to_flag(collator_base::level_type level) { DWORD flags; switch(level) { case collator_base::primary: flags = NORM_IGNORESYMBOLS | NORM_IGNORECASE | NORM_IGNORENONSPACE; break; case collator_base::secondary: flags = NORM_IGNORESYMBOLS | NORM_IGNORECASE; break; case collator_base::tertiary: flags = NORM_IGNORESYMBOLS; break; default: flags = 0; } return flags; } #ifdef BOOST_LOCALE_WINDOWS_2000_API class winlocale{ public: winlocale() : lcid(0) { } winlocale(std::string const &name) { lcid = locale_to_lcid(name); } unsigned lcid; bool is_c() const { return lcid == 0; } }; //////////////////////////////////////////////////////////////////////// /// /// Number Format /// //////////////////////////////////////////////////////////////////////// inline numeric_info wcsnumformat_l(winlocale const &l) { numeric_info res; res.decimal_point = L'.'; unsigned lcid = l.lcid; if(lcid == 0) return res; // limits according to MSDN static const int th_size = 4; static const int de_size = 4; static const int gr_size = 10; wchar_t th[th_size]={0}; wchar_t de[de_size]={0}; wchar_t gr[gr_size]={0}; if( GetLocaleInfoW(lcid,LOCALE_STHOUSAND,th,th_size)==0 || GetLocaleInfoW(lcid,LOCALE_SDECIMAL ,de,de_size)==0 || GetLocaleInfoW(lcid,LOCALE_SGROUPING,gr,gr_size)==0) { return res; } res.decimal_point = de; res.thousands_sep = th; bool inf_group = false; for(unsigned i=0;gr[i];i++) { if(gr[i]==L';') continue; if(L'1'<= gr[i] && gr[i]<=L'9') { res.grouping += char(gr[i]-L'0'); } else if(gr[i]==L'0') inf_group = true; } if(!inf_group) { if(std::numeric_limits::is_signed) { res.grouping+=std::numeric_limits::min(); } else { res.grouping+=std::numeric_limits::max(); } } return res; } inline std::wstring win_map_string_l(unsigned flags,wchar_t const *begin,wchar_t const *end,winlocale const &l) { std::wstring res; int len = LCMapStringW(l.lcid,flags,begin,end-begin,0,0); if(len == 0) return res; std::vector buf(len+1); int l2 = LCMapStringW(l.lcid,flags,begin,end-begin,&buf.front(),buf.size()); res.assign(&buf.front(),l2); return res; } //////////////////////////////////////////////////////////////////////// /// /// Collation /// //////////////////////////////////////////////////////////////////////// inline int wcscoll_l( collator_base::level_type level, wchar_t const *lb,wchar_t const *le, wchar_t const *rb,wchar_t const *re, winlocale const &l) { return CompareStringW(l.lcid,collation_level_to_flag(level),lb,le-lb,rb,re-rb) - 2; } //////////////////////////////////////////////////////////////////////// /// /// Money Format /// //////////////////////////////////////////////////////////////////////// inline std::wstring wcsfmon_l(double value,winlocale const &l) { std::wostringstream ss; ss.imbue(std::locale::classic()); ss << std::setprecision(std::numeric_limits::digits10+1) << value; std::wstring sval = ss.str(); int len = GetCurrencyFormatW(l.lcid,0,sval.c_str(),0,0,0); std::vector buf(len+1); GetCurrencyFormatW(l.lcid,0,sval.c_str(),0,&buf.front(),len); return &buf.front(); } //////////////////////////////////////////////////////////////////////// /// /// Time Format /// //////////////////////////////////////////////////////////////////////// inline std::wstring wcs_format_date_l(wchar_t const *format,SYSTEMTIME const *tm,winlocale const &l) { int len = GetDateFormatW(l.lcid,0,tm,format,0,0); std::vector buf(len+1); GetDateFormatW(l.lcid,0,tm,format,&buf.front(),len); return &buf.front(); } inline std::wstring wcs_format_time_l(wchar_t const *format,SYSTEMTIME const *tm,winlocale const &l) { int len = GetTimeFormatW(l.lcid,0,tm,format,0,0); std::vector buf(len+1); GetTimeFormatW(l.lcid,0,tm,format,&buf.front(),len); return &buf.front(); } inline std::wstring wcsfold(wchar_t const *begin,wchar_t const *end) { winlocale l; l.lcid = 0x0409; // en-US return win_map_string_l(LCMAP_LOWERCASE,begin,end,l); } inline std::wstring wcsnormalize(norm_type norm,wchar_t const *begin,wchar_t const *end) { // We use FoldString, under Vista it actually does normalization; // under XP and below it does something similar, half job, better then nothing unsigned flags = 0; switch(norm) { case norm_nfd: flags = MAP_COMPOSITE; break; case norm_nfc: flags = MAP_PRECOMPOSED; break; case norm_nfkd: flags = MAP_FOLDCZONE; break; case norm_nfkc: flags = MAP_FOLDCZONE | MAP_COMPOSITE; break; default: flags = MAP_PRECOMPOSED; } int len = FoldStringW(flags,begin,end-begin,0,0); if(len == 0) return std::wstring(); std::vector v(len+1); len = FoldStringW(flags,begin,end-begin,&v.front(),len+1); return std::wstring(&v.front(),len); } #endif inline std::wstring wcsxfrm_l(collator_base::level_type level,wchar_t const *begin,wchar_t const *end,winlocale const &l) { int flag = LCMAP_SORTKEY | collation_level_to_flag(level); return win_map_string_l(flag,begin,end,l); } inline std::wstring towupper_l(wchar_t const *begin,wchar_t const *end,winlocale const &l) { return win_map_string_l(LCMAP_UPPERCASE | LCMAP_LINGUISTIC_CASING,begin,end,l); } inline std::wstring towlower_l(wchar_t const *begin,wchar_t const *end,winlocale const &l) { return win_map_string_l(LCMAP_LOWERCASE | LCMAP_LINGUISTIC_CASING,begin,end,l); } inline std::wstring wcsftime_l(char c,std::tm const *tm,winlocale const &l) { SYSTEMTIME wtm=SYSTEMTIME(); wtm.wYear = tm->tm_year + 1900; wtm.wMonth = tm->tm_mon+1; wtm.wDayOfWeek = tm->tm_wday; wtm.wDay = tm->tm_mday; wtm.wHour = tm->tm_hour; wtm.wMinute = tm->tm_min; wtm.wSecond = tm->tm_sec; switch(c) { case 'a': // Abbr Weekday return wcs_format_date_l(L"ddd",&wtm,l); case 'A': // Full Weekday return wcs_format_date_l(L"dddd",&wtm,l); case 'b': // Abbr Month return wcs_format_date_l(L"MMM",&wtm,l); case 'B': // Full Month return wcs_format_date_l(L"MMMM",&wtm,l); case 'c': // DateTile Full return wcs_format_date_l(0,&wtm,l) + L" " + wcs_format_time_l(0,&wtm,l); // not supported by WIN ;( // case 'C': // Century -> 1980 -> 19 // retur case 'd': // Day of Month [01,31] return wcs_format_date_l(L"dd",&wtm,l); case 'D': // %m/%d/%y return wcs_format_date_l(L"MM/dd/yy",&wtm,l); case 'e': // Day of Month [1,31] return wcs_format_date_l(L"d",&wtm,l); case 'h': // == b return wcs_format_date_l(L"MMM",&wtm,l); case 'H': // 24 clock hour 00,23 return wcs_format_time_l(L"HH",&wtm,l); case 'I': // 12 clock hour 01,12 return wcs_format_time_l(L"hh",&wtm,l); /* case 'j': // day of year 001,366 return "D";*/ case 'm': // month as [01,12] return wcs_format_date_l(L"MM",&wtm,l); case 'M': // minute [00,59] return wcs_format_time_l(L"mm",&wtm,l); case 'n': // \n return L"\n"; case 'p': // am-pm return wcs_format_time_l(L"tt",&wtm,l); case 'r': // time with AM/PM %I:%M:%S %p return wcs_format_time_l(L"hh:mm:ss tt",&wtm,l); case 'R': // %H:%M return wcs_format_time_l(L"HH:mm",&wtm,l); case 'S': // second [00,61] return wcs_format_time_l(L"ss",&wtm,l); case 't': // \t return L"\t"; case 'T': // %H:%M:%S return wcs_format_time_l(L"HH:mm:ss",&wtm,l); /* case 'u': // weekday 1,7 1=Monday case 'U': // week number of year [00,53] Sunday first case 'V': // week number of year [01,53] Moday first case 'w': // weekday 0,7 0=Sunday case 'W': // week number of year [00,53] Moday first, */ case 'x': // Date return wcs_format_date_l(0,&wtm,l); case 'X': // Time return wcs_format_time_l(0,&wtm,l); case 'y': // Year [00-99] return wcs_format_date_l(L"yy",&wtm,l); case 'Y': // Year 1998 return wcs_format_date_l(L"yyyy",&wtm,l); case '%': // % return L"%"; default: return L""; } } } // win } // locale } // boost #endif // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4