Locale_API.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. /*
  2. ** Command & Conquer Renegade(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: /Commando/Code/Tools/WWConfig/Locale_API.cpp $
  24. *
  25. * DESCRIPTION
  26. *
  27. * PROGRAMMER
  28. * $Author: Ian_l $
  29. *
  30. * VERSION INFO
  31. * $Modtime: 1/09/02 11:02a $
  32. * $Revision: 2 $
  33. *
  34. *****************************************************************************/
  35. #include <Windows.h>
  36. #include <wtypes.h>
  37. #include "locale.h"
  38. #include "locale_api.h"
  39. #include "rawfile.h"
  40. #include "wwconfig_ids.h"
  41. /****************************************************************************/
  42. /* DEFINES */
  43. /****************************************************************************/
  44. //----------------------------------------------------------------------------
  45. // NOTE: if USE_MULTI_FILE_FORMAT is "true", then a .lOC file must be in
  46. // the same directory as this file.
  47. //----------------------------------------------------------------------------
  48. #define USE_MULTI_FILE_FORMAT FALSE
  49. #define LANGUAGE_IS_DBCS(l) (((l)==IDL_JAPANESE)||((l)==IDL_KOREAN)||((l)==IDL_CHINESE)) // [OYO]
  50. #define CODEPAGE_IS_DBCS(C) ((C==932)||(C==949)||(C==950)) // [OYO]
  51. /****************************************************************************/
  52. /* GLOBAL VARIABLES */
  53. /****************************************************************************/
  54. CHAR LanguageFile[ _MAX_PATH ];
  55. void * LocaleFile = NULL;
  56. int CodePage = GetACP();
  57. int LanguageID = 0;
  58. /****************************************************************************/
  59. /* LOCALE API */
  60. /****************************************************************************/
  61. WCHAR * Remove_Quotes_Around_String ( WCHAR *old_string );
  62. void * Load_File ( const CHAR *filename, long *filesize );
  63. //=============================================================================
  64. // These are wrapper functions around the LOCALE_ functions. I made these to
  65. // make using the single vs. multi language files more transparent to the program.
  66. //=============================================================================
  67. bool Locale_Use_Multi_Language_Files ( void )
  68. {
  69. #if( USE_MULTI_FILE_FORMAT )
  70. return true;
  71. #else
  72. return false;
  73. #endif
  74. }
  75. /****************************************************************************/
  76. /* initialization */
  77. /****************************************************************************/
  78. int Locale_Init ( int language, char *file )
  79. {
  80. int result = 0;
  81. //-------------------------------------------------------------------------
  82. // Check for a file passed in.
  83. //-------------------------------------------------------------------------
  84. if( file == NULL || file[0] == '/0' ) {
  85. return 0;
  86. }
  87. //-------------------------------------------------------------------------
  88. // Initialize settings.
  89. //-------------------------------------------------------------------------
  90. strcpy( LanguageFile, file );
  91. LanguageID = language;
  92. //-------------------------------------------------------------------------
  93. // If language == -1, then set based on CodePage.
  94. //-------------------------------------------------------------------------
  95. if( LanguageID == -1 ) {
  96. switch( CodePage ) {
  97. // Japanese
  98. case 932:
  99. LanguageID = IDL_JAPANESE;
  100. break;
  101. // Korean
  102. case 949:
  103. LanguageID = IDL_KOREAN;
  104. break;
  105. // Chinese
  106. case 950:
  107. LanguageID = IDL_CHINESE;
  108. break;
  109. // English, French, and German
  110. case 1252:
  111. {
  112. LANGID langid = GetSystemDefaultLangID();
  113. WORD plangid = PRIMARYLANGID( langid );
  114. switch( plangid ) {
  115. // German
  116. case 0x07:
  117. LanguageID = IDL_GERMAN;
  118. break;
  119. // French
  120. case 0x0c:
  121. LanguageID = IDL_FRENCH;
  122. break;
  123. // English
  124. case 0x09:
  125. default:
  126. LanguageID = IDL_ENGLISH;
  127. break;
  128. }
  129. }
  130. break;
  131. default:
  132. LanguageID = IDL_ENGLISH;
  133. break;
  134. }
  135. }
  136. //-------------------------------------------------------------------------
  137. // Check for valid LanguageID range.
  138. //-------------------------------------------------------------------------
  139. if( LanguageID < 0 || LanguageID >= LOCALE_LANGUAGE_COUNT ) {
  140. LanguageID = 0;
  141. }
  142. //-------------------------------------------------------------------------
  143. // Use English in the situation where Chinese, Korean, or Japanese was
  144. // requested but not available.
  145. //-------------------------------------------------------------------------
  146. if( LANGUAGE_IS_DBCS( LanguageID ) && !CODEPAGE_IS_DBCS( CodePage )) {
  147. LanguageID = IDL_ENGLISH;
  148. }
  149. //-------------------------------------------------------------------------
  150. // Initialize the lx object.
  151. //-------------------------------------------------------------------------
  152. LOCALE_init();
  153. #if( USE_MULTI_FILE_FORMAT )
  154. //---------------------------------------------------------------------
  155. // Set bank to use and load the appropriate table.
  156. //---------------------------------------------------------------------
  157. LOCALE_setbank(0);
  158. result = LOCALE_loadtable( LanguageFile, LanguageID );
  159. #else
  160. //---------------------------------------------------------------------
  161. // Create a file buffer that holds all the strings in the file.
  162. //---------------------------------------------------------------------
  163. long filesize;
  164. HRSRC hRsrc;
  165. HGLOBAL hGlobal;
  166. int PrimaryLanguage = LANG_NEUTRAL;
  167. int SubLanguage = SUBLANG_DEFAULT;
  168. HMODULE module = GetModuleHandle( NULL );
  169. //-------------------------------------------------------------------------
  170. // Find the string file in this program's resources.
  171. //-------------------------------------------------------------------------
  172. switch( LanguageID ) {
  173. // Japanese
  174. case IDL_JAPANESE:
  175. PrimaryLanguage = LANG_JAPANESE;
  176. SubLanguage = SUBLANG_DEFAULT;
  177. break;
  178. // Korean
  179. case IDL_KOREAN:
  180. PrimaryLanguage = LANG_KOREAN;
  181. SubLanguage = SUBLANG_DEFAULT;
  182. break;
  183. // Chinese
  184. case IDL_CHINESE:
  185. PrimaryLanguage = LANG_CHINESE;
  186. SubLanguage = SUBLANG_DEFAULT;
  187. break;
  188. // German
  189. case IDL_GERMAN:
  190. PrimaryLanguage = LANG_GERMAN;
  191. SubLanguage = SUBLANG_GERMAN;
  192. break;
  193. // French
  194. case IDL_FRENCH:
  195. PrimaryLanguage = LANG_FRENCH;
  196. SubLanguage = SUBLANG_FRENCH;
  197. break;
  198. // English
  199. case IDL_ENGLISH:
  200. PrimaryLanguage = LANG_ENGLISH;
  201. SubLanguage = SUBLANG_ENGLISH_US;
  202. break;
  203. default:
  204. PrimaryLanguage = LANG_ENGLISH;
  205. SubLanguage = SUBLANG_ENGLISH_US;
  206. break;
  207. }
  208. hRsrc = FindResourceEx( module, RT_RCDATA, "STRINGS", MAKELANGID( PrimaryLanguage, SubLanguage ));
  209. if ( hRsrc == NULL ) {
  210. hRsrc = FindResourceEx( module, RT_RCDATA, "STRINGS", MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ));
  211. }
  212. if ( hRsrc ) {
  213. //---------------------------------------------------------------------
  214. // Load the resource, lock the memory, grab a DC.
  215. //---------------------------------------------------------------------
  216. hGlobal = LoadResource( module, hRsrc );
  217. filesize = SizeofResource( module, hRsrc );
  218. LocaleFile = (void*)malloc( filesize + 1 );
  219. memset( LocaleFile, '\0', filesize + 1 );
  220. memcpy( LocaleFile, (const void *)hGlobal, filesize );
  221. //---------------------------------------------------------------------
  222. // Free DS and memory used.
  223. //---------------------------------------------------------------------
  224. UnlockResource( hGlobal );
  225. FreeResource( hGlobal );
  226. }
  227. if( LocaleFile == NULL ) {
  228. LocaleFile = Load_File( LanguageFile, &filesize );
  229. }
  230. if( LocaleFile != NULL ) {
  231. result = 1;
  232. }
  233. #endif
  234. return result;
  235. }
  236. /************************************************************************/
  237. /* restore */
  238. /************************************************************************/
  239. void Locale_Restore ( void )
  240. {
  241. #if( USE_MULTI_FILE_FORMAT )
  242. LOCALE_freetable();
  243. LOCALE_restore();
  244. #else
  245. if( LocaleFile ) {
  246. free( LocaleFile );
  247. LocaleFile = NULL;
  248. }
  249. #endif
  250. }
  251. /********************************************************************************
  252. * Load_File -- Allocates a buffer and loads the file into it. *
  253. * *
  254. * Get a string usine Resource ID and a buffer. *
  255. * *
  256. * INPUT: int StringID -- The resource number of the string. *
  257. * CHAR *String -- The buffer to place the text in. *
  258. * *
  259. * OUTPUT: Returns with a pointer to the buffer. *
  260. * *
  261. * WARNINGS: none *
  262. * *
  263. * HISTORY: *
  264. * 12/10/2001 MML : Created. *
  265. *==============================================================================*/
  266. const CHAR* Locale_GetString( int StringID, CHAR *String )
  267. {
  268. static CHAR buffer[ _MAX_PATH ];
  269. static WCHAR wide_buffer[ _MAX_PATH ];
  270. memset( buffer, '\0', _MAX_PATH );
  271. memset( wide_buffer, '\0', _MAX_PATH );
  272. #if( USE_MULTI_FILE_FORMAT )
  273. wcscpy( wide_buffer, (WCHAR *)LOCALE_getstring( StringID ));
  274. #else
  275. wcscpy( wide_buffer, (WCHAR *)LOCALE_getstr( LocaleFile, StringID ));
  276. #endif
  277. Remove_Quotes_Around_String( wide_buffer );
  278. WideCharToMultiByte( CodePage, 0, wide_buffer, _MAX_PATH, buffer, _MAX_PATH, NULL, NULL );
  279. if( String != NULL ) {
  280. strncpy( String, buffer, _MAX_PATH );
  281. }
  282. return buffer;
  283. }
  284. /********************************************************************************
  285. * Load_File -- Allocates a buffer and loads the file into it. *
  286. * *
  287. * Get a string usine Resource ID and a buffer. *
  288. * *
  289. * INPUT: int StringID -- The resource number of the string. *
  290. * WCHAR *String -- The buffer to place the text in. *
  291. * *
  292. * OUTPUT: Returns with a pointer to the buffer. *
  293. * *
  294. * WARNINGS: none *
  295. * *
  296. * HISTORY: *
  297. * 12/10/2001 MML : Created. *
  298. *==============================================================================*/
  299. const WCHAR* Locale_GetString( int StringID, WCHAR *String )
  300. {
  301. static WCHAR wide_buffer[ _MAX_PATH ];
  302. memset( wide_buffer, '\0', _MAX_PATH );
  303. #if( USE_MULTI_FILE_FORMAT )
  304. wcscpy( wide_buffer, (WCHAR *)LOCALE_getstring( StringID ));
  305. #else
  306. wcscpy( wide_buffer, (WCHAR *)LOCALE_getstr( LocaleFile, StringID ));
  307. #endif
  308. Remove_Quotes_Around_String( wide_buffer );
  309. if( String != NULL ) {
  310. wcsncpy( String, wide_buffer, _MAX_PATH );
  311. }
  312. return wide_buffer;
  313. }
  314. /********************************************************************************
  315. * Load_File -- Allocates a buffer and loads the file into it. *
  316. * *
  317. * Get a string usine Resource ID and a buffer. *
  318. * *
  319. * INPUT: int StringID -- The resource number of the string. *
  320. * *
  321. * OUTPUT: Returns with a pointer to the buffer. *
  322. * *
  323. * WARNINGS: none *
  324. * *
  325. * HISTORY: *
  326. * 12/10/2001 MML : Created. *
  327. *==============================================================================*/
  328. const WCHAR* Locale_GetString( int StringID )
  329. {
  330. static WCHAR wide_buffer[ _MAX_PATH ];
  331. memset( wide_buffer, '\0', _MAX_PATH );
  332. #if( USE_MULTI_FILE_FORMAT )
  333. wcscpy( wide_buffer, (WCHAR *)LOCALE_getstring( StringID ));
  334. #else
  335. wcscpy( wide_buffer, (WCHAR *)LOCALE_getstr( LocaleFile, StringID ));
  336. #endif
  337. Remove_Quotes_Around_String( wide_buffer );
  338. return wide_buffer;
  339. }
  340. /****************************************************************************/
  341. /* formating strings */
  342. /****************************************************************************/
  343. WCHAR *Remove_Quotes_Around_String ( WCHAR *old_string )
  344. {
  345. WCHAR wide_buffer[ _MAX_PATH * 3 ];
  346. WCHAR * letter = old_string;
  347. int length;
  348. //----------------------------------------------------------------------
  349. // If string is not NULL...
  350. //----------------------------------------------------------------------
  351. if ( *letter == '"' ) {
  352. letter++;
  353. wcscpy( wide_buffer, letter );
  354. length = wcslen( wide_buffer );
  355. if ( wide_buffer[ wcslen( wide_buffer )-1 ] == '"' ) {
  356. wide_buffer[ wcslen( wide_buffer )-1 ] = '\0';
  357. }
  358. wcscpy( old_string, wide_buffer );
  359. }
  360. return( old_string );
  361. }
  362. /********************************************************************************
  363. * Load_File -- Allocates a buffer and loads the file into it. *
  364. * *
  365. * This is the C++ replacement for the Load_Alloc_Data function. It will *
  366. * allocate the memory big enough to hold the file & read the file into it. *
  367. * *
  368. * INPUT: file -- The file to read. *
  369. * mem -- The memory system to use for allocation. *
  370. * *
  371. * OUTPUT: Returns with a pointer to the allocated and filled memory block. *
  372. * *
  373. * WARNINGS: none *
  374. * *
  375. * HISTORY: *
  376. * 10/17/1994 JLB : Created. *
  377. *==============================================================================*/
  378. void * Load_File ( const char *filename, long *filesize )
  379. {
  380. int size, bytes_read;
  381. void *ptr = NULL;
  382. // StandardFileClass file;
  383. RawFileClass file;
  384. if ( filename == NULL || filename[0] == '\0' ) {
  385. return( NULL );
  386. }
  387. //-------------------------------------------------------------------------
  388. // Open file in READ ONLY mode. If fails, exit.
  389. //-------------------------------------------------------------------------
  390. // file.Open( filename, MODE_READ_ONLY );
  391. file.Open( filename, FileClass::READ );
  392. // if( !file.Query_Open()) {
  393. if( !file.Is_Open()) {
  394. return( NULL );
  395. }
  396. //-------------------------------------------------------------------------
  397. // Get filesize and create a buffer.
  398. //-------------------------------------------------------------------------
  399. // size = file.Query_Size();
  400. size = file.Size();
  401. ptr = (void*)malloc(size + 1);
  402. if ( !ptr ) {
  403. return( NULL );
  404. }
  405. //-------------------------------------------------------------------------
  406. // Read data into the buffer, close the file.
  407. //-------------------------------------------------------------------------
  408. memset( ptr, '\0', size + 1 );
  409. // bytes_read = file.Read( ptr, size );
  410. bytes_read = file.Read( ptr, size );
  411. // file.Close();
  412. file.Close();
  413. //-------------------------------------------------------------------------
  414. // Check return bytes. It should match the file size.
  415. //-------------------------------------------------------------------------
  416. assert( bytes_read == size );
  417. if ( bytes_read != size ) {
  418. free(ptr);
  419. return( NULL );
  420. }
  421. if ( filesize != NULL ) {
  422. *filesize = (long)size;
  423. }
  424. return( ptr );
  425. }