Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

504 lines
18 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //===========================================================================//
  7. #ifndef TIER1_ILOCALIZE_H
  8. #define TIER1_ILOCALIZE_H
  9. #ifdef _WIN32
  10. #pragma once
  11. #endif
  12. #include "appframework/IAppSystem.h"
  13. #include <tier1/KeyValues.h>
  14. // unicode character type
  15. // for more unicode manipulation functions #include <wchar.h>
  16. #if !defined(_WCHAR_T_DEFINED) && !defined(GNUC)
  17. typedef unsigned short wchar_t;
  18. #define _WCHAR_T_DEFINED
  19. #endif
  20. // direct references to localized strings
  21. typedef unsigned long StringIndex_t;
  22. const unsigned long INVALID_LOCALIZE_STRING_INDEX = (StringIndex_t) -1;
  23. //-----------------------------------------------------------------------------
  24. // Purpose: Handles localization of text
  25. // looks up string names and returns the localized unicode text
  26. //-----------------------------------------------------------------------------
  27. abstract_class ILocalize
  28. {
  29. public:
  30. // adds the contents of a file to the localization table
  31. virtual bool AddFile( const char *fileName, const char *pPathID = NULL, bool bIncludeFallbackSearchPaths = false ) = 0;
  32. // Remove all strings from the table
  33. virtual void RemoveAll() = 0;
  34. // Finds the localized text for tokenName
  35. virtual wchar_t *Find(char const *tokenName) = 0;
  36. // finds the index of a token by token name, INVALID_STRING_INDEX if not found
  37. virtual StringIndex_t FindIndex(const char *tokenName) = 0;
  38. // gets the values by the string index
  39. virtual const char *GetNameByIndex(StringIndex_t index) = 0;
  40. virtual wchar_t *GetValueByIndex(StringIndex_t index) = 0;
  41. ///////////////////////////////////////////////////////////////////
  42. // the following functions should only be used by localization editors
  43. // iteration functions
  44. virtual StringIndex_t GetFirstStringIndex() = 0;
  45. // returns the next index, or INVALID_STRING_INDEX if no more strings available
  46. virtual StringIndex_t GetNextStringIndex(StringIndex_t index) = 0;
  47. // adds a single name/unicode string pair to the table
  48. virtual void AddString( const char *tokenName, wchar_t *unicodeString, const char *fileName ) = 0;
  49. // changes the value of a string
  50. virtual void SetValueByIndex(StringIndex_t index, wchar_t *newValue) = 0;
  51. // saves the entire contents of the token tree to the file
  52. virtual bool SaveToFile( const char *fileName ) = 0;
  53. // iterates the filenames
  54. virtual int GetLocalizationFileCount() = 0;
  55. virtual const char *GetLocalizationFileName(int index) = 0;
  56. // returns the name of the file the specified localized string is stored in
  57. virtual const char *GetFileNameByIndex(StringIndex_t index) = 0;
  58. // for development only, reloads localization files
  59. virtual void ReloadLocalizationFiles( ) = 0;
  60. virtual const char *FindAsUTF8( const char *pchTokenName ) = 0;
  61. // need to replace the existing ConstructString with this
  62. virtual void ConstructString(OUT_Z_BYTECAP(unicodeBufferSizeInBytes) wchar_t *unicodeOutput, int unicodeBufferSizeInBytes, const char *tokenName, KeyValues *localizationVariables) = 0;
  63. virtual void ConstructString(OUT_Z_BYTECAP(unicodeBufferSizeInBytes) wchar_t *unicodeOutput, int unicodeBufferSizeInBytes, StringIndex_t unlocalizedTextSymbol, KeyValues *localizationVariables) = 0;
  64. ///////////////////////////////////////////////////////////////////
  65. // static interface
  66. // converts an english string to unicode
  67. // returns the number of wchar_t in resulting string, including null terminator
  68. static int ConvertANSIToUnicode(const char *ansi, OUT_Z_BYTECAP(unicodeBufferSizeInBytes) wchar_t *unicode, int unicodeBufferSizeInBytes);
  69. // converts an unicode string to an english string
  70. // unrepresentable characters are converted to system default
  71. // returns the number of characters in resulting string, including null terminator
  72. static int ConvertUnicodeToANSI(const wchar_t *unicode, OUT_Z_BYTECAP(ansiBufferSize) char *ansi, int ansiBufferSize);
  73. // builds a localized formatted string
  74. // uses the format strings first: %s1, %s2, ... unicode strings (wchar_t *)
  75. template < typename T >
  76. static void ConstructString(OUT_Z_BYTECAP(unicodeBufferSizeInBytes) T *unicodeOuput, int unicodeBufferSizeInBytes, const T *formatString, int numFormatParameters, ...)
  77. {
  78. va_list argList;
  79. va_start( argList, numFormatParameters );
  80. ConstructStringVArgsInternal( unicodeOuput, unicodeBufferSizeInBytes, formatString, numFormatParameters, argList );
  81. va_end( argList );
  82. }
  83. template < typename T >
  84. static void ConstructStringVArgs(OUT_Z_BYTECAP(unicodeBufferSizeInBytes) T *unicodeOuput, int unicodeBufferSizeInBytes, const T *formatString, int numFormatParameters, va_list argList)
  85. {
  86. ConstructStringVArgsInternal( unicodeOuput, unicodeBufferSizeInBytes, formatString, numFormatParameters, argList );
  87. }
  88. template < typename T >
  89. static void ConstructString(OUT_Z_BYTECAP(unicodeBufferSizeInBytes) T *unicodeOutput, int unicodeBufferSizeInBytes, const T *formatString, KeyValues *localizationVariables)
  90. {
  91. ConstructStringKeyValuesInternal( unicodeOutput, unicodeBufferSizeInBytes, formatString, localizationVariables );
  92. }
  93. // Safe version of Construct String that has the compiler infer the buffer size
  94. template <size_t maxLenInChars, typename T >
  95. static void ConstructString_safe( OUT_Z_ARRAY T (&pDest)[maxLenInChars], const T *formatString, int numFormatParameters, ... )
  96. {
  97. va_list argList;
  98. va_start( argList, numFormatParameters );
  99. ConstructStringVArgsInternal( pDest, maxLenInChars * sizeof( *pDest ), formatString, numFormatParameters, argList );
  100. va_end( argList );
  101. }
  102. template <size_t maxLenInChars, typename T >
  103. static void ConstructString_safe( OUT_Z_ARRAY T (&pDest)[maxLenInChars], const T *formatString, KeyValues *localizationVariables )
  104. {
  105. ConstructStringKeyValuesInternal( pDest, maxLenInChars * sizeof( *pDest ), formatString, localizationVariables );
  106. }
  107. // Non-static version to be safe version of the virtual functions that utilize KVP
  108. template <size_t maxLenInChars, typename T >
  109. void ConstructString_safe( OUT_Z_ARRAY T( &pDest )[maxLenInChars], const char *formatString, KeyValues *localizationVariables )
  110. {
  111. ConstructString( pDest, maxLenInChars * sizeof( *pDest ), formatString, localizationVariables );
  112. }
  113. private:
  114. // internal "interface"
  115. static void ConstructStringVArgsInternal(OUT_Z_BYTECAP(unicodeBufferSizeInBytes) char *unicodeOutput, int unicodeBufferSizeInBytes, const char *formatString, int numFormatParameters, va_list argList);
  116. static void ConstructStringVArgsInternal(OUT_Z_BYTECAP(unicodeBufferSizeInBytes) wchar_t *unicodeOutput, int unicodeBufferSizeInBytes, const wchar_t *formatString, int numFormatParameters, va_list argList);
  117. static void ConstructStringKeyValuesInternal(OUT_Z_BYTECAP(unicodeBufferSizeInBytes) char *unicodeOutput, int unicodeBufferSizeInBytes, const char *formatString, KeyValues *localizationVariables);
  118. static void ConstructStringKeyValuesInternal(OUT_Z_BYTECAP(unicodeBufferSizeInBytes) wchar_t *unicodeOutput, int unicodeBufferSizeInBytes, const wchar_t *formatString, KeyValues *localizationVariables);
  119. };
  120. #ifdef GC
  121. typedef char locchar_t;
  122. #define loc_snprintf Q_snprintf
  123. #define loc_sprintf_safe V_sprintf_safe
  124. #define loc_sncat Q_strncat
  125. #define loc_scat_safe V_strcat_safe
  126. #define loc_sncpy Q_strncpy
  127. #define loc_scpy_safe V_strcpy_safe
  128. #define loc_strlen Q_strlen
  129. #define LOCCHAR( x ) x
  130. #else
  131. typedef wchar_t locchar_t;
  132. #define loc_snprintf V_snwprintf
  133. #define loc_sprintf_safe V_swprintf_safe
  134. #define loc_sncat V_wcsncat
  135. #define loc_scat_safe V_wcscat_safe
  136. #define loc_sncpy Q_wcsncpy
  137. #define loc_scpy_safe V_wcscpy_safe
  138. #define loc_strlen Q_wcslen
  139. #define LOCCHAR(x) L ## x
  140. #endif
  141. // --------------------------------------------------------------------------
  142. // Purpose:
  143. // --------------------------------------------------------------------------
  144. template < typename T >
  145. class TypedKeyValuesStringHelper
  146. {
  147. public:
  148. static const T *Read( KeyValues *pKeyValues, const char *pKeyName, const T *pDefaultValue );
  149. static void Write( KeyValues *pKeyValues, const char *pKeyName, const T *pValue );
  150. };
  151. // --------------------------------------------------------------------------
  152. template < >
  153. class TypedKeyValuesStringHelper<char>
  154. {
  155. public:
  156. static const char *Read( KeyValues *pKeyValues, const char *pKeyName, const char *pDefaultValue ) { return pKeyValues->GetString( pKeyName, pDefaultValue ); }
  157. static void Write( KeyValues *pKeyValues, const char *pKeyName, const char *pValue ) { pKeyValues->SetString( pKeyName, pValue ); }
  158. };
  159. // --------------------------------------------------------------------------
  160. template < >
  161. class TypedKeyValuesStringHelper<wchar_t>
  162. {
  163. public:
  164. static const wchar_t *Read( KeyValues *pKeyValues, const char *pKeyName, const wchar_t *pDefaultValue ) { return pKeyValues->GetWString( pKeyName, pDefaultValue ); }
  165. static void Write( KeyValues *pKeyValues, const char *pKeyName, const wchar_t *pValue ) { pKeyValues->SetWString( pKeyName, pValue ); }
  166. };
  167. // --------------------------------------------------------------------------
  168. // Purpose: CLocalizedStringArg<> is a class that will take a variable of any
  169. // arbitary type and convert it to a string of whatever character type
  170. // we're using for localization (locchar_t).
  171. //
  172. // Independently it isn't very useful, though it can be used to sort-of-
  173. // intelligently fill out the correct format string. It's designed to be
  174. // used for the arguments of CConstructLocalizedString, which can be of
  175. // arbitrary number and type.
  176. //
  177. // If you pass in a (non-specialized) pointer, the code will assume that
  178. // you meant that pointer to be used as a localized string. This will
  179. // still fail to compile if some non-string type is passed in, but will
  180. // handle weird combinations of const/volatile/whatever automatically.
  181. // --------------------------------------------------------------------------
  182. // The base implementation doesn't do anything except fail to compile if you
  183. // use it. Getting an "incomplete type" error here means that you tried to construct
  184. // a localized string with a type that doesn't have a specialization.
  185. template < typename T >
  186. class CLocalizedStringArg;
  187. // --------------------------------------------------------------------------
  188. template < typename T >
  189. class CLocalizedStringArgStringImpl
  190. {
  191. public:
  192. enum { kIsValid = true };
  193. CLocalizedStringArgStringImpl( const locchar_t *pStr ) : m_pStr( pStr ) { }
  194. const locchar_t *GetLocArg() const { Assert( m_pStr ); return m_pStr; }
  195. private:
  196. const locchar_t *m_pStr;
  197. };
  198. // --------------------------------------------------------------------------
  199. template < typename T >
  200. class CLocalizedStringArg<T *> : public CLocalizedStringArgStringImpl<T>
  201. {
  202. public:
  203. CLocalizedStringArg( const locchar_t *pStr ) : CLocalizedStringArgStringImpl<T>( pStr ) { }
  204. };
  205. // --------------------------------------------------------------------------
  206. template < typename T >
  207. class CLocalizedStringArgPrintfImpl
  208. {
  209. public:
  210. enum { kIsValid = true };
  211. CLocalizedStringArgPrintfImpl( T value, const locchar_t *loc_Format ) { loc_snprintf( m_cBuffer, kBufferSize, loc_Format, value ); }
  212. const locchar_t *GetLocArg() const { return m_cBuffer; }
  213. private:
  214. enum { kBufferSize = 128, };
  215. locchar_t m_cBuffer[ kBufferSize ];
  216. };
  217. // --------------------------------------------------------------------------
  218. template < >
  219. class CLocalizedStringArg<uint16> : public CLocalizedStringArgPrintfImpl<uint16>
  220. {
  221. public:
  222. CLocalizedStringArg( uint16 unValue ) : CLocalizedStringArgPrintfImpl<uint16>( unValue, LOCCHAR("%u") ) { }
  223. };
  224. // --------------------------------------------------------------------------
  225. template < >
  226. class CLocalizedStringArg<uint32> : public CLocalizedStringArgPrintfImpl<uint32>
  227. {
  228. public:
  229. CLocalizedStringArg( uint32 unValue ) : CLocalizedStringArgPrintfImpl<uint32>( unValue, LOCCHAR("%u") ) { }
  230. };
  231. // --------------------------------------------------------------------------
  232. template < >
  233. class CLocalizedStringArg<uint64> : public CLocalizedStringArgPrintfImpl<uint64>
  234. {
  235. public:
  236. CLocalizedStringArg( uint64 unValue ) : CLocalizedStringArgPrintfImpl<uint64>( unValue, LOCCHAR("%llu") ) { }
  237. };
  238. // --------------------------------------------------------------------------
  239. template < >
  240. class CLocalizedStringArg<float> : public CLocalizedStringArgPrintfImpl<float>
  241. {
  242. public:
  243. // Display one decimal point if we've got a value less than one, and no point
  244. // if we're greater than one or are effectively zero.
  245. CLocalizedStringArg( float fValue )
  246. : CLocalizedStringArgPrintfImpl<float>( fValue,
  247. fabsf( fValue ) <= FLT_EPSILON || fabsf( fValue ) >= 1.0f ? LOCCHAR("%.0f") : LOCCHAR("%.1f") )
  248. {
  249. //
  250. }
  251. };
  252. // --------------------------------------------------------------------------
  253. // Purpose:
  254. // --------------------------------------------------------------------------
  255. class CConstructLocalizedString
  256. {
  257. public:
  258. template < typename T >
  259. CConstructLocalizedString( const locchar_t *loc_Format, T arg0 )
  260. {
  261. COMPILE_TIME_ASSERT( CLocalizedStringArg<T>::kIsValid );
  262. m_loc_Buffer[0] = '\0';
  263. if ( loc_Format )
  264. {
  265. ::ILocalize::ConstructString( m_loc_Buffer, sizeof( m_loc_Buffer ), loc_Format, 1, CLocalizedStringArg<T>( arg0 ).GetLocArg() );
  266. }
  267. }
  268. template < typename T, typename U >
  269. CConstructLocalizedString( const locchar_t *loc_Format, T arg0, U arg1 )
  270. {
  271. COMPILE_TIME_ASSERT( CLocalizedStringArg<T>::kIsValid );
  272. COMPILE_TIME_ASSERT( CLocalizedStringArg<U>::kIsValid );
  273. m_loc_Buffer[0] = '\0';
  274. if ( loc_Format )
  275. {
  276. ::ILocalize::ConstructString( m_loc_Buffer, sizeof( m_loc_Buffer ), loc_Format, 2, CLocalizedStringArg<T>( arg0 ).GetLocArg(), CLocalizedStringArg<U>( arg1 ).GetLocArg() );
  277. }
  278. }
  279. template < typename T, typename U, typename V >
  280. CConstructLocalizedString( const locchar_t *loc_Format, T arg0, U arg1, V arg2 )
  281. {
  282. COMPILE_TIME_ASSERT( CLocalizedStringArg<T>::kIsValid );
  283. COMPILE_TIME_ASSERT( CLocalizedStringArg<U>::kIsValid );
  284. COMPILE_TIME_ASSERT( CLocalizedStringArg<V>::kIsValid );
  285. m_loc_Buffer[0] = '\0';
  286. if ( loc_Format )
  287. {
  288. ::ILocalize::ConstructString( m_loc_Buffer,
  289. sizeof( m_loc_Buffer ),
  290. loc_Format,
  291. 3,
  292. CLocalizedStringArg<T>( arg0 ).GetLocArg(),
  293. CLocalizedStringArg<U>( arg1 ).GetLocArg(),
  294. CLocalizedStringArg<V>( arg2 ).GetLocArg() );
  295. }
  296. }
  297. template < typename T, typename U, typename V, typename W >
  298. CConstructLocalizedString( const locchar_t *loc_Format, T arg0, U arg1, V arg2, W arg3 )
  299. {
  300. COMPILE_TIME_ASSERT( CLocalizedStringArg<T>::kIsValid );
  301. COMPILE_TIME_ASSERT( CLocalizedStringArg<U>::kIsValid );
  302. COMPILE_TIME_ASSERT( CLocalizedStringArg<V>::kIsValid );
  303. COMPILE_TIME_ASSERT( CLocalizedStringArg<W>::kIsValid );
  304. m_loc_Buffer[0] = '\0';
  305. if ( loc_Format )
  306. {
  307. ::ILocalize::ConstructString( m_loc_Buffer,
  308. sizeof( m_loc_Buffer ),
  309. loc_Format,
  310. 4,
  311. CLocalizedStringArg<T>( arg0 ).GetLocArg(),
  312. CLocalizedStringArg<U>( arg1 ).GetLocArg(),
  313. CLocalizedStringArg<V>( arg2 ).GetLocArg(),
  314. CLocalizedStringArg<W>( arg3 ).GetLocArg() );
  315. }
  316. }
  317. template < typename T, typename U, typename V, typename W, typename X >
  318. CConstructLocalizedString( const locchar_t *loc_Format, T arg0, U arg1, V arg2, W arg3, X arg4 )
  319. {
  320. COMPILE_TIME_ASSERT( CLocalizedStringArg<T>::kIsValid );
  321. COMPILE_TIME_ASSERT( CLocalizedStringArg<U>::kIsValid );
  322. COMPILE_TIME_ASSERT( CLocalizedStringArg<V>::kIsValid );
  323. COMPILE_TIME_ASSERT( CLocalizedStringArg<W>::kIsValid );
  324. COMPILE_TIME_ASSERT( CLocalizedStringArg<X>::kIsValid );
  325. m_loc_Buffer[0] = '\0';
  326. if ( loc_Format )
  327. {
  328. ::ILocalize::ConstructString( m_loc_Buffer,
  329. sizeof( m_loc_Buffer ),
  330. loc_Format,
  331. 5,
  332. CLocalizedStringArg<T>( arg0 ).GetLocArg(),
  333. CLocalizedStringArg<U>( arg1 ).GetLocArg(),
  334. CLocalizedStringArg<V>( arg2 ).GetLocArg(),
  335. CLocalizedStringArg<W>( arg3 ).GetLocArg(),
  336. CLocalizedStringArg<X>( arg4 ).GetLocArg() );
  337. }
  338. }
  339. template < typename T, typename U, typename V, typename W, typename X, typename Y >
  340. CConstructLocalizedString( const locchar_t *loc_Format, T arg0, U arg1, V arg2, W arg3, X arg4, Y arg5 )
  341. {
  342. COMPILE_TIME_ASSERT( CLocalizedStringArg<T>::kIsValid );
  343. COMPILE_TIME_ASSERT( CLocalizedStringArg<U>::kIsValid );
  344. COMPILE_TIME_ASSERT( CLocalizedStringArg<V>::kIsValid );
  345. COMPILE_TIME_ASSERT( CLocalizedStringArg<W>::kIsValid );
  346. COMPILE_TIME_ASSERT( CLocalizedStringArg<X>::kIsValid );
  347. COMPILE_TIME_ASSERT( CLocalizedStringArg<Y>::kIsValid );
  348. m_loc_Buffer[0] = '\0';
  349. if ( loc_Format )
  350. {
  351. ::ILocalize::ConstructString( m_loc_Buffer,
  352. sizeof( m_loc_Buffer ),
  353. loc_Format,
  354. 6,
  355. CLocalizedStringArg<T>( arg0 ).GetLocArg(),
  356. CLocalizedStringArg<U>( arg1 ).GetLocArg(),
  357. CLocalizedStringArg<V>( arg2 ).GetLocArg(),
  358. CLocalizedStringArg<W>( arg3 ).GetLocArg(),
  359. CLocalizedStringArg<X>( arg4 ).GetLocArg(),
  360. CLocalizedStringArg<Y>( arg5 ).GetLocArg() );
  361. }
  362. }
  363. template < typename T, typename U, typename V, typename W, typename X, typename Y, typename Z >
  364. CConstructLocalizedString( const locchar_t *loc_Format, T arg0, U arg1, V arg2, W arg3, X arg4, Y arg5, Z arg6)
  365. {
  366. COMPILE_TIME_ASSERT( CLocalizedStringArg<T>::kIsValid );
  367. COMPILE_TIME_ASSERT( CLocalizedStringArg<U>::kIsValid );
  368. COMPILE_TIME_ASSERT( CLocalizedStringArg<V>::kIsValid );
  369. COMPILE_TIME_ASSERT( CLocalizedStringArg<W>::kIsValid );
  370. COMPILE_TIME_ASSERT( CLocalizedStringArg<X>::kIsValid );
  371. COMPILE_TIME_ASSERT( CLocalizedStringArg<Y>::kIsValid );
  372. COMPILE_TIME_ASSERT( CLocalizedStringArg<Z>::kIsValid );
  373. m_loc_Buffer[0] = '\0';
  374. if ( loc_Format )
  375. {
  376. ::ILocalize::ConstructString( m_loc_Buffer,
  377. sizeof( m_loc_Buffer ),
  378. loc_Format,
  379. 7,
  380. CLocalizedStringArg<T>( arg0 ).GetLocArg(),
  381. CLocalizedStringArg<U>( arg1 ).GetLocArg(),
  382. CLocalizedStringArg<V>( arg2 ).GetLocArg(),
  383. CLocalizedStringArg<W>( arg3 ).GetLocArg(),
  384. CLocalizedStringArg<X>( arg4 ).GetLocArg(),
  385. CLocalizedStringArg<Y>( arg5 ).GetLocArg(),
  386. CLocalizedStringArg<Z>( arg6 ).GetLocArg() );
  387. }
  388. }
  389. CConstructLocalizedString( const locchar_t *loc_Format, KeyValues *pKeyValues )
  390. {
  391. m_loc_Buffer[0] = '\0';
  392. if ( loc_Format && pKeyValues )
  393. {
  394. ::ILocalize::ConstructString( m_loc_Buffer, sizeof( m_loc_Buffer ), loc_Format, pKeyValues );
  395. }
  396. }
  397. operator const locchar_t *() const
  398. {
  399. return m_loc_Buffer;
  400. }
  401. private:
  402. enum { kBufferSize = 512, };
  403. locchar_t m_loc_Buffer[ kBufferSize ];
  404. };
  405. #endif // TIER1_ILOCALIZE_H