/* ** Command & Conquer Renegade(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ /*********************************************************************************************** *** 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 *** *********************************************************************************************** * * * Project Name : LevelEdit * * * * $Archive:: /Commando/Code/wwtranslatedb/translatedb.cpp $* * * * Author:: Patrick Smith * * * * $Modtime:: 1/28/02 4:05p $* * * * $Revision:: 18 $* * * *---------------------------------------------------------------------------------------------* * Functions: * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #include "translatedb.h" #include #include #include "persist.h" #include "persistfactory.h" #include "chunkio.h" #include "translatedbids.h" #include "rawfile.h" #include "textfile.h" #include "tdbcategories.h" #include "definition.h" #include "definitionmgr.h" #include "definitionclassids.h" /////////////////////////////////////////////////////////////////////// // Local prototypes /////////////////////////////////////////////////////////////////////// static int Build_List_From_String (const char *buffer, const char *delimiter, StringClass **string_list); /////////////////////////////////////////////////////////////////////// // Global singleton instance /////////////////////////////////////////////////////////////////////// TranslateDBClass _TheTranslateDB; /////////////////////////////////////////////////////////////////////// // Static member initialization /////////////////////////////////////////////////////////////////////// TDB_OBJ_LIST TranslateDBClass::m_ObjectList; HashTemplateClass TranslateDBClass::m_ObjectHash; TDB_CATEGORY_LIST TranslateDBClass::m_CategoryList; uint32 TranslateDBClass::m_VersionNumber = 100; uint32 TranslateDBClass::m_LanguageID = TranslateDBClass::LANGID_ENGLISH; bool TranslateDBClass::IsSingleLanguageExport = false; TranslateDBClass::FILTER_OPT TranslateDBClass::FilterType = FILTER_DISABLED; uint32 TranslateDBClass::FilterCategoryID = 0xFFFFFFFF; /////////////////////////////////////////////////////////////////////// // Constants /////////////////////////////////////////////////////////////////////// enum { CHUNKID_VARIABLES = 0x07141200, CHUNKID_OBJECTS, CHUNKID_CATEGORIES }; enum { VARID_VERSION_NUMBER = 0x01, VARID_LANGUAGE_ID }; const WCHAR * STRING_NOT_FOUND = L"TDBERR"; const char * ENGLISH_STRING_NOT_FOUND = "TDBERR"; /////////////////////////////////////////////////////////////////////// // // Chunk_ID // /////////////////////////////////////////////////////////////////////// uint32 TranslateDBClass::Chunk_ID (void) const { return CHUNKID_TRANSLATE_DB; } /////////////////////////////////////////////////////////////////////// // // Initialize // /////////////////////////////////////////////////////////////////////// void TranslateDBClass::Initialize (void) { m_ObjectList.Set_Growth_Step (1000); return ; } /////////////////////////////////////////////////////////////////////// // // Shutdown // /////////////////////////////////////////////////////////////////////// void TranslateDBClass::Shutdown (void) { Free_Objects (); Free_Categories (); return ; } /////////////////////////////////////////////////////////////////////// // // Free_Categories // /////////////////////////////////////////////////////////////////////// void TranslateDBClass::Free_Categories (void) { // // Loop over and free all the translation categories // for (int index = 0; index < m_CategoryList.Count (); index ++) { TDBCategoryClass *category = m_CategoryList[index]; if (category != NULL) { delete category; } } m_CategoryList.Delete_All (); return ; } /////////////////////////////////////////////////////////////////////// // // Free_Objects // /////////////////////////////////////////////////////////////////////// void TranslateDBClass::Free_Objects (void) { // // Loop over and free all the translation objects // for (int index = 0; index < m_ObjectList.Count (); index ++) { TDBObjClass *translate_obj = m_ObjectList[index]; if (translate_obj != NULL) { delete translate_obj; } } m_ObjectList.Delete_All (); // Remove the stuff from the hash table as well.. m_ObjectHash.Remove_All(); return ; } /////////////////////////////////////////////////////////////////////// // // Contains_Data // /////////////////////////////////////////////////////////////////////// bool TranslateDBClass::Contains_Data (void) const { return true; } /////////////////////////////////////////////////////////////////////// // // Save // /////////////////////////////////////////////////////////////////////// bool TranslateDBClass::Save (ChunkSaveClass &csave) { bool retval = true; csave.Begin_Chunk (CHUNKID_VARIABLES); WRITE_MICRO_CHUNK (csave, VARID_VERSION_NUMBER, m_VersionNumber); WRITE_MICRO_CHUNK (csave, VARID_LANGUAGE_ID, m_LanguageID); csave.End_Chunk (); csave.Begin_Chunk (CHUNKID_CATEGORIES); // // Loop over and save all the translation categories // for (int index = 0; index < m_CategoryList.Count (); index ++) { TDBCategoryClass *category = m_CategoryList[index]; // // Save this category // if (category != NULL) { csave.Begin_Chunk (category->Get_Factory ().Chunk_ID ()); category->Get_Factory ().Save (csave, category); csave.End_Chunk (); } } csave.End_Chunk (); csave.Begin_Chunk (CHUNKID_OBJECTS); // // Loop over and save all the translation objects // for (index = 0; index < m_ObjectList.Count (); index ++) { TDBObjClass *translate_obj = m_ObjectList[index]; // // Save this translation object // if (translate_obj != NULL) { // // Check to ensure this category isn't filtered out... // bool is_equal = (translate_obj->Get_Category_ID () == FilterCategoryID); if ( FilterType == FILTER_DISABLED || (FilterType == FILTER_IF_EQUAL && is_equal == false) || (FilterType == FILTER_IF_NOT_EQUAL && is_equal)) { csave.Begin_Chunk (translate_obj->Get_Factory ().Chunk_ID ()); translate_obj->Get_Factory ().Save (csave, translate_obj); csave.End_Chunk (); } } } csave.End_Chunk (); return retval; } /////////////////////////////////////////////////////////////////////// // // Load // /////////////////////////////////////////////////////////////////////// bool TranslateDBClass::Load (ChunkLoadClass &cload) { Free_Objects (); Free_Categories (); bool retval = true; while (cload.Open_Chunk ()) { switch (cload.Cur_Chunk_ID ()) { // // Load all the presets from this chunk // case CHUNKID_VARIABLES: retval &= Load_Variables (cload); break; case CHUNKID_OBJECTS: retval &= Load_Objects (cload); break; case CHUNKID_CATEGORIES: retval &= Load_Categories (cload); break; } cload.Close_Chunk (); } Validate_Data (); return retval; } /////////////////////////////////////////////////////////////////////// // // Load_Categories // /////////////////////////////////////////////////////////////////////// bool TranslateDBClass::Load_Categories (ChunkLoadClass &cload) { bool retval = true; while (cload.Open_Chunk ()) { // // Load this object from the chunk (if possible) // PersistFactoryClass *factory = SaveLoadSystemClass::Find_Persist_Factory (cload.Cur_Chunk_ID ()); if (factory != NULL) { TDBCategoryClass *category = (TDBCategoryClass *)factory->Load (cload); if (category != NULL) { Add_Category (category, false); } } cload.Close_Chunk (); } return retval; } /////////////////////////////////////////////////////////////////////// // // Load_Objects // /////////////////////////////////////////////////////////////////////// bool TranslateDBClass::Load_Objects (ChunkLoadClass &cload) { bool retval = true; while (cload.Open_Chunk ()) { // // Load this object from the chunk (if possible) // PersistFactoryClass *factory = SaveLoadSystemClass::Find_Persist_Factory (cload.Cur_Chunk_ID ()); if (factory != NULL) { TDBObjClass *translate_obj = (TDBObjClass *)factory->Load (cload); if (translate_obj != NULL) { Add_Object (translate_obj); } } cload.Close_Chunk (); } return retval; } /////////////////////////////////////////////////////////////////////// // // Load_Variables // /////////////////////////////////////////////////////////////////////// bool TranslateDBClass::Load_Variables (ChunkLoadClass &cload) { bool retval = true; while (cload.Open_Micro_Chunk ()) { switch (cload.Cur_Micro_Chunk_ID ()) { READ_MICRO_CHUNK (cload, VARID_VERSION_NUMBER, m_VersionNumber); READ_MICRO_CHUNK (cload, VARID_LANGUAGE_ID, m_LanguageID); } cload.Close_Micro_Chunk (); } return retval; } /////////////////////////////////////////////////////////////////////// // // Validate_Data // /////////////////////////////////////////////////////////////////////// void TranslateDBClass::Validate_Data (void) { if (m_CategoryList.Count () == 0) { // // Create the default category // TDBCategoryClass *category = new TDBCategoryClass; category->Set_Name ("Default"); m_CategoryList.Add (category); } return ; } /////////////////////////////////////////////////////////////////////// // // Export_Table // /////////////////////////////////////////////////////////////////////// void TranslateDBClass::Export_Table (const char *filename) { // // Create the file // HANDLE file = ::CreateFile (filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0L, NULL); WWASSERT (file != INVALID_HANDLE_VALUE); if (file != INVALID_HANDLE_VALUE) { TextFileClass file_obj; file_obj.Attach (file); // // Loop over all the translation objects and write a tab delimited // entry for each one // for (int index = 0; index < m_ObjectList.Count (); index ++) { TDBObjClass *object = m_ObjectList[index]; if (object != NULL && object->As_StringTwiddlerClass () == NULL) { StringClass english_string = object->Get_English_String (); int length = english_string.Get_Length (); for (int index = 0; index < length; index ++) { if (english_string[index] == '\n') { english_string[index] = ' '; } } // // Lookup the string's category // StringClass category_name; TDBCategoryClass *category = Find_Category (object->Get_Category_ID ()); if (category != NULL) { category_name = category->Get_Name (); } // // Lookup the string's sound preset // StringClass sound_preset_name; DefinitionClass *definition = DefinitionMgrClass::Find_Definition (object->Get_Sound_ID (), false); if (definition != NULL) { sound_preset_name = definition->Get_Name (); } // // Write a tab delimited entry for this object // StringClass text_entry; text_entry = category_name; text_entry += "\t"; text_entry += object->Get_ID_Desc (); text_entry += "\t"; text_entry += english_string; text_entry += "\t"; text_entry += sound_preset_name; file_obj.Write_Line (text_entry); } } // // Close the file // file_obj.Detach (); ::CloseHandle (file); } return ; } /////////////////////////////////////////////////////////////////////// // // Export_C_Header // /////////////////////////////////////////////////////////////////////// void TranslateDBClass::Export_C_Header (const char *filename) { // // Create the file // HANDLE file = ::CreateFile (filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0L, NULL); WWASSERT (file != INVALID_HANDLE_VALUE); if (file != INVALID_HANDLE_VALUE) { TextFileClass file_obj; file_obj.Attach (file); // // Wtite the 'C' style header framework // file_obj.Write_Line ("#if defined(_MSC_VER)"); file_obj.Write_Line ("#pragma once"); file_obj.Write_Line ("#endif"); file_obj.Write_Line (""); file_obj.Write_Line ("#ifndef __STRING_IDS_H"); file_obj.Write_Line ("#define __STRING_IDS_H"); file_obj.Write_Line (""); StringClass version_line; version_line.Format ("#define STRINGS_VER %d", m_VersionNumber); file_obj.Write_Line (version_line); file_obj.Write_Line (""); file_obj.Write_Line ("// TRANSLATEDB: Begin ID Block"); // // Loop over all the translation objects and write a #define to the // header file for each one... // for (int index = 0; index < m_ObjectList.Count (); index ++) { TDBObjClass *object = m_ObjectList[index]; if (object != NULL) { // // Write a #define for this object's ID // StringClass id_entry; id_entry.Format ("#define %s %d", (const char *)object->Get_ID_Desc (), object->Get_ID ()); file_obj.Write_Line (id_entry); } } file_obj.Write_Line ("// TRANSLATEDB: End ID Block"); file_obj.Write_Line (""); file_obj.Write_Line ("#endif //__STRING_IDS_H"); // // Close the file // file_obj.Detach (); ::CloseHandle (file); } return ; } /////////////////////////////////////////////////////////////////////// // // Import_C_Header // /////////////////////////////////////////////////////////////////////// void TranslateDBClass::Import_C_Header (const char *filename) { // // Create the file // HANDLE file = ::CreateFile (filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0L, NULL); WWASSERT (file != INVALID_HANDLE_VALUE); if (file != INVALID_HANDLE_VALUE) { TextFileClass file_obj; file_obj.Attach (file); StringClass line; bool found_id_block = false; // // Look for the start of the ID block // while (found_id_block == false && file_obj.Read_Line (line)) { found_id_block = (line.Compare_No_Case ("// TRANSLATEDB: Begin ID Block") == 0); } if (found_id_block) { // // Read each ID define from the header file // bool found_end_block = false; while (found_end_block == false && file_obj.Read_Line (line)) { if (::strnicmp (line, "#define ", 8) == 0) { // // Break the #define into its parts // int word_breaks[4] = { 0 }; int curr_break = 0; // // Find out where each word begins and ends // int count = line.Get_Length (); for (int index = 8; curr_break < 4 && index < count; index ++) { bool is_whitespace = (line[index] == ' ' || line[index] == '\t'); if (is_whitespace == (curr_break & 1) || index == count - 1) { word_breaks[curr_break ++] = index; } } // // Did we encounter the right number of words? // if (curr_break == 4) { // // Isolate the words // char id_desc_text[64] = { 0 }; char id_text[64] = { 0 }; ::strncpy (id_desc_text, line.Peek_Buffer () + word_breaks[0], word_breaks[1] - word_breaks[0]); ::strncpy (id_text, line.Peek_Buffer () + word_breaks[2], word_breaks[3] - word_breaks[2]); // // Convert the ID string to a number // uint32 id = ::atoi (id_text); // // Do we already have this object? // TDBObjClass *object = Find_Object (id); if (object == NULL) { object = Find_Object (id_desc_text); if (object == NULL) { // // If we didn't already have this object, then create // a new object and add it to the system // object = new TDBObjClass; object->Set_ID_Desc (id_desc_text); Add_Object (object); } } } } else { // // Check for block-end conditions // found_end_block = (line.Compare_No_Case ("// TRANSLATEDB: End ID Block") == 0); } } } // // Close the file // file_obj.Detach (); ::CloseHandle (file); } return ; } /////////////////////////////////////////////////////////////////////// // // Get_Object_Count // /////////////////////////////////////////////////////////////////////// int TranslateDBClass::Get_Object_Count (void) { return m_ObjectList.Count (); } /////////////////////////////////////////////////////////////////////// // // Get_Object // /////////////////////////////////////////////////////////////////////// TDBObjClass * TranslateDBClass::Get_Object (int index) { TDBObjClass *object = NULL; WWASSERT (index >= 0 && index < m_ObjectList.Count ()); if (index >= 0 && index < m_ObjectList.Count ()) { object = m_ObjectList[index]; } return object; } /////////////////////////////////////////////////////////////////////// // // Find_Unique_ID // /////////////////////////////////////////////////////////////////////// uint32 TranslateDBClass::Find_Unique_ID (void) { uint32 new_id = ID_MIN + m_ObjectList.Count (); // // Return the 'id' of the first empty slot in the list // for (int index = 0; index < m_ObjectList.Count (); index ++) { if (m_ObjectList[index] == NULL) { new_id = (ID_MIN + index); break; } } return new_id; } /////////////////////////////////////////////////////////////////////// // // Add_Category // /////////////////////////////////////////////////////////////////////// TDBCategoryClass * TranslateDBClass::Add_Category (const char *name) { // // Create the new category // TDBCategoryClass *category = new TDBCategoryClass; category->Set_Name (name); // // Add the category to our list and return a pointer to the caller // Add_Category (category); return category; } /////////////////////////////////////////////////////////////////////// // // Add_Category // /////////////////////////////////////////////////////////////////////// bool TranslateDBClass::Add_Category (TDBCategoryClass *new_category, bool assign_id) { bool retval = false; WWASSERT (new_category != NULL); if (new_category != NULL) { // // Assign this category an ID (if necessary) // if (assign_id && new_category->Get_ID () == 0) { uint32 new_id = 1; for (int index = 0; index < m_CategoryList.Count (); index ++) { uint32 curr_id = m_CategoryList[index]->Get_ID (); new_id = max (curr_id + 1, new_id); } new_category->Set_ID (new_id); } // // Add the new category to our list // m_CategoryList.Add (new_category); retval = true; } return retval; } /////////////////////////////////////////////////////////////////////// // // Remove_Category // /////////////////////////////////////////////////////////////////////// bool TranslateDBClass::Remove_Category (int index) { bool retval = false; // // Make sure this index is in our range // WWASSERT (index >= 0 && index < m_CategoryList.Count ()); if (index >= 0 && index < m_CategoryList.Count ()) { // // Free the object that was in this slot // TDBCategoryClass *category = m_CategoryList[index]; if (category != NULL) { // // Remove all objects from the category // int category_id = category->Get_ID (); for ( TDBObjClass *object = Get_First_Object (category_id); object != NULL; object = Get_Next_Object (category_id, object)) { object->Set_Category_ID (CATEGORY_DEFAULT); } delete category; } // // Remove the entry from our list // m_CategoryList.Delete (index); retval = true; } return retval; } /////////////////////////////////////////////////////////////////////// // // Add_Object // /////////////////////////////////////////////////////////////////////// bool TranslateDBClass::Add_Object (TDBObjClass *new_obj) { bool retval = false; WWASSERT (new_obj != NULL); if (new_obj != NULL) { // // Try to find an unused ID for the object (if necessary) // if (new_obj->Get_ID () < ID_MIN) { new_obj->Set_ID (Find_Unique_ID ()); } // // Determine where in the list this object should // be inserted // int new_id = new_obj->Get_ID (); int obj_index = new_id - ID_MIN; // // Grow the list up to the number of elements we need // while (m_ObjectList.Count () <= obj_index) { m_ObjectList.Add (NULL); } // // Add the object to our list // m_ObjectList[obj_index] = new_obj; // Insert object to the hash table as well... StringClass lower_case_name(new_obj->Get_ID_Desc(),true); _strlwr(lower_case_name.Peek_Buffer()); m_ObjectHash.Insert(lower_case_name,new_obj); retval = true; } return retval; } /////////////////////////////////////////////////////////////////////// // // Remove_Object // /////////////////////////////////////////////////////////////////////// bool TranslateDBClass::Remove_Object (int index) { bool retval = false; // // Make sure this index is in our range // WWASSERT (index >= 0 && index < m_ObjectList.Count ()); if (index >= 0 && index < m_ObjectList.Count ()) { // // Free the object that was in this slot // TDBObjClass *object = m_ObjectList[index]; if (object != NULL) { // Remove the object from the hash table StringClass lower_case_name(object->Get_ID_Desc(),true); _strlwr(lower_case_name.Peek_Buffer()); m_ObjectHash.Remove(lower_case_name); delete object; } // // Remove the pointer from the list and re-assign IDs // m_ObjectList[index] = NULL; retval = true; } return retval; } ////////////////////////////////////////////////////////////// // // Remove_All // ////////////////////////////////////////////////////////////// void TranslateDBClass::Remove_All (void) { Free_Objects (); return ; } ////////////////////////////////////////////////////////////// // // Get_Version_Number // ////////////////////////////////////////////////////////////// uint32 TranslateDBClass::Get_Version_Number (void) { return m_VersionNumber; } ////////////////////////////////////////////////////////////// // // Update_Version // ////////////////////////////////////////////////////////////// void TranslateDBClass::Update_Version (void) { m_VersionNumber ++; return ; } /////////////////////////////////////////////////////////////////////// // // Get_Category_Count // /////////////////////////////////////////////////////////////////////// int TranslateDBClass::Get_Category_Count (void) { return m_CategoryList.Count (); } /////////////////////////////////////////////////////////////////////// // // Get_Category // /////////////////////////////////////////////////////////////////////// TDBCategoryClass * TranslateDBClass::Get_Category (int index) { TDBCategoryClass *category = NULL; WWASSERT (index >= 0 && index < m_CategoryList.Count ()); if (index >= 0 && index < m_CategoryList.Count ()) { category = m_CategoryList[index]; } return category; } /////////////////////////////////////////////////////////////////////// // // Find_Category // /////////////////////////////////////////////////////////////////////// TDBCategoryClass * TranslateDBClass::Find_Category (uint32 id) { TDBCategoryClass *category = NULL; // // Loop over all the categories until we've found a matching ID // for (int index = 0; index < m_CategoryList.Count (); index ++) { if (m_CategoryList[index]->Get_ID () == id) { category = m_CategoryList[index]; break; } } return category; } /////////////////////////////////////////////////////////////////////// // // Find_Category // /////////////////////////////////////////////////////////////////////// TDBCategoryClass * TranslateDBClass::Find_Category (const char *name) { TDBCategoryClass *category = NULL; // // Loop over all the categories until we've found a matching name // for (int index = 0; index < m_CategoryList.Count (); index ++) { if (m_CategoryList[index]->Get_Name ().Compare_No_Case (name) == 0) { category = m_CategoryList[index]; break; } } return category; } /////////////////////////////////////////////////////////////////////// // // Get_First_Object // /////////////////////////////////////////////////////////////////////// TDBObjClass * TranslateDBClass::Get_First_Object (uint32 category_id) { TDBObjClass *object = NULL; // // Loop over the objects we know about and return the first // one that matches the given category ID // for (int index = 0; index < m_ObjectList.Count (); index ++) { TDBObjClass *curr_obj = m_ObjectList[index]; if (curr_obj != NULL) { // // Does this object belong to the category we are enumerating? // if (curr_obj->Get_Category_ID () == category_id) { object = curr_obj; break; } } } return object; } /////////////////////////////////////////////////////////////////////// // // Get_Next_Object // /////////////////////////////////////////////////////////////////////// TDBObjClass * TranslateDBClass::Get_Next_Object (uint32 category_id, TDBObjClass *curr_obj) { // // Sanity check // if (curr_obj == NULL) { return NULL; } TDBObjClass *object = NULL; // // Determine where in the list to start looking // int start_index = (curr_obj->Get_ID () - ID_MIN) + 1; // // Loop over the objects we know about and return the first // one that matches the given category ID // for (int index = start_index; index < m_ObjectList.Count (); index ++) { TDBObjClass *curr_obj = m_ObjectList[index]; if (curr_obj != NULL) { // // Does this object belong to the category we are enumerating? // if (curr_obj->Get_Category_ID () == category_id) { object = curr_obj; break; } } } return object; } ///////////////////////////////////////////////////////////////////////////// // // Convert_Chars_To_Newline // ///////////////////////////////////////////////////////////////////////////// void Convert_Chars_To_Newline (StringClass &string) { StringClass retval; int count = string.Get_Length (); // // Copy characters between the strings // for (int index = 0; index < count; index ++) { if (index + 1 < count && string[index] == '\\' && string[index + 1] == 'n') { retval += '\n'; index ++; } else { retval += string[index]; } } string = retval; return ; } /////////////////////////////////////////////////////////////////////// // // Import_Strings // /////////////////////////////////////////////////////////////////////// void TranslateDBClass::Import_Strings (const char *filename) { // // Open the file // HANDLE file = ::CreateFile ( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0L, NULL); WWASSERT (file != INVALID_HANDLE_VALUE); if (file != INVALID_HANDLE_VALUE) { // // Attach this file to a text file class for easier parsing // TextFileClass file_obj; file_obj.Attach (file); // // Keep reading data from the file until we've reached the end // of the file or the data becomes corrupt // bool keep_going = true; StringClass line; while (keep_going && file_obj.Read_Line (line)) { // // Convert the string to an array of values // StringClass *value_array = NULL; int value_count = Build_List_From_String (line, "\t", &value_array); // // We can't keep going unless we've got at least 3 columns of information // if (value_count >= 3) { // // Lookup the category this entry belongs to // TDBCategoryClass *category = Find_Category (value_array[0]); // // Create the entry // TDBObjClass *new_obj = new TDBObjClass; new_obj->Set_Category_ID (category ? category->Get_ID () : 0); new_obj->Set_ID_Desc (value_array[1]); // // Set the english string // StringClass english_string = value_array[2]; ::Convert_Chars_To_Newline (english_string); new_obj->Set_English_String (english_string); // // If necessary, lookup the sound definition that goes with this new entry // and plug in its ID. // if (value_count >= 4) { DefinitionClass *definition = DefinitionMgrClass::Find_Typed_Definition (value_array[3], CLASSID_SOUND, false); if (definition != NULL) { new_obj->Set_Sound_ID (definition->Get_ID ()); } } // // Add this object to the database // Add_Object (new_obj); } // // Cleanup // if (value_array != NULL) { delete [] value_array; value_array = NULL; } } } return ; } /////////////////////////////////////////////////////////////////////// // // Build_List_From_String // /////////////////////////////////////////////////////////////////////// int Build_List_From_String ( const char * buffer, const char * delimiter, StringClass ** string_list ) { int count = 0; WWASSERT (buffer != NULL); WWASSERT (delimiter != NULL); WWASSERT (string_list != NULL); if ((buffer != NULL) && (delimiter != NULL) && (string_list != NULL)) { int delim_len = ::strlen (delimiter); // // Determine how many entries there will be in the list // for (const char *entry = buffer; (entry != NULL) && (entry[1] != 0); entry = ::strstr (entry, delimiter)) { // // Move past the current delimiter (if necessary) // if ((::strnicmp (entry, delimiter, delim_len) == 0) && (count > 0)) { entry += delim_len; } // Increment the count of entries count ++; } if (count > 0) { // // Allocate enough StringClass objects to hold all the strings in the list // (*string_list) = new StringClass[count]; // // Parse the string and pull out its entries. // count = 0; for (entry = buffer; (entry != NULL) && (entry[1] != 0); entry = ::strstr (entry, delimiter)) { // // Move past the current delimiter (if necessary) // if ((::strnicmp (entry, delimiter, delim_len) == 0) && (count > 0)) { entry += delim_len; } // // Copy this entry into its own string // StringClass entry_string = entry; char *delim_start = ::strstr (entry_string, delimiter); if (delim_start != NULL) { delim_start[0] = 0; } // // Add this entry to our list // if ((entry_string.Get_Length () > 0) || (count == 0)) { (*string_list)[count++] = entry_string; } } } else if (delim_len > 0) { count = 1; (*string_list) = new StringClass[count]; (*string_list)[0] = buffer; } } // // Return the number of entries in our list // return count; } /////////////////////////////////////////////////////////////////////// // // Set_Export_Filter // /////////////////////////////////////////////////////////////////////// void TranslateDBClass::Set_Export_Filter (FILTER_OPT filter, uint32 category_id) { FilterType = filter; FilterCategoryID = category_id; return ; }