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.

198 lines
5.8 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. #include "cbase.h"
  3. #include "localization_provider.h"
  4. enum { kScratchBufferSize = 1024 };
  5. // ----------------------------------------------------------------------------
  6. // Find a localized string, but return something safe if the key is null or the localized
  7. // string is missing.
  8. // ----------------------------------------------------------------------------
  9. locchar_t* CLocalizationProvider::FindSafe( const char* pchKey ) const
  10. {
  11. if ( pchKey )
  12. {
  13. locchar_t* wszLocalized = Find( pchKey );
  14. if ( !wszLocalized )
  15. {
  16. #ifdef STAGING_ONLY
  17. return const_cast< locchar_t* >(LOCCHAR("<NULL LOC STRING>")); // Super janky cast alert! This method should really return a const locchar_t* but making that change breaks all the callsites...fix later.
  18. #else
  19. return const_cast<locchar_t*>(LOCCHAR(""));
  20. #endif
  21. }
  22. else
  23. {
  24. return wszLocalized;
  25. }
  26. }
  27. else
  28. {
  29. #ifdef STAGING_ONLY
  30. return const_cast<locchar_t*>(LOCCHAR("<NULL LOC KEY>"));
  31. #else
  32. return const_cast<locchar_t*>(LOCCHAR(""));
  33. #endif
  34. }
  35. }
  36. #ifdef GC
  37. #include "gcsdk/gcbase.h"
  38. // GC Localization implementation
  39. static CGCLocalizationProvider *GGCLocalizationProvider()
  40. {
  41. static CGCLocalizationProvider *g_pGCLocalizationProvider = NULL;
  42. if ( !g_pGCLocalizationProvider )
  43. g_pGCLocalizationProvider = new CGCLocalizationProvider( GGCGameBase() );
  44. return g_pGCLocalizationProvider;
  45. }
  46. CLocalizationProvider *GLocalizationProvider()
  47. {
  48. AssertMsg( false, "Using global localization provider in GC - All strings will be in English. For proper localization, CLocalizationProvider instance should be created and passed in." );
  49. return GGCLocalizationProvider();
  50. }
  51. locchar_t *CGCLocalizationProvider::Find( const char *pchKey ) const
  52. {
  53. // we emulate VGUI's behavior of returning an empty string for keys that are not found
  54. return (locchar_t*)m_pGC->LocalizeToken( pchKey, m_eLang, false );
  55. }
  56. bool CGCLocalizationProvider::BEnsureCleanUTF8Truncation( char *unicodeOutput )
  57. {
  58. int nStringLength = V_strlen( unicodeOutput );
  59. // make sure we're not in the middle of a multibyte character
  60. int iPos = nStringLength - 1;
  61. char c = unicodeOutput[iPos];
  62. if ( (c & 0x80) != 0 )
  63. {
  64. // not an ascii char, so do some multibyte char checking
  65. int cBytes = 0;
  66. // count up all continuation bytes
  67. while ( (c & 0xC0) == 0x80 && iPos > 0 ) // first two bits are 10xxxx, continuation
  68. {
  69. cBytes++;
  70. c = unicodeOutput[--iPos];
  71. }
  72. // make sure we had the expected number of continuation bytes for the last
  73. // multibyte lead character
  74. bool bTruncateOK = true;
  75. if ( ( c & 0xF8 ) == 0xF0 ) // first 5 bits are 11110, should be 3 following bytes
  76. bTruncateOK = ( cBytes == 3 );
  77. else if ( ( c & 0xF0 ) == 0xE0 ) // first 4 bits are 1110, should be 2 following bytes
  78. bTruncateOK = ( cBytes == 2 );
  79. else if ( ( c & 0xE0 ) == 0xC0 ) // first 3 bits are 110, should be 1 following byte
  80. bTruncateOK = ( cBytes == 1 );
  81. // if we truncated in the middle of a multi-byte char, move the end point back to this character
  82. if ( !bTruncateOK )
  83. unicodeOutput[iPos] = '\0';
  84. return !bTruncateOK;
  85. }
  86. return false;
  87. }
  88. void CGCLocalizationProvider::ConvertLoccharToANSI( const locchar_t *loc_In, CUtlConstString *out_ansi ) const
  89. {
  90. *out_ansi = loc_In;
  91. }
  92. void CGCLocalizationProvider::ConvertLoccharToUnicode( const locchar_t *loc_In, CUtlConstWideString *out_unicode ) const
  93. {
  94. wchar_t utf16_Scratch[kScratchBufferSize];
  95. V_UTF8ToUnicode( loc_In, utf16_Scratch, kScratchBufferSize );
  96. *out_unicode = utf16_Scratch;
  97. }
  98. void CGCLocalizationProvider::ConvertUTF8ToLocchar( const char *utf8_In, CUtlConstStringBase<locchar_t> *out_loc ) const
  99. {
  100. *out_loc = utf8_In;
  101. }
  102. int CGCLocalizationProvider::ConvertLoccharToANSI( const locchar_t *loc, char *ansi, int ansiBufferSize ) const
  103. {
  104. Q_strncpy( ansi, loc, ansiBufferSize );
  105. return 0;
  106. }
  107. int CGCLocalizationProvider::ConvertLoccharToUnicode( const locchar_t *loc, wchar_t *unicode, int unicodeBufferSize ) const
  108. {
  109. return V_UTF8ToUnicode( loc, unicode, unicodeBufferSize );
  110. }
  111. void CGCLocalizationProvider::ConvertUTF8ToLocchar( const char *utf8, locchar_t *locchar, int loccharBufferSize ) const
  112. {
  113. Q_strncpy( locchar, utf8, loccharBufferSize );
  114. }
  115. #else
  116. CLocalizationProvider *GLocalizationProvider()
  117. {
  118. static CVGUILocalizationProvider g_VGUILocalizationProvider;
  119. return &g_VGUILocalizationProvider;
  120. }
  121. // vgui localization implementation
  122. CVGUILocalizationProvider::CVGUILocalizationProvider()
  123. {
  124. }
  125. locchar_t *CVGUILocalizationProvider::Find( const char *pchKey ) const
  126. {
  127. return (locchar_t*)g_pVGuiLocalize->Find( pchKey );
  128. }
  129. void CVGUILocalizationProvider::ConvertLoccharToANSI( const locchar_t *loc_In, CUtlConstString *out_ansi ) const
  130. {
  131. char ansi_Scratch[kScratchBufferSize];
  132. g_pVGuiLocalize->ConvertUnicodeToANSI( loc_In, ansi_Scratch, kScratchBufferSize );
  133. *out_ansi = ansi_Scratch;
  134. }
  135. void CVGUILocalizationProvider::ConvertLoccharToUnicode( const locchar_t *loc_In, CUtlConstWideString *out_unicode ) const
  136. {
  137. *out_unicode = loc_In;
  138. }
  139. void CVGUILocalizationProvider::ConvertUTF8ToLocchar( const char *utf8_In, CUtlConstStringBase<locchar_t> *out_loc ) const
  140. {
  141. locchar_t loc_Scratch[kScratchBufferSize];
  142. V_UTF8ToUnicode( utf8_In, loc_Scratch, kScratchBufferSize );
  143. *out_loc = loc_Scratch;
  144. }
  145. void CVGUILocalizationProvider::ConvertUTF8ToLocchar( const char *utf8, locchar_t *locchar, int loccharBufferSize ) const
  146. {
  147. V_UTF8ToUnicode( utf8, locchar, loccharBufferSize );
  148. }
  149. int CVGUILocalizationProvider::ConvertLoccharToANSI( const locchar_t *loc, char *ansi, int ansiBufferSize ) const
  150. {
  151. return g_pVGuiLocalize->ConvertUnicodeToANSI( loc, ansi, ansiBufferSize );
  152. }
  153. int CVGUILocalizationProvider::ConvertLoccharToUnicode( const locchar_t *loc, wchar_t *unicode, int unicodeBufferSize ) const
  154. {
  155. Q_wcsncpy( unicode, loc, unicodeBufferSize );
  156. return 0;
  157. }
  158. #endif