llresmgr.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:9k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llresmgr.cpp
  3.  * @brief Localized resource manager
  4.  *
  5.  * $LicenseInfo:firstyear=2001&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2001-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. // NOTE: this is a MINIMAL implementation.  The interface will remain, but the implementation will
  33. // (when the time is right) become dynamic and probably use external files.
  34. #include "linden_common.h"
  35. #include "llresmgr.h"
  36. #include "llfontgl.h"
  37. #include "llerror.h"
  38. #include "llstring.h"
  39. LLResMgr::LLResMgr()
  40. {
  41. // Set default
  42. setLocale( LLLOCALE_USA );
  43. }
  44. void LLResMgr::setLocale( LLLOCALE_ID locale_id )
  45. {
  46. mLocale = locale_id;
  47. //RN: for now, use normal 'C' locale for everything but specific UI input/output routines
  48. // switch( locale_id )
  49. // {
  50. // case LLLOCALE_USA: 
  51. //#if LL_WINDOWS
  52. // // Windows doesn't use ISO country codes.
  53. // llinfos << "Setting locale to " << setlocale( LC_ALL, "english-usa" ) << llendl;
  54. //#else
  55. // // posix version should work everywhere else.
  56. // llinfos << "Setting locale to " << setlocale( LC_ALL, "en_US" ) << llendl;
  57. //#endif
  58. // break;
  59. // case LLLOCALE_UK:
  60. //#if LL_WINDOWS
  61. // // Windows doesn't use ISO country codes.
  62. // llinfos << "Setting locale to " << setlocale( LC_ALL, "english-uk" ) << llendl;
  63. //#else
  64. // // posix version should work everywhere else.
  65. // llinfos << "Setting locale to " << setlocale( LC_ALL, "en_GB" ) << llendl;
  66. //#endif
  67. // break;
  68. // default:
  69. // llassert(0);
  70. // setLocale(LLLOCALE_USA);
  71. // break;
  72. // }
  73. }
  74. char LLResMgr::getDecimalPoint() const
  75. char decimal = localeconv()->decimal_point[0]; 
  76. #if LL_DARWIN
  77. // On the Mac, locale support is broken before 10.4, which causes things to go all pear-shaped.
  78. if(decimal == 0)
  79. {
  80. decimal = '.';
  81. }
  82. #endif
  83. return decimal;
  84. }
  85. char LLResMgr::getThousandsSeparator() const
  86. {
  87. char separator = localeconv()->thousands_sep[0]; 
  88. #if LL_DARWIN
  89. // On the Mac, locale support is broken before 10.4, which causes things to go all pear-shaped.
  90. if(separator == 0)
  91. {
  92. separator = ',';
  93. }
  94. #endif
  95. return separator;
  96. }
  97. char LLResMgr::getMonetaryDecimalPoint() const
  98. {
  99. char decimal = localeconv()->mon_decimal_point[0]; 
  100. #if LL_DARWIN
  101. // On the Mac, locale support is broken before 10.4, which causes things to go all pear-shaped.
  102. if(decimal == 0)
  103. {
  104. decimal = '.';
  105. }
  106. #endif
  107. return decimal;
  108. }
  109. char LLResMgr::getMonetaryThousandsSeparator() const
  110. {
  111. char separator = localeconv()->mon_thousands_sep[0]; 
  112. #if LL_DARWIN
  113. // On the Mac, locale support is broken before 10.4, which causes things to go all pear-shaped.
  114. if(separator == 0)
  115. {
  116. separator = ',';
  117. }
  118. #endif
  119. return separator;
  120. }
  121. // Sets output to a string of integers with monetary separators inserted according to the locale.
  122. std::string LLResMgr::getMonetaryString( S32 input ) const
  123. {
  124. std::string output;
  125. LLLocale locale(LLLocale::USER_LOCALE);
  126. struct lconv *conv = localeconv();
  127. #if LL_DARWIN
  128. // On the Mac, locale support is broken before 10.4, which causes things to go all pear-shaped.
  129. // Fake up a conv structure with some reasonable values for the fields this function uses.
  130. struct lconv fakeconv;
  131. char fake_neg[2] = "-";
  132. char fake_mon_group[4] = "x03x03x00"; // commas every 3 digits
  133. if(conv->negative_sign[0] == 0) // Real locales all seem to have something here...
  134. {
  135. fakeconv = *conv; // start with what's there.
  136. switch(mLocale)
  137. {
  138. default:   // Unknown -- use the US defaults.
  139. case LLLOCALE_USA: 
  140. case LLLOCALE_UK: // UK ends up being the same as US for the items used here.
  141. fakeconv.negative_sign = fake_neg;
  142. fakeconv.mon_grouping = fake_mon_group;
  143. fakeconv.n_sign_posn = 1; // negative sign before the string
  144. break;
  145. }
  146. conv = &fakeconv;
  147. }
  148. #endif
  149. char* negative_sign = conv->negative_sign;
  150. char separator = getMonetaryThousandsSeparator();
  151. char* grouping = conv->mon_grouping;
  152. // Note on mon_grouping:
  153. // Specifies a string that defines the size of each group of digits in formatted monetary quantities.
  154. // The operand for the mon_grouping keyword consists of a sequence of semicolon-separated integers. 
  155. // Each integer specifies the number of digits in a group. The initial integer defines the size of
  156. // the group immediately to the left of the decimal delimiter. The following integers define succeeding
  157. // groups to the left of the previous group. If the last integer is not -1, the size of the previous
  158. // group (if any) is repeatedly used for the remainder of the digits. If the last integer is -1, no
  159. // further grouping is performed. 
  160. // Note: we assume here that the currency symbol goes on the left. (Hey, it's Lindens! We can just decide.)
  161. BOOL negative = (input < 0 );
  162. BOOL negative_before = negative && (conv->n_sign_posn != 2);
  163. BOOL negative_after = negative && (conv->n_sign_posn == 2);
  164. std::string digits = llformat("%u", abs(input));
  165. if( !grouping || !grouping[0] )
  166. {
  167. if( negative_before )
  168. {
  169. output.append( negative_sign );
  170. }
  171. output.append( digits );
  172. if( negative_after )
  173. {
  174. output.append( negative_sign );
  175. }
  176. return output;
  177. }
  178. S32 groupings[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  179. S32 cur_group;
  180. for( cur_group = 0; grouping[ cur_group ]; cur_group++ )
  181. {
  182. if( grouping[ cur_group ] != ';' )
  183. {
  184. groupings[cur_group] = grouping[ cur_group ];
  185. }
  186. cur_group++;
  187. if( groupings[cur_group] < 0 )
  188. {
  189. break;
  190. }
  191. }
  192. S32 group_count = cur_group;
  193. char reversed_output[20] = ""; /* Flawfinder: ignore */
  194. char forward_output[20] = ""; /* Flawfinder: ignore */
  195. S32 output_pos = 0;
  196. cur_group = 0;
  197. S32 pos = digits.size()-1;
  198. S32 count_within_group = 0;
  199. while( (pos >= 0) && (groupings[cur_group] >= 0) )
  200. {
  201. count_within_group++;
  202. if( count_within_group > groupings[cur_group] )
  203. {
  204. count_within_group = 1;
  205. reversed_output[ output_pos++ ] = separator;
  206. if( (cur_group + 1) >= group_count )
  207. {
  208. break;
  209. }
  210. else
  211. if( groupings[cur_group + 1] > 0 )
  212. {
  213. cur_group++;
  214. }
  215. }
  216. reversed_output[ output_pos++ ] = digits[pos--];
  217. }
  218. while( pos >= 0 )
  219. {
  220. reversed_output[ output_pos++ ] = digits[pos--];
  221. }
  222. reversed_output[ output_pos ] = '';
  223. forward_output[ output_pos ] = '';
  224. for( S32 i = 0; i < output_pos; i++ )
  225. {
  226. forward_output[ output_pos - 1 - i ] = reversed_output[ i ];
  227. }
  228. if( negative_before )
  229. {
  230. output.append( negative_sign );
  231. }
  232. output.append( forward_output );
  233. if( negative_after )
  234. {
  235. output.append( negative_sign );
  236. }
  237. return output;
  238. }
  239. void LLResMgr::getIntegerString( std::string& output, S32 input ) const
  240. {
  241. // handle special case of input value being zero
  242. if (input == 0)
  243. {
  244. output = "0";
  245. return;
  246. }
  247. // *NOTE: this method does not handle negative input integers correctly
  248. S32 fraction = 0;
  249. std::string fraction_string;
  250. S32 remaining_count = input;
  251. while(remaining_count > 0)
  252. {
  253. fraction = (remaining_count) % 1000;
  254. if (!output.empty())
  255. {
  256. if (fraction == remaining_count)
  257. {
  258. fraction_string = llformat("%d%c", fraction, getThousandsSeparator());
  259. }
  260. else
  261. {
  262. fraction_string = llformat("%3.3d%c", fraction, getThousandsSeparator());
  263. }
  264. output = fraction_string + output;
  265. }
  266. else
  267. {
  268. if (fraction == remaining_count)
  269. {
  270. fraction_string = llformat("%d", fraction);
  271. }
  272. else
  273. {
  274. fraction_string = llformat("%3.3d", fraction);
  275. }
  276. output = fraction_string;
  277. }
  278. remaining_count /= 1000;
  279. }
  280. }
  281. #if LL_WINDOWS
  282. const std::string LLLocale::USER_LOCALE("English_United States.1252");// = LLStringUtil::null;
  283. const std::string LLLocale::SYSTEM_LOCALE("English_United States.1252");
  284. #elif LL_DARWIN
  285. const std::string LLLocale::USER_LOCALE("en_US.iso8859-1");// = LLStringUtil::null;
  286. const std::string LLLocale::SYSTEM_LOCALE("en_US.iso8859-1");
  287. #elif LL_SOLARIS
  288. const std::string LLLocale::USER_LOCALE("en_US.ISO8859-1");
  289. const std::string LLLocale::SYSTEM_LOCALE("C");
  290. #else // LL_LINUX likes this
  291. const std::string LLLocale::USER_LOCALE("en_US.utf8");
  292. const std::string LLLocale::SYSTEM_LOCALE("C");
  293. #endif
  294. LLLocale::LLLocale(const std::string& locale_string)
  295. {
  296. mPrevLocaleString = setlocale( LC_ALL, NULL );
  297. char* new_locale_string = setlocale( LC_ALL, locale_string.c_str());
  298. if ( new_locale_string == NULL)
  299. {
  300. llwarns << "Failed to set locale " << locale_string << llendl;
  301. setlocale(LC_ALL, SYSTEM_LOCALE.c_str());
  302. }
  303. //else
  304. //{
  305. // llinfos << "Set locale to " << new_locale_string << llendl;
  306. //}
  307. }
  308. LLLocale::~LLLocale() 
  309. {
  310. setlocale( LC_ALL, mPrevLocaleString.c_str() );
  311. }