| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411 |
- /*
- ** Command & Conquer Generals Zero Hour(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) 2001-2003 Electronic Arts Inc. //
- // //
- ////////////////////////////////////////////////////////////////////////////////
- //----------------------------------------------------------------------------
- //
- // Westwood Studios Pacific.
- //
- // Confidential Information
- // Copyright(C) 2001 - All Rights Reserved
- //
- //----------------------------------------------------------------------------
- //
- // Project: RTS3
- //
- // File name: GameText.cpp
- //
- // Created: 11/07/01
- //
- //----------------------------------------------------------------------------
- //----------------------------------------------------------------------------
- // Includes
- //----------------------------------------------------------------------------
- #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
- #include "GameClient/GameText.h"
- #include "Common/Language.h"
- #include "Common/Registry.h"
- #include "GameClient/LanguageFilter.h"
- #include "Common/Debug.h"
- #include "Common/UnicodeString.h"
- #include "Common/AsciiString.h"
- #include "Common/GlobalData.h"
- #include "Common/File.h"
- #include "Common/FileSystem.h"
- #ifdef _INTERNAL
- // for occasional debugging...
- //#pragma optimize("", off)
- //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
- #endif
- //----------------------------------------------------------------------------
- // Externals
- //----------------------------------------------------------------------------
- #if defined(_DEBUG) || defined(_INTERNAL)
- Bool g_useStringFile = TRUE;
- #endif
- //----------------------------------------------------------------------------
- // Defines
- //----------------------------------------------------------------------------
- #define CSF_ID ( ('C'<<24) | ('S'<<16) | ('F'<<8) | (' ') )
- #define CSF_LABEL ( ('L'<<24) | ('B'<<16) | ('L'<<8) | (' ') )
- #define CSF_STRING ( ('S'<<24) | ('T'<<16) | ('R'<<8) | (' ') )
- #define CSF_STRINGWITHWAVE ( ('S'<<24) | ('T'<<16) | ('R'<<8) | ('W') )
- #define CSF_VERSION 3
- #define STRING_FILE 0
- #define CSF_FILE 1
- #define MAX_UITEXT_LENGTH (10*1024)
- //----------------------------------------------------------------------------
- // Private Types
- //----------------------------------------------------------------------------
- //===============================
- // StringInfo
- //===============================
- struct StringInfo
- {
- AsciiString label;
- UnicodeString text;
- AsciiString speech;
- };
- struct StringLookUp
- {
- AsciiString *label;
- StringInfo *info;
- };
- //===============================
- // CSFHeader
- //===============================
- struct CSFHeader
- {
- Int id;
- Int version;
- Int num_labels;
- Int num_strings;
- Int skip;
- Int langid;
- };
- //===============================
- // struct NoString
- //===============================
- struct NoString
- {
- struct NoString *next;
- UnicodeString text;
- };
- //===============================
- // GameTextManager
- //===============================
- class GameTextManager : public GameTextInterface
- {
- public:
- GameTextManager();
- virtual ~GameTextManager();
- virtual void init( void ); ///< Initlaizes the text system
- virtual void deinit( void ); ///< De-initlaizes the text system
- virtual void update( void ) {}; ///< update text manager
- virtual void reset( void ); ///< Resets the text system
- virtual UnicodeString fetch( const Char *label, Bool *exists = NULL ); ///< Returns the associated labeled unicode text
- virtual UnicodeString fetch( AsciiString label, Bool *exists = NULL ); ///< Returns the associated labeled unicode text
- virtual AsciiStringVec& getStringsWithLabelPrefix(AsciiString label);
- virtual void initMapStringFile( const AsciiString& filename );
- protected:
- Int m_textCount;
- Int m_maxLabelLen;
- Char m_buffer[MAX_UITEXT_LENGTH];
- Char m_buffer2[MAX_UITEXT_LENGTH];
- Char m_buffer3[MAX_UITEXT_LENGTH];
- WideChar m_tbuffer[MAX_UITEXT_LENGTH*2];
-
- StringInfo *m_stringInfo;
- StringLookUp *m_stringLUT;
- Bool m_initialized;
- #if defined(_DEBUG) || defined(_INTERNAL)
- Bool m_jabberWockie;
- Bool m_munkee;
- #endif
- NoString *m_noStringList;
- Int m_useStringFile;
- LanguageID m_language;
- UnicodeString m_failed;
- StringInfo *m_mapStringInfo;
- StringLookUp *m_mapStringLUT;
- Int m_mapTextCount;
- /// m_asciiStringVec will be altered every time that getStringsWithLabelPrefix is called,
- /// so don't simply store a pointer to it.
- AsciiStringVec m_asciiStringVec;
- void stripSpaces ( WideChar *string );
- void removeLeadingAndTrailing ( Char *m_buffer );
- void readToEndOfQuote( File *file, Char *in, Char *out, Char *wavefile, Int maxBufLen );
- void reverseWord ( Char *file, Char *lp );
- void translateCopy( WideChar *outbuf, Char *inbuf );
- Bool getStringCount( const Char *filename, Int& textCount );
- Bool getCSFInfo ( const Char *filename );
- Bool parseCSF( const Char *filename );
- Bool parseStringFile( const char *filename );
- Bool parseMapStringFile( const char *filename );
- Bool readLine( char *buffer, Int max, File *file );
- Char readChar( File *file );
- };
- static int _cdecl compareLUT ( const void *, const void*);
- //----------------------------------------------------------------------------
- // Private Data
- //----------------------------------------------------------------------------
- //----------------------------------------------------------------------------
- // Public Data
- //----------------------------------------------------------------------------
- GameTextInterface *TheGameText = NULL;
- //----------------------------------------------------------------------------
- // Private Prototypes
- //----------------------------------------------------------------------------
- //----------------------------------------------------------------------------
- // Private Functions
- //----------------------------------------------------------------------------
- //----------------------------------------------------------------------------
- // Public Functions
- //----------------------------------------------------------------------------
- //============================================================================
- // CreateGameTextInterface
- //============================================================================
- GameTextInterface* CreateGameTextInterface( void )
- {
- return NEW GameTextManager;
- }
- //============================================================================
- // GameTextManager::GameTextManager
- //============================================================================
- GameTextManager::GameTextManager()
- : m_textCount(0),
- m_maxLabelLen(0),
- m_stringInfo(NULL),
- m_stringLUT(NULL),
- m_initialized(FALSE),
- m_noStringList(NULL),
- #if defined(_DEBUG) || defined(_INTERNAL)
- m_jabberWockie(FALSE),
- m_munkee(FALSE),
- m_useStringFile(g_useStringFile),
- #else
- m_useStringFile(TRUE),
- #endif
- m_mapStringInfo(NULL),
- m_mapStringLUT(NULL),
- m_failed(L"***FATAL*** String Manager failed to initilaize properly")
- {
- // Added By Sadullah Nader
- // Initializations missing and needed
- for(Int i=0; i < MAX_UITEXT_LENGTH; i++)
- {
- m_buffer[i] = 0;
- m_buffer2[i] = 0;
- m_buffer3[i] = 0;
- }
- //
- }
- //============================================================================
- // GameTextManager::~GameTextManager
- //============================================================================
- GameTextManager::~GameTextManager()
- {
- deinit();
- }
- //============================================================================
- // GameTextManager::init
- //============================================================================
- extern const Char *g_strFile;
- extern const Char *g_csfFile;
- void GameTextManager::init( void )
- {
- AsciiString csfFile;
- csfFile.format(g_csfFile, GetRegistryLanguage().str());
- Int format;
- if ( m_initialized )
- {
- return;
- }
- m_initialized = TRUE;
- m_maxLabelLen = 0;
- #if defined(_DEBUG) || defined(_INTERNAL)
- if(TheGlobalData)
- {
- m_jabberWockie = TheGlobalData->m_jabberOn;
- m_munkee = TheGlobalData->m_munkeeOn;
- }
- #endif
- if ( m_useStringFile && getStringCount( g_strFile, m_textCount ) )
- {
- format = STRING_FILE;
- }
- else if ( getCSFInfo ( csfFile.str() ) )
- {
- format = CSF_FILE;
- }
- else
- {
- return;
- }
- if( (m_textCount == 0) )
- {
- return;
- }
- //Allocate StringInfo Array
- m_stringInfo = NEW StringInfo[m_textCount];
- if( m_stringInfo == NULL )
- {
- deinit();
- return;
- }
- if ( format == STRING_FILE )
- {
- if( parseStringFile( g_strFile ) == FALSE )
- {
- deinit();
- return;
- }
- }
- else
- {
- if ( !parseCSF ( csfFile.str() ) )
- {
- deinit();
- return;
- }
- }
- m_stringLUT = NEW StringLookUp[m_textCount];
- StringLookUp *lut = m_stringLUT;
- StringInfo *info = m_stringInfo;
- for ( Int i = 0; i < m_textCount; i++ )
- {
- lut->info = info;
- lut->label = &info->label;
- lut++;
- info++;
- }
- qsort( m_stringLUT, m_textCount, sizeof(StringLookUp), compareLUT );
- UnicodeString ourName = fetch("GUI:Command&ConquerGenerals");
- AsciiString ourNameA;
- ourNameA.translate(ourName); //get ASCII version for Win 9x
- extern HWND ApplicationHWnd; ///< our application window handle
- if (ApplicationHWnd) {
- //Set it twice because Win 9x does not support SetWindowTextW.
- ::SetWindowText(ApplicationHWnd, ourNameA.str());
- ::SetWindowTextW(ApplicationHWnd, ourName.str());
- }
- }
- //============================================================================
- // GameTextManager::deinit
- //============================================================================
- void GameTextManager::deinit( void )
- {
- if( m_stringInfo != NULL )
- {
- delete [] m_stringInfo;
- m_stringInfo = NULL;
- }
- if( m_stringLUT != NULL )
- {
- delete [] m_stringLUT;
- m_stringLUT = NULL;
- }
- m_textCount = 0;
- NoString *noString = m_noStringList;
- DEBUG_LOG(("\n*** Missing strings ***\n"));
- while ( noString )
- {
- DEBUG_LOG(("*** %ls ***\n", noString->text.str()));
- NoString *next = noString->next;
- delete noString;
- noString = next;
- }
- DEBUG_LOG(("*** End missing strings ***\n\n"));
- m_noStringList = NULL;
- m_initialized = FALSE;
- }
- //============================================================================
- // GameTextManager::reset
- //============================================================================
- void GameTextManager::reset( void )
- {
- if( m_mapStringInfo != NULL )
- {
- delete [] m_mapStringInfo;
- m_mapStringInfo = NULL;
- }
- if( m_mapStringLUT != NULL )
- {
- delete [] m_mapStringLUT;
- m_mapStringLUT = NULL;
- }
- }
- //============================================================================
- // GameTextManager::stripSpaces
- //============================================================================
- void GameTextManager::stripSpaces ( WideChar *string )
- {
- WideChar *str, *ptr;
- WideChar ch, last = 0;
- Int skipall = TRUE;
- str = ptr = string;
- while ( (ch = *ptr++) != 0 )
- {
- if ( ch == ' ' )
- {
- if ( last == ' ' || skipall )
- {
- continue;
- }
- }
- if ( ch == '\n' || ch == '\t' )
- {
- // remove last space
- if ( last == ' ' )
- {
- str--;
- }
- skipall = TRUE; // skip all spaces
- last = *str++ = ch;
- continue;
- }
- last = *str++ = ch;
- skipall = FALSE;
- }
- if ( last == ' ' )
- {
- str--;
- }
- *str = 0;
- }
- //============================================================================
- // GameTextManager::removeLeadingAndTrailing
- //============================================================================
- void GameTextManager::removeLeadingAndTrailing ( Char *buffer )
- {
- Char *first, *ptr;
- Char ch;
- ptr = first = buffer;
- while ( (ch = *first) != 0 && iswspace ( ch ))
- {
- first++;
- }
- while ( (*ptr++ = *first++) != 0 );
- ptr -= 2;;
- while ( (ptr > buffer) && (ch = *ptr) != 0 && iswspace ( ch ) )
- {
- ptr--;
- }
- ptr++;
- *ptr = 0;
- }
- //============================================================================
- // GameTextManager::readToEndOfQuote
- //============================================================================
- void GameTextManager::readToEndOfQuote( File *file, Char *in, Char *out, Char *wavefile, Int maxBufLen )
- {
- Int slash = FALSE;
- Int state = 0;
- Int line_start = FALSE;
- Char ch;
- Int ccount = 0;
- Int len = 0;
- Int done = FALSE;
- while ( maxBufLen )
- {
- // get next Char
- if ( in )
- {
- if ( (ch = *in++) == 0 )
- {
- in = NULL; // have exhausted the input m_buffer
- ch = readChar ( file );
- }
- }
- else
- {
- ch = readChar ( file );
- }
- if ( ch == EOF )
- {
- return ;
- }
- if ( ch == '\n' )
- {
- line_start = TRUE;
- slash = FALSE;
- ccount = 0;
- ch = ' ';
- }
- else if ( ch == '\\' && !slash)
- {
- slash = TRUE;
- }
- else if ( ch == '\\' && slash)
- {
- slash = FALSE;
- }
- else if ( ch == '"' && !slash )
- {
- break; // done
- }
- else
- {
- slash = FALSE;
- }
- if ( iswspace ( ch ))
- {
- ch = ' ';
- }
- *out++ = ch;
- maxBufLen--;
- }
- *out = 0;
- while ( !done )
- {
- // get next Char
- if ( in )
- {
- if ( (ch = *in++) == 0 )
- {
- in = NULL; // have exhausted the input m_buffer
- ch = readChar ( file );
- }
- }
- else
- {
- ch = readChar ( file );
- }
- if ( ch == '\n' || ch == EOF )
- {
- break;
- }
- switch ( state )
- {
- case 0:
- if ( iswspace ( ch ) || ch == '=' )
- {
- break;
- }
- state = 1;
- case 1:
- if ( ( ch >= 'a' && ch <= 'z') || ( ch >= 'A' && ch <='Z') || (ch >= '0' && ch <= '9') || ch == '_' )
- {
- *wavefile++ = ch;
- len++;
- break;
- }
- state = 2;
- case 2:
- break;
- }
- }
- *wavefile = 0;
- if ( len )
- {
- if ( ( ch = *(wavefile-1)) >= '0' && ch <= '9' )
- {
- *wavefile++ = 'e';
- *wavefile = 0;
- }
- }
- }
- //============================================================================
- // GameTextManager::reverseWord
- //============================================================================
- void GameTextManager::reverseWord ( Char *file, Char *lp )
- {
- Int first = TRUE;
- Char f, l;
- Int ok = TRUE ;
- while ( ok )
- {
- if ( file >= lp )
- {
- return;
- }
- f = *file;
- l = *lp;
- if ( first )
- {
- if ( f >= 'A' && f <= 'Z' )
- {
- if ( l >= 'a' && l <= 'z' )
- {
- f = (f - 'A') + 'a';
- l = (l - 'a') + 'A';
- }
- }
- first = FALSE;
- }
- *lp-- = f;
- *file++ = l;
- }
- }
- //============================================================================
- // GameTextManager::translateCopy
- //============================================================================
- void GameTextManager::translateCopy( WideChar *outbuf, Char *inbuf )
- {
- Int slash = FALSE;
- #if defined(_DEBUG) || defined(_INTERNAL)
- if ( m_jabberWockie )
- {
- static Char buffer[MAX_UITEXT_LENGTH*2];
- Char *firstLetter = NULL, *lastLetter;
- Char *b = buffer;
- Int formatWord = FALSE;
- Char ch;
- while ( (ch = *inbuf++) != 0 )
- {
- if ( ! (( ch >= 'a' && ch <= 'z') || ( ch >= 'A' && ch <= 'Z' )))
- {
- if ( firstLetter )
- {
- if ( !formatWord )
- {
- lastLetter = b-1;
- reverseWord ( firstLetter, lastLetter );
- }
- firstLetter = NULL;
- formatWord = FALSE;
- }
- *b++ = ch;
- if ( ch == '\\' )
- {
- *b++ = *inbuf++;
- }
- if ( ch == '%' )
- {
- while ( (ch = *inbuf++) != 0 && !( (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')))
- {
- *b++ = ch;
- }
- *b++ = ch;
- }
- }
- else
- {
- if ( !firstLetter )
- {
- firstLetter = b;
- }
- *b++ = ch;
- }
- }
- if ( firstLetter )
- {
- lastLetter = b-1;
- reverseWord ( firstLetter, lastLetter );
- }
- *b++ = 0;
- inbuf = buffer;
- }
- else if( m_munkee )
- {
- wcscpy(outbuf, L"Munkee");
- return;
- }
- #endif
- while( *inbuf != '\0' )
- {
- if( slash == TRUE )
- {
- slash = FALSE;
- switch( *inbuf )
- {
- // in case end of string is reached
- // should never happen!!!
- case '\0':
- return;
- case '\\':
- *outbuf++ = '\\';
- break;
- case '\'':
- *outbuf++ = '\'';
- break;
- case '\"':
- *outbuf++ = '\"';
- break;
- case '\?':
- *outbuf++ = '\?';
- break;
- case 't':
- *outbuf++ = '\t';
- break;
- case 'n':
- *outbuf++ = '\n';
- break;
- default:
- *outbuf++ = *inbuf & 0x00FF;
- break;
- }
- }
- else if( *inbuf != '\\' )
- {
- *outbuf++ = *inbuf & 0x00FF;
- }
- else
- slash = TRUE;
- inbuf++;
- }
- *outbuf= 0;
- }
- //============================================================================
- // GameTextManager::getStringCount
- //============================================================================
- Bool GameTextManager::getStringCount( const char *filename, Int& textCount )
- {
- Int ok = TRUE;
- textCount = 0;
- File *file;
- file = TheFileSystem->openFile(filename, File::READ | File::TEXT);
- DEBUG_LOG(("Looking in %s for string file\n", filename));
-
- if ( file == NULL )
- {
- return FALSE;
- }
- while(ok)
- {
- if( !readLine( m_buffer, sizeof( m_buffer) -1, file ) )
- break;
- removeLeadingAndTrailing ( m_buffer );
- if( m_buffer[0] == '"' )
- {
- Int len = strlen(m_buffer);
- m_buffer[ len ] = '\n';
- m_buffer[ len+1] = 0;
- readToEndOfQuote( file, &m_buffer[1], m_buffer2, m_buffer3, MAX_UITEXT_LENGTH );
- }
- else if( !stricmp( m_buffer, "END") )
- {
- textCount++;
- }
- }
- textCount += 500;
- file->close();
- file = NULL;
- return TRUE;
- }
- //============================================================================
- // GameTextManager::getCSFInfo
- //============================================================================
- Bool GameTextManager::getCSFInfo ( const Char *filename )
- {
- CSFHeader header;
- Int ok = FALSE;
- File *file = TheFileSystem->openFile(filename, File::READ | File::BINARY);
- DEBUG_LOG(("Looking in %s for compiled string file\n", filename));
- if ( file != NULL )
- {
- if ( file->read( &header, sizeof ( header )) == sizeof ( header ) )
- {
- if ( header.id == CSF_ID )
- {
- m_textCount = header.num_labels;
- if ( header.version >= 2 )
- {
- m_language = (LanguageID) header.langid;
- }
- else
- {
- m_language = LANGUAGE_ID_US;
- }
- ok = TRUE;
- }
- }
- file->close();
- file = NULL;
- }
- return ok;
- }
- //============================================================================
- // GameTextManager::parseCSF
- //============================================================================
- Bool GameTextManager::parseCSF( const Char *filename )
- {
- File *file;
- Int id;
- Int len;
- Int listCount = 0;
- Bool ok = FALSE;
- CSFHeader header;
- file = TheFileSystem->openFile(filename, File::READ | File::BINARY);
- if ( file == NULL )
- {
- return FALSE;
- }
- if ( file->read ( &header, sizeof ( CSFHeader)) != sizeof ( CSFHeader) )
- {
- return FALSE;
- }
- while( file->read ( &id, sizeof (id)) == sizeof ( id) )
- {
- Int num;
- Int num_strings;
- if ( id != CSF_LABEL )
- {
- goto quit;
- }
- file->read ( &num_strings, sizeof ( Int ));
- file->read ( &len, sizeof ( Int ) );
- if ( len )
- {
- file->read ( m_buffer, len );
- }
- m_buffer[len] = 0;
- m_stringInfo[listCount].label = m_buffer;
- if ( len > m_maxLabelLen )
- {
- m_maxLabelLen = len;
- }
- num = 0;
- while ( num < num_strings )
- {
- file->read ( &id, sizeof ( Int ) );
- if ( id != CSF_STRING && id != CSF_STRINGWITHWAVE )
- {
- goto quit;
- }
- file->read ( &len, sizeof ( Int ) );
- if ( len )
- {
- file->read ( m_tbuffer, len*sizeof(WideChar) );
- }
- if ( num == 0 )
- {
- // only use the first string found
- m_tbuffer[len] = 0;
-
- {
- WideChar *ptr;
-
- ptr = m_tbuffer;
-
- while ( *ptr )
- {
- *ptr = ~*ptr;
- ptr++;
- }
- }
-
- stripSpaces ( m_tbuffer );
- m_stringInfo[listCount].text = m_tbuffer;
- }
- if ( id == CSF_STRINGWITHWAVE )
- {
- file->read ( &len, sizeof ( Int ) );
- if ( len )
- {
- file->read ( m_buffer, len );
- }
- m_buffer[len] = 0;
- if ( num == 0 && len )
- {
- // only use the first string found
- m_stringInfo[listCount].speech = m_buffer;
- }
- }
- num++;
- }
- listCount++;
- }
- ok = TRUE;
- quit:
- file->close();
- file = NULL;
- return ok;
- }
- //============================================================================
- // GameTextManager::parseStringFile
- //============================================================================
- Bool GameTextManager::parseStringFile( const char *filename )
- {
- Int listCount = 0;
- Int ok = TRUE;
- File *file = TheFileSystem->openFile(filename, File::READ | File::TEXT);
-
- if ( file == NULL )
- {
- return FALSE;
- }
- while( ok )
- {
- Int len;
- if( !readLine( m_buffer, MAX_UITEXT_LENGTH, file ))
- {
- break;
- }
- removeLeadingAndTrailing ( m_buffer );
- if( ( *(unsigned short *)m_buffer == 0x2F2F) || !m_buffer[0]) // 0x2F2F is Hex for //
- continue;
- // make sure label is unique
- for ( Int i = 0; i < listCount; i++ )
- {
- if ( !stricmp ( m_stringInfo[i].label.str(), m_buffer ))
- {
- DEBUG_ASSERTCRASH ( FALSE, ("String label '%s' multiply defined!", m_buffer ));
- }
- }
- m_stringInfo[listCount].label = m_buffer;
- len = strlen ( m_buffer );
- if ( len > m_maxLabelLen )
- {
- m_maxLabelLen = len;
- }
- Bool readString = FALSE;
- while( ok )
- {
- if (!readLine ( m_buffer, sizeof(m_buffer)-1, file ))
- {
- DEBUG_ASSERTCRASH (FALSE, ("Unexpected end of string file"));
- ok = FALSE;
- goto quit;
- }
- removeLeadingAndTrailing ( m_buffer );
- if( m_buffer[0] == '"' )
- {
- len = strlen(m_buffer);
- m_buffer[ len ] = '\n';
- m_buffer[ len+1] = 0;
- readToEndOfQuote( file, &m_buffer[1], m_buffer2, m_buffer3, MAX_UITEXT_LENGTH );
- if ( readString )
- {
- // only one string per label allows
- DEBUG_ASSERTCRASH ( FALSE, ("String label '%s' has more than one string defined!", m_stringInfo[listCount].label.str()));
- }
- else
- {
- // Copy string into new home
- translateCopy( m_tbuffer, m_buffer2 );
- stripSpaces ( m_tbuffer );
-
- m_stringInfo[listCount].text = m_tbuffer ;
- m_stringInfo[listCount].speech = m_buffer3;
- readString = TRUE;
- }
- }
- else if ( !stricmp ( m_buffer, "END" ))
- {
- break;
- }
- }
- listCount++;
- }
- quit:
- file->close();
- file = NULL;
- return ok;
- }
- //============================================================================
- // GameTextManager::initMapStringFile
- //============================================================================
- void GameTextManager::initMapStringFile( const AsciiString& filename )
- {
- m_mapTextCount = 0;
- getStringCount( filename.str(), m_mapTextCount );
- m_mapStringInfo = NEW StringInfo[m_mapTextCount];
- parseMapStringFile( filename.str() );
- m_mapStringLUT = NEW StringLookUp[m_mapTextCount];
- StringLookUp *lut = m_mapStringLUT;
- StringInfo *info = m_mapStringInfo;
- for ( Int i = 0; i < m_mapTextCount; i++ )
- {
- lut->info = info;
- lut->label = &info->label;
- lut++;
- info++;
- }
- qsort( m_mapStringLUT, m_mapTextCount, sizeof(StringLookUp), compareLUT );
- }
- //============================================================================
- // GameTextManager::parseMapStringFile
- //============================================================================
- Bool GameTextManager::parseMapStringFile( const char *filename )
- {
- Int listCount = 0;
- Int ok = TRUE;
- File *file;
- file = TheFileSystem->openFile(filename, File::READ | File::TEXT);
- if ( file == NULL )
- {
- return FALSE;
- }
- while( ok )
- {
- Int len;
- if( !readLine( m_buffer, MAX_UITEXT_LENGTH, file ))
- {
- break;
- }
- removeLeadingAndTrailing ( m_buffer );
- if( ( *(unsigned short *)m_buffer == 0x2F2F) || !m_buffer[0]) // 0x2F2F is Hex for //
- continue;
- // make sure label is unique
- for ( Int i = 0; i < listCount; i++ )
- {
- if ( !stricmp ( m_mapStringInfo[i].label.str(), m_buffer ))
- {
- DEBUG_ASSERTCRASH ( FALSE, ("String label '%s' multiply defined!", m_buffer ));
- }
- }
- m_mapStringInfo[listCount].label = m_buffer;
- len = strlen ( m_buffer );
- if ( len > m_maxLabelLen )
- {
- m_maxLabelLen = len;
- }
- Bool readString = FALSE;
- while( ok )
- {
- if (!readLine ( m_buffer, sizeof(m_buffer)-1, file ))
- {
- DEBUG_ASSERTCRASH (FALSE, ("Unexpected end of string file"));
- ok = FALSE;
- goto quit;
- }
- removeLeadingAndTrailing ( m_buffer );
- if( m_buffer[0] == '"' )
- {
- len = strlen(m_buffer);
- m_buffer[ len ] = '\n';
- m_buffer[ len+1] = 0;
- readToEndOfQuote( file, &m_buffer[1], m_buffer2, m_buffer3, MAX_UITEXT_LENGTH );
- if ( readString )
- {
- // only one string per label allowed
- DEBUG_ASSERTCRASH ( FALSE, ("String label '%s' has more than one string defined!", m_stringInfo[listCount].label.str()));
- }
- else
- {
- // Copy string into new home
- translateCopy( m_tbuffer, m_buffer2 );
- stripSpaces ( m_tbuffer );
- UnicodeString text = UnicodeString(m_tbuffer);
- if (TheLanguageFilter)
- TheLanguageFilter->filterLine(text);
-
- m_mapStringInfo[listCount].text = text;
- m_mapStringInfo[listCount].speech = m_buffer3;
- readString = TRUE;
- }
- }
- else if ( !stricmp ( m_buffer, "END" ))
- {
- break;
- }
- }
- listCount++;
- }
- quit:
- file->close();
- file = NULL;
- return ok;
- }
- //============================================================================
- // *GameTextManager::fetch
- //============================================================================
- UnicodeString GameTextManager::fetch( const Char *label, Bool *exists )
- {
- DEBUG_ASSERTCRASH ( m_initialized, ("String Manager has not been m_initialized") );
- if( m_stringInfo == NULL )
- {
- if( exists )
- *exists = FALSE;
- return m_failed;
- }
- StringLookUp *lookUp;
- StringLookUp key;
- AsciiString lb;
- lb = label;
- key.info = NULL;
- key.label = &lb;
- lookUp = (StringLookUp *) bsearch( &key, (void*) m_stringLUT, m_textCount, sizeof(StringLookUp), compareLUT );
- if ( lookUp == NULL && m_mapStringLUT && m_mapTextCount )
- {
- lookUp = (StringLookUp *) bsearch( &key, (void*) m_mapStringLUT, m_mapTextCount, sizeof(StringLookUp), compareLUT );
- }
- if( lookUp == NULL )
- {
- // string not found
- if( exists )
- *exists = FALSE;
- // See if we already have the missing string
- UnicodeString missingString;
- missingString.format(L"MISSING: '%hs'", label);
- NoString *noString = m_noStringList;
- while ( noString )
- {
- if (noString->text == missingString)
- return missingString;
- noString = noString->next;
- }
- //DEBUG_LOG(("*** MISSING:'%s' ***\n", label));
- // Remember file could have been altered at this point.
- noString = NEW NoString;
- noString->text = missingString;
- noString->next = m_noStringList;
- m_noStringList = noString;
- return noString->text;
- }
- if( exists )
- *exists = TRUE;
- return lookUp->info->text;
- }
- //============================================================================
- // *GameTextManager::fetch
- //============================================================================
- UnicodeString GameTextManager::fetch( AsciiString label, Bool *exists )
- {
- return fetch(label.str(), exists);
- }
- //============================================================================
- // GameTextManager::getStringsWithLabelPrefix
- //============================================================================
- AsciiStringVec& GameTextManager::getStringsWithLabelPrefix(AsciiString label)
- {
- m_asciiStringVec.clear();
- if (m_stringLUT) {
- for (int i = 0; i < m_textCount; ++i) {
- if (strstr(m_stringLUT[i].label->str(), label.str()) == m_stringLUT[i].label->str()) {
- m_asciiStringVec.push_back(*m_stringLUT[i].label);
- }
- }
- }
- if (m_mapStringLUT) {
- for (int i = 0; i < m_mapTextCount; ++i) {
- if (strstr(m_mapStringLUT[i].label->str(), label.str()) == m_mapStringLUT[i].label->str()) {
- m_asciiStringVec.push_back(*m_mapStringLUT[i].label);
- }
- }
- }
- return m_asciiStringVec;
- }
- //============================================================================
- // GameTextManager::readLine
- //============================================================================
- Bool GameTextManager::readLine( char *buffer, Int max, File *file )
- {
- Int ok = FALSE;
- while ( max && file->read( buffer, 1 ) == 1 )
- {
- ok = TRUE;
- if ( *buffer == '\n' )
- {
- break;
- }
- buffer++;
- max--;
- }
- *buffer = 0;
- return ok;
- }
- //============================================================================
- // GameTextManager::readChar
- //============================================================================
- Char GameTextManager::readChar( File *file )
- {
- Char ch;
- if ( file->read( &ch, 1 ) == 1 )
- {
- return ch;
- }
- return 0;
- }
- //============================================================================
- // GameTextManager::compareLUT
- //============================================================================
- static int __cdecl compareLUT ( const void *i1, const void*i2)
- {
- StringLookUp *lut1 = (StringLookUp*) i1;
- StringLookUp *lut2 = (StringLookUp*) i2;
- return stricmp( lut1->label->str(), lut2->label->str());
- }
|