stringsmgr.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793
  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 S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : LevelEdit *
  23. * *
  24. * $Archive:: /Commando/Code/Tools/LevelEdit/stringsmgr.cpp $*
  25. * *
  26. * Author:: Patrick Smith *
  27. * *
  28. * $Modtime:: 2/12/02 6:16p $*
  29. * *
  30. * $Revision:: 14 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "stdafx.h"
  36. #include "stringsmgr.h"
  37. #include "filelocations.h"
  38. #include "filemgr.h"
  39. #include "assetdatabase.h"
  40. #include "chunkio.h"
  41. #include "rawfile.h"
  42. #include "saveload.h"
  43. #include "translatedb.h"
  44. #include "stringlibrarydialog.h"
  45. #include "excel.h"
  46. #include "audiblesound.h"
  47. #include "definitionmgr.h"
  48. #include "definitionclassids.h"
  49. #include "utils.h"
  50. /////////////////////////////////////////////////////////////////////////
  51. // Local constants
  52. /////////////////////////////////////////////////////////////////////////
  53. enum
  54. {
  55. COL_CATEGORY_NAME = 0,
  56. COL_STRING_ID,
  57. COL_SOUND_FILENAME,
  58. COL_ENGLISH_TEXT,
  59. COL_TRANSLATED_TEXT,
  60. COL_COMMENTS,
  61. COL_ERRORS,
  62. COL_SOUND_PRESET_NAME,
  63. };
  64. /////////////////////////////////////////////////////////////////////////
  65. //
  66. // Create_Database_If_Necessary
  67. //
  68. /////////////////////////////////////////////////////////////////////////
  69. void
  70. StringsMgrClass::Create_Database_If_Necessary (void)
  71. {
  72. FileMgrClass *file_mgr = ::Get_File_Mgr ();
  73. AssetDatabaseClass &asset_db = file_mgr->Get_Database_Interface ();
  74. //
  75. // Determine where the file should exist locally
  76. //
  77. CString filename = ::Get_File_Mgr ()->Make_Full_Path (STRINGS_DB_PATH);
  78. //
  79. // Check to see if the file exists in VSS
  80. //
  81. if (asset_db.Does_File_Exist (filename) == false) {
  82. //
  83. // Save a copy of the database to disk and add it to VSS
  84. //
  85. Save_Translation_Database ();
  86. asset_db.Add_File (filename);
  87. } else {
  88. //
  89. // The file exists in VSS, so update our local copy
  90. //
  91. Get_Latest_Version ();
  92. }
  93. return ;
  94. }
  95. /////////////////////////////////////////////////////////////////////////
  96. //
  97. // Save_Translation_Database
  98. //
  99. /////////////////////////////////////////////////////////////////////////
  100. void
  101. StringsMgrClass::Save_Translation_Database (void)
  102. {
  103. CString filename = ::Get_File_Mgr ()->Make_Full_Path (STRINGS_DB_PATH);
  104. Save_Translation_Database (filename);
  105. return ;
  106. }
  107. /////////////////////////////////////////////////////////////////////////
  108. //
  109. // Save_Translation_Database
  110. //
  111. /////////////////////////////////////////////////////////////////////////
  112. void
  113. StringsMgrClass::Save_Translation_Database (const char *full_path)
  114. {
  115. //
  116. // Create the file
  117. //
  118. HANDLE file = ::CreateFile (full_path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
  119. 0L, NULL);
  120. ASSERT (file != INVALID_HANDLE_VALUE);
  121. if (file != INVALID_HANDLE_VALUE) {
  122. RawFileClass file_obj;
  123. file_obj.Attach (file);
  124. ChunkSaveClass chunk_save (&file_obj);
  125. //
  126. // Save the translation database subsystem
  127. //
  128. SaveLoadSystemClass::Save (chunk_save, _TheTranslateDB);
  129. }
  130. return ;
  131. }
  132. /////////////////////////////////////////////////////////////////////////
  133. //
  134. // Load_Translation_Database
  135. //
  136. /////////////////////////////////////////////////////////////////////////
  137. void
  138. StringsMgrClass::Load_Translation_Database (void)
  139. {
  140. CString filename = ::Get_File_Mgr ()->Make_Full_Path (STRINGS_DB_PATH);
  141. //
  142. // Open the file
  143. //
  144. HANDLE file = ::CreateFile (filename, GENERIC_READ, FILE_SHARE_READ, NULL,
  145. OPEN_EXISTING, 0L, NULL);
  146. ASSERT (file != INVALID_HANDLE_VALUE);
  147. if (file != INVALID_HANDLE_VALUE) {
  148. RawFileClass file_obj;
  149. file_obj.Attach (file);
  150. ChunkLoadClass chunk_load (&file_obj);
  151. //
  152. // Let the save/load system handle the laod
  153. //
  154. SaveLoadSystemClass::Load (chunk_load);
  155. }
  156. return ;
  157. }
  158. /////////////////////////////////////////////////////////////////////////
  159. //
  160. // Import_Strings
  161. //
  162. /////////////////////////////////////////////////////////////////////////
  163. void
  164. StringsMgrClass::Import_Strings (void)
  165. {
  166. CFileDialog dialog (TRUE, ".txt", "strings.txt",
  167. OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_EXPLORER,
  168. "Text Files (*.txt)|*.txt||", ::AfxGetMainWnd ());
  169. dialog.m_ofn.lpstrTitle = "Import Strings";
  170. //
  171. // Ask the user what file they want to load
  172. //
  173. if (dialog.DoModal () == IDOK) {
  174. if (Check_Out ()) {
  175. //
  176. // Import the strings and save the database back to disk
  177. //
  178. TranslateDBClass::Import_Strings (dialog.GetPathName ());
  179. Save_Translation_Database ();
  180. Check_In ();
  181. }
  182. }
  183. return ;
  184. }
  185. /////////////////////////////////////////////////////////////////////////
  186. //
  187. // Import_IDs
  188. //
  189. /////////////////////////////////////////////////////////////////////////
  190. void
  191. StringsMgrClass::Import_IDs (void)
  192. {
  193. CFileDialog dialog (TRUE, ".h", "string_ids.h",
  194. OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_EXPLORER,
  195. "C Header Files (*.h)|*.h||", ::AfxGetMainWnd ());
  196. //
  197. // Ask the user what file they want to load
  198. //
  199. if (dialog.DoModal () == IDOK) {
  200. if (Check_Out ()) {
  201. //
  202. // Import the header and save the database back to disk
  203. //
  204. TranslateDBClass::Import_C_Header (dialog.GetPathName ());
  205. Save_Translation_Database ();
  206. Check_In ();
  207. }
  208. }
  209. return ;
  210. }
  211. /////////////////////////////////////////////////////////////////////////
  212. //
  213. // Export_IDs
  214. //
  215. /////////////////////////////////////////////////////////////////////////
  216. void
  217. StringsMgrClass::Export_IDs (void)
  218. {
  219. CFileDialog dialog (FALSE, ".h", "string_ids.h",
  220. OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_EXPLORER,
  221. "C Header Files (*.h)|*.h||", ::AfxGetMainWnd ());
  222. //
  223. // Ask the user what file they want to create
  224. //
  225. if (dialog.DoModal () == IDOK) {
  226. //
  227. // Check to make sure the destination filename is not read-only
  228. //
  229. CString path = dialog.GetPathName ();
  230. DWORD file_attributes = ::GetFileAttributes (path);
  231. if (file_attributes != 0xFFFFFFFF && file_attributes & FILE_ATTRIBUTE_READONLY) {
  232. ::MessageBox (::AfxGetMainWnd ()->m_hWnd, "File is read-only, export operation can not complete.", "File Error", MB_ICONERROR | MB_ICONEXCLAMATION);
  233. } else {
  234. TranslateDBClass::Export_C_Header (path);
  235. }
  236. }
  237. return ;
  238. }
  239. /////////////////////////////////////////////////////////////////////////
  240. //
  241. // Get_Latest_Version
  242. //
  243. /////////////////////////////////////////////////////////////////////////
  244. bool
  245. StringsMgrClass::Get_Latest_Version (void)
  246. {
  247. FileMgrClass *file_mgr = ::Get_File_Mgr ();
  248. AssetDatabaseClass &asset_db = file_mgr->Get_Database_Interface ();
  249. //
  250. // Determine where the file should exist locally
  251. //
  252. CString filename = ::Get_File_Mgr ()->Make_Full_Path (STRINGS_DB_PATH);
  253. //
  254. // Ask VSS to get the latest version of the file for us
  255. //
  256. return asset_db.Get (filename);
  257. }
  258. /////////////////////////////////////////////////////////////////////////
  259. //
  260. // Check_Out
  261. //
  262. /////////////////////////////////////////////////////////////////////////
  263. bool
  264. StringsMgrClass::Check_Out (void)
  265. {
  266. FileMgrClass *file_mgr = ::Get_File_Mgr ();
  267. AssetDatabaseClass &asset_db = file_mgr->Get_Database_Interface ();
  268. //
  269. // Determine where the file should exist locally
  270. //
  271. CString filename = ::Get_File_Mgr ()->Make_Full_Path (STRINGS_DB_PATH);
  272. //
  273. // Ask VSS to check out the file to us
  274. //
  275. return asset_db.Check_Out_Ex (filename, ::AfxGetMainWnd ()->m_hWnd);
  276. }
  277. /////////////////////////////////////////////////////////////////////////
  278. //
  279. // Check_In
  280. //
  281. /////////////////////////////////////////////////////////////////////////
  282. bool
  283. StringsMgrClass::Check_In (void)
  284. {
  285. FileMgrClass *file_mgr = ::Get_File_Mgr ();
  286. AssetDatabaseClass &asset_db = file_mgr->Get_Database_Interface ();
  287. //
  288. // Determine where the file should exist locally
  289. //
  290. CString filename = ::Get_File_Mgr ()->Make_Full_Path (STRINGS_DB_PATH);
  291. //
  292. // Ask VSS to check in the file for us
  293. //
  294. return asset_db.Check_In_Ex (filename, ::AfxGetMainWnd ()->m_hWnd);
  295. }
  296. /////////////////////////////////////////////////////////////////////////
  297. //
  298. // Undo_Check_Out
  299. //
  300. /////////////////////////////////////////////////////////////////////////
  301. bool
  302. StringsMgrClass::Undo_Check_Out (void)
  303. {
  304. FileMgrClass *file_mgr = ::Get_File_Mgr ();
  305. AssetDatabaseClass &asset_db = file_mgr->Get_Database_Interface ();
  306. bool retval = false;
  307. //
  308. // Determine where the file should exist locally
  309. //
  310. CString filename = ::Get_File_Mgr ()->Make_Full_Path (STRINGS_DB_PATH);
  311. //
  312. // We only undo the checkout if its checked out to us
  313. //
  314. if (asset_db.Get_File_Status (filename) == AssetDatabaseClass::CHECKED_OUT_TO_ME) {
  315. retval = asset_db.Undo_Check_Out (filename);
  316. }
  317. return retval;
  318. }
  319. /////////////////////////////////////////////////////////////////////////
  320. //
  321. // Edit_Database
  322. //
  323. /////////////////////////////////////////////////////////////////////////
  324. void
  325. StringsMgrClass::Edit_Database (HWND parent_wnd)
  326. {
  327. CWaitCursor wait_cursor;
  328. //
  329. // Check out the strings database from VSS
  330. //
  331. if (StringsMgrClass::Check_Out ()) {
  332. //
  333. // Reload the database
  334. //
  335. StringsMgrClass::Load_Translation_Database ();
  336. //
  337. // Show a dialog to the user so then can edit the strings
  338. //
  339. StringLibraryDialogClass dialog (CWnd::FromHandle (parent_wnd));
  340. if (dialog.DoModal () == IDOK) {
  341. StringsMgrClass::Save_Translation_Database ();
  342. StringsMgrClass::Check_In ();
  343. } else {
  344. StringsMgrClass::Undo_Check_Out ();
  345. }
  346. }
  347. return ;
  348. }
  349. /////////////////////////////////////////////////////////////////////////
  350. //
  351. // Export_For_Translation
  352. //
  353. /////////////////////////////////////////////////////////////////////////
  354. void
  355. StringsMgrClass::Export_For_Translation (const char *filename, uint32 lang_id)
  356. {
  357. CWaitCursor wait_cursor;
  358. if (ExcelClass::Initialize () == false) {
  359. ::MessageBox (::AfxGetMainWnd ()->m_hWnd, "Cannot Initialize Excel, this feature requires Excel installed on the machine.", "Export Error", MB_ICONERROR | MB_OK);
  360. return ;
  361. }
  362. //
  363. // Overwrite any existing files
  364. //
  365. if (GetFileAttributes (filename) != 0xFFFFFFFF) {
  366. ::DeleteFile (filename);
  367. }
  368. //
  369. // Lookup the path of the executable
  370. //
  371. char path[MAX_PATH] = { 0 };
  372. ::GetModuleFileName (NULL, path, sizeof (path));
  373. //
  374. // Strip off the filename
  375. //
  376. char *filename_portion = ::strrchr (path, '\\');
  377. if (filename_portion != NULL) {
  378. filename_portion[0] = 0;
  379. }
  380. //
  381. // Create the new excel workbook based on this template
  382. //
  383. StringClass template_path = Make_Path (path, "renegade.xlt");
  384. ExcelClass::New_Workbook (template_path);
  385. //
  386. // Loop over all the strings in the database
  387. //
  388. int count = TranslateDBClass::Get_Object_Count ();
  389. for (int index = 0; index < count; index ++) {
  390. TDBObjClass *object = TranslateDBClass::Get_Object (index);
  391. if (object != NULL && object->As_StringTwiddlerClass () == NULL) {
  392. //
  393. // Get the data for this string that we want to export
  394. //
  395. const StringClass &string = object->Get_English_String ();
  396. const StringClass &string_id = object->Get_ID_Desc ();
  397. int sound_preset_id = object->Get_Sound_ID ();
  398. int category_id = object->Get_Category_ID ();
  399. const WideStringClass &foreign_string = object->Get_String (lang_id);
  400. //
  401. // Dig out the filename from the sound object
  402. //
  403. WideStringClass wide_sound_filename;
  404. WideStringClass wide_sound_preset_name;
  405. AudibleSoundDefinitionClass *sound_def = (AudibleSoundDefinitionClass *)DefinitionMgrClass::Find_Definition (sound_preset_id, false);
  406. if (sound_def != NULL) {
  407. wide_sound_preset_name.Convert_From (sound_def->Get_Name ());
  408. CString ascii_filename = ::Get_Filename_From_Path (sound_def->Get_Filename ());
  409. wide_sound_filename.Convert_From ((const char *)ascii_filename);
  410. }
  411. //
  412. // Lookup the category name
  413. //
  414. WideStringClass category_name;
  415. TDBCategoryClass *category = TranslateDBClass::Find_Category (category_id);
  416. if (category != NULL) {
  417. category_name.Convert_From (category->Get_Name ());
  418. }
  419. //
  420. // Convert the data to wide character format
  421. //
  422. WideStringClass wide_string;
  423. WideStringClass wide_string_id;
  424. wide_string.Convert_From (string);
  425. wide_string_id.Convert_From (string_id);
  426. //
  427. // Convert any newline characters to string literals
  428. //
  429. Convert_Newline_To_Chars (wide_string);
  430. //
  431. // Put this data into the cells
  432. //
  433. ExcelClass::Set_String (index + 1, COL_CATEGORY_NAME, category_name);
  434. ExcelClass::Set_String (index + 1, COL_STRING_ID, wide_string_id);
  435. ExcelClass::Set_String (index + 1, COL_SOUND_FILENAME, wide_sound_filename);
  436. ExcelClass::Set_String (index + 1, COL_ENGLISH_TEXT, wide_string);
  437. ExcelClass::Set_String (index + 1, COL_SOUND_PRESET_NAME,wide_sound_preset_name);
  438. if (lang_id != TranslateDBClass::LANGID_ENGLISH && object->Contains_Translation (lang_id)) {
  439. ExcelClass::Set_String (index + 1, COL_TRANSLATED_TEXT, foreign_string);
  440. }
  441. }
  442. }
  443. //
  444. // Save our changes
  445. //
  446. ExcelClass::Save_Workbook (filename);
  447. ExcelClass::Shutdown ();
  448. return ;
  449. }
  450. /////////////////////////////////////////////////////////////////////////
  451. //
  452. // Import_From_Translation
  453. //
  454. /////////////////////////////////////////////////////////////////////////
  455. void
  456. StringsMgrClass::Import_From_Translation (const char *filename, uint32 lang_id)
  457. {
  458. CWaitCursor wait_cursor;
  459. if (ExcelClass::Initialize () == false) {
  460. ::MessageBox (::AfxGetMainWnd ()->m_hWnd, "Cannot Initialize Excel, this feature requires Excel installed on the machine.", "Export Error", MB_ICONERROR | MB_OK);
  461. return ;
  462. }
  463. if (Check_Out () == false) {
  464. return ;
  465. }
  466. //
  467. // Open the workbook
  468. //
  469. ExcelClass::Open_Workbook (filename);
  470. //
  471. // Keep reading until we don't have any more data to read
  472. //
  473. bool keep_going = true;
  474. for (int index = 0; keep_going; index ++) {
  475. //
  476. // Read these fields of data
  477. //
  478. WideStringClass category_name;
  479. WideStringClass string_id;
  480. WideStringClass english_string;
  481. WideStringClass string;
  482. WideStringClass preset_name;
  483. ExcelClass::Get_String (index + 1, COL_CATEGORY_NAME, category_name);
  484. ExcelClass::Get_String (index + 1, COL_STRING_ID, string_id);
  485. ExcelClass::Get_String (index + 1, COL_ENGLISH_TEXT, english_string);
  486. ExcelClass::Get_String (index + 1, COL_TRANSLATED_TEXT, string);
  487. ExcelClass::Get_String (index + 1, COL_SOUND_PRESET_NAME,preset_name);
  488. //
  489. // Convert any typed newline literals "\n" to characters '\n'
  490. //
  491. Convert_Chars_To_Newline (english_string);
  492. Convert_Chars_To_Newline (string);
  493. Apply_Characteristics (english_string, string);
  494. //
  495. // Did we find the data?
  496. //
  497. if (string_id.Is_Empty ()) {
  498. keep_going = false;
  499. } else {
  500. StringClass ascii_string_id;
  501. string_id.Convert_To (ascii_string_id);
  502. //
  503. // Find or add this object to our database
  504. //
  505. TDBObjClass *object = TranslateDBClass::Find_Object (ascii_string_id);
  506. if ((object == NULL) && (lang_id == TranslateDBClass::LANGID_ENGLISH)) {
  507. object = new TDBObjClass;
  508. object->Set_ID_Desc (ascii_string_id);
  509. TranslateDBClass::Add_Object (object);
  510. }
  511. if (object != NULL) {
  512. //
  513. // Set the string for this language
  514. //
  515. if (lang_id != TranslateDBClass::LANGID_ENGLISH) {
  516. object->Set_String (lang_id, string);
  517. } else {
  518. object->Set_String (TranslateDBClass::LANGID_ENGLISH, english_string);
  519. }
  520. //
  521. // Find or add the category
  522. //
  523. StringClass ascii_category_name;
  524. category_name.Convert_To (ascii_category_name);
  525. TDBCategoryClass *category = TranslateDBClass::Find_Category (ascii_category_name);
  526. if (category == NULL && ascii_category_name.Get_Length () > 0) {
  527. category = new TDBCategoryClass;
  528. category->Set_Name (ascii_category_name);
  529. TranslateDBClass::Add_Category (category, true);
  530. }
  531. //
  532. // Set the category
  533. //
  534. if (category != NULL) {
  535. object->Set_Category_ID (category->Get_ID ());
  536. }
  537. //
  538. // Find the sound preset
  539. //
  540. StringClass ascii_preset_name;
  541. preset_name.Convert_To (ascii_preset_name);
  542. DefinitionClass *definition = DefinitionMgrClass::Find_Typed_Definition (ascii_preset_name, CLASSID_SOUND, false);
  543. if (definition != NULL) {
  544. object->Set_Sound_ID (definition->Get_ID ());
  545. }
  546. }
  547. }
  548. }
  549. //
  550. // Let the user know how many strings were imported
  551. //
  552. CString message;
  553. message.Format ("Successfully imported %d strings.", index);
  554. ::MessageBox (::AfxGetMainWnd ()->m_hWnd, message, "String Import", MB_ICONEXCLAMATION | MB_OK);
  555. //
  556. // Close Excel and save the changes to the database
  557. //
  558. ExcelClass::Shutdown ();
  559. Save_Translation_Database ();
  560. Check_In ();
  561. return ;
  562. }
  563. /////////////////////////////////////////////////////////////////////////////
  564. //
  565. // Convert_Newline_To_Chars
  566. //
  567. /////////////////////////////////////////////////////////////////////////////
  568. void
  569. StringsMgrClass::Convert_Newline_To_Chars (WideStringClass &string)
  570. {
  571. WideStringClass retval;
  572. //
  573. // Take a guess as to how large to make the final string
  574. //
  575. int count = string.Get_Length ();
  576. //
  577. // Copy characters between the strings
  578. //
  579. for (int index = 0; index < count; index ++) {
  580. if (string[index] == L'\n') {
  581. retval += L"\\n";
  582. } else if (string[index] == L'\t') {
  583. retval += L"\\t";
  584. } else {
  585. retval += string[index];
  586. }
  587. }
  588. string = retval;
  589. return ;
  590. }
  591. /////////////////////////////////////////////////////////////////////////////
  592. //
  593. // Convert_Chars_To_Newline
  594. //
  595. /////////////////////////////////////////////////////////////////////////////
  596. void
  597. StringsMgrClass::Convert_Chars_To_Newline (WideStringClass &string)
  598. {
  599. WideStringClass retval;
  600. //
  601. // Take a guess as to how large to make the final string
  602. //
  603. int count = string.Get_Length ();
  604. //
  605. // Copy characters between the strings
  606. //
  607. for (int index = 0; index < count; index ++) {
  608. if (index + 1 < count && string[index] == L'\\' && string[index + 1] == L'n') {
  609. retval += L'\n';
  610. index ++;
  611. } else if (index + 1 < count && string[index] == L'\\' && string[index + 1] == L't') {
  612. retval += L'\t';
  613. index ++;
  614. } else {
  615. retval += string[index];
  616. }
  617. }
  618. string = retval;
  619. return ;
  620. }
  621. /////////////////////////////////////////////////////////////////////////////
  622. //
  623. // Apply_Characteristics
  624. //
  625. /////////////////////////////////////////////////////////////////////////////
  626. void
  627. StringsMgrClass::Apply_Characteristics
  628. (
  629. WideStringClass &english_string,
  630. WideStringClass &translated_string
  631. )
  632. {
  633. int english_len = english_string.Get_Length ();
  634. int trans_len = translated_string.Get_Length ();
  635. if (english_len == 0 || trans_len == 0) {
  636. return ;
  637. }
  638. /*if (english_len > 2 && trans_len > 2) {
  639. //
  640. // Check to see if the english string is commented out
  641. ///
  642. const WCHAR *buffer = english_string;
  643. if (buffer[0] == L'/' && buffer[1] == L'/') {
  644. //
  645. // Do we need to comment out the translated string as well?
  646. //
  647. const WCHAR *trans_buffer = translated_string;
  648. if (trans_buffer[0] != L'/' || trans_buffer[1] != L'/') {
  649. //
  650. // Prepend the forward slashes
  651. //
  652. WideStringClass temp_string = L"//";
  653. temp_string += translated_string;
  654. translated_string = temp_string;
  655. trans_len = translated_string.Get_Length ();
  656. }
  657. }
  658. }*/
  659. //
  660. // Concatenate a '\n' onto the end of the translated string, if
  661. // there's one at the end of the english string
  662. //
  663. const WCHAR *buffer = english_string;
  664. if (buffer[english_len - 1] == L'\n') {
  665. const WCHAR *trans_buffer = translated_string;
  666. if (trans_buffer[trans_len - 1] != L'\n') {
  667. translated_string += L"\n";
  668. }
  669. }
  670. return ;
  671. }