Locale_API.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. /*
  2. ** Command & Conquer Generals Zero Hour(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /*****************************************************************************
  19. * C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S *
  20. ******************************************************************************
  21. *
  22. * FILE
  23. * $Archive: /Renegade Setup/Autorun/Locale_API.cpp $
  24. *
  25. * DESCRIPTION
  26. *
  27. * PROGRAMMER
  28. * $Author: Maria_l $
  29. *
  30. * VERSION INFO
  31. * $Modtime: 1/22/02 5:41p $
  32. * $Revision: 12 $
  33. *
  34. *****************************************************************************/
  35. #include "locale.h"
  36. #include "locale_api.h"
  37. #include "utils.h"
  38. #include "wnd_file.h"
  39. //#include "resources.h"
  40. #include "GameText.h"
  41. #define MISSING_STRING_HINTS_MAX (20)
  42. wchar_t *localeStringsMissing[ MISSING_STRING_HINTS_MAX ] =
  43. {
  44. { L"0 MissingInstall" },
  45. { L"1 MissingExplore" },
  46. { L"2 MissingPreviews" },
  47. { L"3 MissingCancel" },
  48. { L"4 MissingAutoRunTitle" },
  49. { L"5 MissingNoExplorer" },
  50. { L"6 MissingWinVersionText" },
  51. { L"7 MissingWinVersionTitle" },
  52. { L"8 MissingCantFind" },
  53. { L"9 MissingUninstall" },
  54. { L"10 MissingWebsite" },
  55. { L"11 MissingCheckForUpdates" },
  56. { L"12 MissingWorldBuilder" },
  57. { L"13 MissingPlay" },
  58. { L"14 MissingGameTitle" },
  59. { L"15 MissingFullGameTitle" },
  60. { L"16 MissingRegistryKey" },
  61. { L"17 MissingMainWindow" },
  62. { L"18 MissingThing" },
  63. { L"19 UNKNOWN MESSAGE" }
  64. };
  65. /****************************************************************************/
  66. /* DEFINES */
  67. /****************************************************************************/
  68. //----------------------------------------------------------------------------
  69. // NOTE: if USE_MULTI_FILE_FORMAT is "true", then a .lOC file must be in
  70. // the same directory as this file.
  71. //----------------------------------------------------------------------------
  72. #define USE_MULTI_FILE_FORMAT FALSE
  73. #define LANGUAGE_IS_DBCS(l) (((l)==IDL_JAPANESE)||((l)==IDL_KOREAN)||((l)==IDL_CHINESE)) // [OYO]
  74. #define CODEPAGE_IS_DBCS(C) ((C==932)||(C==949)||(C==950)) // [OYO]
  75. /****************************************************************************/
  76. /* GLOBAL VARIABLES */
  77. /****************************************************************************/
  78. char LanguageFile[ _MAX_PATH ];
  79. void * LocaleFile = NULL;
  80. int CodePage = GetACP();
  81. int LanguageID = 0;
  82. int PrimaryLanguage = LANG_NEUTRAL;
  83. int SubLanguage = SUBLANG_DEFAULT;
  84. /****************************************************************************/
  85. /* LOCALE API */
  86. /****************************************************************************/
  87. wchar_t * Remove_Quotes_Around_String ( wchar_t *old_string );
  88. //=============================================================================
  89. // These are wrapper functions around the LOCALE_ functions. I made these to
  90. // make using the single vs. multi language files more transparent to the program.
  91. //=============================================================================
  92. bool Locale_Use_Multi_Language_Files ( void )
  93. {
  94. #if( USE_MULTI_FILE_FORMAT )
  95. return true;
  96. #else
  97. return false;
  98. #endif
  99. }
  100. /****************************************************************************/
  101. /* initialization */
  102. /****************************************************************************/
  103. int Locale_Init ( int language, char *file )
  104. {
  105. int result = 0;
  106. TheGameText = CreateGameTextInterface();
  107. TheGameText->init();
  108. /*
  109. //-------------------------------------------------------------------------
  110. // Check for valid language range.
  111. //-------------------------------------------------------------------------
  112. if( language < 0 || language >= LANG_NUM ) {
  113. language = 0;
  114. }
  115. //-------------------------------------------------------------------------
  116. // Check for a file passed in.
  117. //-------------------------------------------------------------------------
  118. if( file == NULL || file[0] == '/0' ) {
  119. return 0;
  120. }
  121. strcpy( LanguageFile, file );
  122. LanguageID = language;
  123. Msg( __LINE__, __FILE__, "LanguageID = %d", LanguageID );
  124. Msg( __LINE__, __FILE__, "CodePage = %d.", CodePage );
  125. Msg( __LINE__, __FILE__, "LanguageFile = %s.", LanguageFile );
  126. //-------------------------------------------------------------------------
  127. // Initialize the lx object.
  128. //-------------------------------------------------------------------------
  129. LOCALE_init();
  130. #if( USE_MULTI_FILE_FORMAT )
  131. //---------------------------------------------------------------------
  132. // Set bank to use and load the appropriate table.
  133. //---------------------------------------------------------------------
  134. LOCALE_setbank(0);
  135. result = LOCALE_loadtable( LanguageFile, LanguageID );
  136. #else
  137. //---------------------------------------------------------------------
  138. // Create a file buffer that holds all the strings in the file.
  139. //---------------------------------------------------------------------
  140. long filesize;
  141. HRSRC hRsrc;
  142. HGLOBAL hGlobal;
  143. HMODULE module = GetModuleHandle( NULL );
  144. //-------------------------------------------------------------------------
  145. // Find the string file in this program's resources.
  146. //-------------------------------------------------------------------------
  147. switch( CodePage ) {
  148. // Japanese
  149. case 932:
  150. PrimaryLanguage = LANG_JAPANESE;
  151. SubLanguage = SUBLANG_DEFAULT;
  152. break;
  153. // Korean
  154. case 949:
  155. PrimaryLanguage = LANG_KOREAN;
  156. SubLanguage = SUBLANG_DEFAULT;
  157. break;
  158. // Chinese
  159. case 950:
  160. PrimaryLanguage = LANG_CHINESE;
  161. SubLanguage = SUBLANG_DEFAULT;
  162. break;
  163. // English, French, and German
  164. case 1252:
  165. switch( LanguageID ) {
  166. case LANG_GERMAN:
  167. PrimaryLanguage = LANG_GERMAN;
  168. SubLanguage = SUBLANG_GERMAN;
  169. break;
  170. case LANG_FRENCH:
  171. PrimaryLanguage = LANG_FRENCH;
  172. SubLanguage = SUBLANG_FRENCH;
  173. break;
  174. case LANG_ENGLISH:
  175. PrimaryLanguage = LANG_ENGLISH;
  176. SubLanguage = SUBLANG_ENGLISH_US;
  177. break;
  178. }
  179. break;
  180. }
  181. hRsrc = FindResourceEx( module, RT_RCDATA, "STRINGS", MAKELANGID( PrimaryLanguage, SubLanguage ));
  182. if ( hRsrc == NULL ) {
  183. hRsrc = FindResourceEx( module, RT_RCDATA, "STRINGS", MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ));
  184. }
  185. if ( hRsrc ) {
  186. //---------------------------------------------------------------------
  187. // Load the resource, lock the memory, grab a DC.
  188. //---------------------------------------------------------------------
  189. hGlobal = LoadResource( module, hRsrc );
  190. filesize = SizeofResource( module, hRsrc );
  191. LocaleFile = (void*)malloc( filesize + 1 );
  192. memset( LocaleFile, '\0', filesize + 1 );
  193. memcpy( LocaleFile, (const void *)hGlobal, filesize );
  194. //---------------------------------------------------------------------
  195. // Free DS and memory used.
  196. //---------------------------------------------------------------------
  197. UnlockResource( hGlobal );
  198. FreeResource( hGlobal );
  199. }
  200. if( LocaleFile == NULL ) {
  201. LocaleFile = Load_File( LanguageFile, &filesize );
  202. }
  203. if( LocaleFile != NULL ) {
  204. result = 1;
  205. }
  206. //---------------------------------------------------------------------
  207. // Set the LanguageID because we may need this later.
  208. //---------------------------------------------------------------------
  209. // CHAR buffer[ _MAX_PATH ];
  210. // Locale_GetString( LANG_NUM, buffer );
  211. // LanguageID = atoi( buffer );
  212. LanguageID = 0;
  213. #if(_DEBUG)
  214. switch( LanguageID ) {
  215. case 6:
  216. CodePage = 932;
  217. break;
  218. case 9:
  219. CodePage = 949;
  220. break;
  221. case 10:
  222. CodePage = 950;
  223. break;
  224. }
  225. #endif
  226. #endif
  227. */
  228. return result;
  229. }
  230. /************************************************************************/
  231. /* restore */
  232. /************************************************************************/
  233. void Locale_Restore ( void )
  234. {
  235. if (TheGameText)
  236. {
  237. delete TheGameText;
  238. TheGameText = NULL;
  239. }
  240. #if( USE_MULTI_FILE_FORMAT )
  241. LOCALE_freetable();
  242. LOCALE_restore();
  243. #else
  244. if( LocaleFile ) {
  245. free( LocaleFile );
  246. LocaleFile = NULL;
  247. }
  248. #endif
  249. }
  250. /****************************************************************************/
  251. /* retreiving strings */
  252. /****************************************************************************/
  253. const char* Locale_GetString( int StringID, char *String )
  254. {
  255. static char buffer[ _MAX_PATH ];
  256. static wchar_t wide_buffer[ _MAX_PATH ];
  257. memset( buffer, '\0', _MAX_PATH );
  258. memset( wide_buffer, '\0', _MAX_PATH );
  259. #if( USE_MULTI_FILE_FORMAT )
  260. wcscpy( wide_buffer, (wchar_t *)LOCALE_getstring( StringID ));
  261. #else
  262. wcscpy( wide_buffer, (wchar_t *)LOCALE_getstr( LocaleFile, StringID ));
  263. #endif
  264. Remove_Quotes_Around_String( wide_buffer );
  265. WideCharToMultiByte( CodePage, 0, wide_buffer, _MAX_PATH, buffer, _MAX_PATH, NULL, NULL );
  266. if( String != NULL ) {
  267. strncpy( String, buffer, _MAX_PATH );
  268. }
  269. return buffer;
  270. }
  271. const wchar_t* Locale_GetString( const char *id, wchar_t *buffer, int size )
  272. {
  273. if (TheGameText)
  274. {
  275. const wchar_t *fetched = TheGameText->fetch(id);
  276. if (buffer)
  277. {
  278. wcsncpy(buffer, fetched, size);
  279. buffer[size-1] = 0;
  280. }
  281. return fetched;
  282. }
  283. return L"No String Manager";
  284. }
  285. /*
  286. const wchar_t* Locale_GetString( int StringID, wchar_t *String )
  287. {
  288. static wchar_t wide_buffer[ _MAX_PATH ];
  289. memset( wide_buffer, '\0', _MAX_PATH );
  290. #if( USE_MULTI_FILE_FORMAT )
  291. wcscpy( wide_buffer, (wchar_t *)LOCALE_getstring( StringID ));
  292. #else
  293. wchar_t *localeStr = NULL;
  294. if (TheGameText != NULL)
  295. localeStr = (wchar_t *)TheGameText->fetch( s_stringLabels[StringID] );
  296. if (localeStr == NULL)
  297. {
  298. return localeStringsMissing[ min( MISSING_STRING_HINTS_MAX - 1, StringID ) ];
  299. }
  300. else
  301. {
  302. wcscpy( wide_buffer, localeStr);
  303. }
  304. #endif
  305. Remove_Quotes_Around_String( wide_buffer );
  306. if( String != NULL ) {
  307. wcsncpy( String, wide_buffer, _MAX_PATH );
  308. }
  309. return wide_buffer;
  310. }
  311. */
  312. /****************************************************************************/
  313. /* formating strings */
  314. /****************************************************************************/
  315. wchar_t *Remove_Quotes_Around_String ( wchar_t *old_string )
  316. {
  317. wchar_t wide_buffer[ _MAX_PATH ];
  318. wchar_t *letter = old_string;
  319. int length;
  320. //----------------------------------------------------------------------
  321. // If string is not NULL...
  322. //----------------------------------------------------------------------
  323. if ( *letter == '"' ) {
  324. letter++;
  325. wcscpy( wide_buffer, letter );
  326. length = wcslen( wide_buffer );
  327. if ( wide_buffer[ wcslen( wide_buffer )-1 ] == '"' ) {
  328. wide_buffer[ wcslen( wide_buffer )-1 ] = '\0';
  329. }
  330. wcscpy( old_string, wide_buffer );
  331. }
  332. return( old_string );
  333. }