mirror of
https://github.com/electronicarts/CnC_Renegade.git
synced 2025-12-16 15:41:39 -05:00
Initial commit of Command & Conquer Renegade source code.
This commit is contained in:
324
Code/Tools/LevelEdit/rcstringextractor.cpp
Normal file
324
Code/Tools/LevelEdit/rcstringextractor.cpp
Normal file
@@ -0,0 +1,324 @@
|
||||
/*
|
||||
** 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 ¤t_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;
|
||||
}
|
||||
Reference in New Issue
Block a user