This repository has been archived on 2025-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
CnC_Renegade/Code/Tools/LevelEdit/rcstringextractor.cpp

324 lines
8.1 KiB
C++

/*
** 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 <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** 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/Tools/LevelEdit/rcstringextractor.cpp $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 10/29/01 11:08a $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "stdafx.h"
#include "rcstringextractor.h"
#include "translatedb.h"
#include "stringsmgr.h"
#include "textfile.h"
//////////////////////////////////////////////////////////////////////
//
// RCStringExtractorClass
//
//////////////////////////////////////////////////////////////////////
RCStringExtractorClass::RCStringExtractorClass (void) :
CategoryIndex (0)
{
return;
}
//////////////////////////////////////////////////////////////////////
//
// Find_String
//
//////////////////////////////////////////////////////////////////////
bool
RCStringExtractorClass::Find_String
(
StringClass & line,
const char * keyword,
const char * replacement,
StringClass & contents
)
{
bool retval = false;
StringClass new_line = line;
//
// Did we find the keyword?
//
char *buffer = ::strstr (new_line, keyword);
if (buffer != NULL) {
buffer += ::lstrlen (keyword);
//
// Skip to the start of the string
//
bool found_start = false;
while (buffer[0] != 0) {
if (buffer[0] == '\"') {
buffer ++;
found_start = true;
break;
}
buffer ++;
}
if (found_start) {
//
// Skip past any format specifiers
//
if (buffer[0] == '%') {
buffer += 2;
}
//
// Record the start and end of the string
//
bool found_end = false;
char *start = buffer;
while (buffer[0] != 0) {
if (buffer[0] == '\"') {
found_end = true;
break;
}
buffer ++;
}
if (found_end) {
char *end = buffer;
//
// Return the contents to the caller
//
end[0] = 0;
contents = start;
if (contents.Get_Length () > 0) {
//
// Check to ensure this isn't already a translation string
//
if (::strstr (contents, "IDS_") == NULL) {
//
// Now fill in the replacement
//
start[0] = 0;
line = new_line.Peek_Buffer ();
line += replacement;
line += "\"";
line += end + 1;
retval = true;
}
}
}
}
}
return retval;
}
//////////////////////////////////////////////////////////////////////
//
// Process_Line
//
//////////////////////////////////////////////////////////////////////
void
RCStringExtractorClass::Process_Line (StringClass &line, int &current_index)
{
StringClass contents;
const char *KEYWORDS[] =
{
"CAPTION",
"LTEXT",
"PUSHBUTTON",
"CONTROL",
"RTEXT",
"CTEXT"
};
const int KEYWORD_COUNT = sizeof (KEYWORDS) / sizeof (const char *);
//
// Make a string identifier from the prefix and the current index
//
StringClass string_id;
string_id.Format ("%s%.3d", Prefix.Peek_Buffer (), current_index);
//
// Check to see if this line is one of the ones we need to process
//
for (int index = 0; index < KEYWORD_COUNT; index ++) {
if (Find_String (line, KEYWORDS[index], string_id, contents)) {
//
// Create a new translation DB entry for this string
//
TDBObjClass *new_obj = new TDBObjClass;
new_obj->Set_English_String (contents);
new_obj->Set_ID_Desc (string_id);
new_obj->Set_Category_ID (CategoryIndex);
//
// Add the new object to the database
//
TranslateDBClass::Add_Object (new_obj);
current_index ++;
break;
}
}
return ;
}
//////////////////////////////////////////////////////////////////////////
//
// Set_Src_RC_Filename
//
//////////////////////////////////////////////////////////////////////////
void
RCStringExtractorClass::Set_Src_RC_Filename (const char *full_path)
{
SrcFilename = full_path;
DestFilename = SrcFilename + "_extracted";
return ;
}
//////////////////////////////////////////////////////////////////////////
//
// Extract_Strings
//
//////////////////////////////////////////////////////////////////////////
void
RCStringExtractorClass::Extract_Strings (void)
{
//
// Check out the strings database
//
if (StringsMgrClass::Check_Out ()) {
CategoryIndex = 0;
//
// Try to find the category these strings are to be imported into
//
TDBCategoryClass *category = TranslateDBClass::Find_Category (CategoryName);
if (category != NULL) {
CategoryIndex = category->Get_ID ();
}
//
// Try to open the .RC file
//
TextFileClass file (SrcFilename);
TextFileClass output_file (DestFilename);
if (file.Open (RawFileClass::READ) && output_file.Open (RawFileClass::WRITE)) {
//
// Determine where to start our numbering scheme
//
int current_index = Find_Starting_Index ();
//
// Read each line from the file
//
StringClass curr_line;
while (file.Read_Line (curr_line)) {
Process_Line (curr_line, current_index);
curr_line += "\r\n";
output_file.Write (curr_line, ::lstrlen (curr_line));
}
//
// Close the files
//
file.Close ();
output_file.Close ();
}
//
// Save the translation database and check it back into VSS
//
StringsMgrClass::Save_Translation_Database ();
StringsMgrClass::Check_In ();
}
return ;
}
//////////////////////////////////////////////////////////////////////////
//
// Find_Starting_Index
//
//////////////////////////////////////////////////////////////////////////
int
RCStringExtractorClass::Find_Starting_Index (void)
{
int max_index = 0;
int prefix_len = Prefix.Get_Length ();
//
// Loop over all the objects in the translation database
//
int count = TranslateDBClass::Get_Object_Count ();
for (int index = 0; index < count; index ++) {
TDBObjClass *obj = TranslateDBClass::Get_Object (index);
if (obj != NULL) {
//
// Is this one of the strings we care about?
//
const StringClass &string_desc = obj->Get_ID_Desc ();
if (::strnicmp (Prefix, string_desc, prefix_len) == 0) {
//
// Check to see if this is the largest index we've found yet
//
const char *suffix = (string_desc.Peek_Buffer () + prefix_len);
int number = ::atoi (suffix);
max_index = max (number, max_index);
}
}
}
return max_index + 1;
}