| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669 |
- /*
- ** 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 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 : Setup *
- * *
- * File Name : UTILS.C *
- * *
- * Programmers: Maria del Mar McCready Legg *
- * *
- * Start Date : December 12, 1992 *
- * *
- * Last Update : March 16, 1998 [MML] *
- * *
- *--------------------------------------------------------------------------*
- * Functions: *
- * *
- * Clip_Line_To_Rect -- Clips a line (two points) against a *
- * rectangle, using CS algorithm. *
- * Compute_Code -- computes line clipping bit code for *
- * point & rectangle. *
- * Copy_File -- Copies a file from one dir to another. *
- * Convert_Hex_To_Version -- Converts a hex num obtained from the *
- * Registry, into a string *
- * representation of a version *
- * number ( XX.XX ). *
- * Convert_Version_To_Hex -- Converts a string to an unsigned long. *
- * Convert_To_Version_Format -- Converts version string's "," to "."s *
- * Dialog_Box -- draws a dialog background box *
- * Draw_Box -- Displays a highlighted box. *
- * Fatal -- General purpose fatal error handler. *
- * Get_Version -- Retrieves a version string from a file. *
- * Get_String -- Returns a pointer to the undipped text. *
- * Is_File_Available -- Use both FindFirst to check that CD is *
- * in drive & if File_Exists() to *
- * determine if file is really there. *
- * Pad_With_Zeros -- Adds zeros to the beginning of string. *
- * String_Width -- Calculate with of the string. *
- * Strip_Newlines -- Remove '\r' from string passed in. *
- * TextPtr -- Returns a pointer to the undipped text. *
- * Path_Name_Valid -- Validate that the path has the correct *
- * number of chars between '\' in the *
- * path. *
- * Path_Get_Next_Directory -- Return the next dir path from string. *
- * Path_Add_Back_Slash -- Add a "\\" to the end of the string. *
- * Path_Remove_Back_Slash -- Remove a '\\' at the end of the string. *
- * Path_Trim_Blanks -- Trim lead/trail white spaces off string *
- * Pad_With_Zeros -- Adds zeros to the beginning of string. *
- * Remove_Ending_Spaces -- Remove any blank spaces at end of string*
- * Remove_Spaces -- Remove spaces from string passed in. *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
- #include <io.h>
- #include "args.h"
- #include "assert.h"
- #include "locale_api.h"
- #include "resource.h"
- #include "utils.h"
- #include "winfix.h"
- #include "wnd_file.h"
- #include <winver.h>
- #include <shlwapi.h>
- //#include "resources.h"
- //----------------------------------------------------------------------------
- //
- // Function: Fix_Single_Ampersands()
- //
- // Purpose: To replace each "&" with "&&" for display in a dialog.
- // Some dialogs mistake a single "&" for an accelerator key.
- //
- // Input: pszString - any NULL terminated string.
- //
- // Returns: VOID (returns nothing)
- //
- // Comments: Modifies the characters in pszString.
- //
- //---------------------------------------------------------------------------
- void Fix_Single_Ampersands ( LPSTR pszString, bool upper_case )
- {
- char pszTemp[ MAX_PATH ]; // variable to hold the string passed
- char pszOld[ MAX_PATH ]; // variable to hold the string passed
- char * letter;
- int i = 0;
- lstrcpy((LPSTR)pszOld, (LPSTR)pszString );
- letter = pszOld;
- memset ( pszTemp, '\0', MAX_PATH );
- //----------------------------------------------------------------------
- // While our ptr has not passed the end of the string...
- //----------------------------------------------------------------------
- while (*letter != '\0') {
- if (*letter == '&') {
-
- pszTemp[i++] = '&';
- pszTemp[i++] = '&';
- letter++;
-
- } else {
- if ( upper_case ) {
- pszTemp[i++] = (char) toupper( *( letter++ ));
- } else {
- pszTemp[i++] = *(letter++);
- }
- }
- }
- strcpy((LPSTR)pszString, (LPSTR)pszTemp );
- }
- void Fix_Single_Ampersands ( wchar_t *pszString, bool upper_case )
- {
- wchar_t pszTemp[ MAX_PATH ]; // variable to hold the string passed
- wchar_t pszOld[ MAX_PATH ]; // variable to hold the string passed
- wchar_t *letter;
- int i = 0;
-
- wcscpy( pszOld, pszString );
- letter = pszOld;
- memset ( pszTemp, '\0', MAX_PATH );
- //----------------------------------------------------------------------
- // While our ptr has not passed the end of the string...
- //----------------------------------------------------------------------
- while (*letter != '\0') {
- if (*letter == '&') {
-
- pszTemp[i++] = '&';
- pszTemp[i++] = '&';
- letter++;
-
- } else {
- if ( upper_case ) {
- pszTemp[i++] = (char) toupper( *( letter++ ));
- } else {
- pszTemp[i++] = *(letter++);
- }
- }
- }
- wcscpy( pszString, pszTemp );
- }
- ////////////////UnicodeString Fix_Single_Ampersands( UnicodeString string, bool upper_case)
- ////////////////{
- //////////////// UnicodeString retval;
- ////////////////
- //////////////// Int i = 0;
- //////////////// while (i < string.getLength()) {
- //////////////// if (upper_case) {
- //////////////// retval.concat(toupper(string.getCharAt(i)));
- //////////////// } else {
- //////////////// retval.concat(string.getCharAt(i));
- //////////////// }
- //////////////// if (string.getCharAt(i) == L'&') {
- //////////////// retval.concat(string.getCharAt(i));
- //////////////// }
- //////////////// ++i;
- //////////////// }
- ////////////////
- //////////////// return retval;
- ////////////////}
- //----------------------------------------------------------------------------
- //
- // Function: Fix_Double_Ampersands()
- //
- // Purpose: To replace each "&&" with "&" for display in a dialog.
- // Some dialogs mistake a single "&" for an accelerator key.
- //
- // Input: pszString - any NULL terminated string.
- //
- // Returns: VOID (returns nothing)
- //
- // Comments: Modifies the characters in pszString.
- //
- //---------------------------------------------------------------------------
- void Fix_Double_Ampersands ( LPSTR pszString, bool upper_case )
- {
- char pszTemp[ MAX_PATH ]; // variable to hold the string passed
- char pszOld[ MAX_PATH ]; // variable to hold the string passed
- char *letter;
- int i = 0;
- lstrcpy( (LPSTR)pszOld, (LPSTR)pszString );
- letter = pszOld;
- memset ( pszTemp, '\0', MAX_PATH );
- //----------------------------------------------------------------------
- // While our ptr has not passed the end of the string...
- //----------------------------------------------------------------------
- while (*letter != '\0') {
- if ((*letter == '&') && (*( letter+1 ) == '&')) {
- pszTemp[i++] = '&';
- letter = letter + 2;
-
- } else {
-
- if ( upper_case ) {
- pszTemp[i++] = (char) toupper( *( letter++ ));
- } else {
- pszTemp[i++] = *(letter++);
- }
- }
- }
- strcpy((LPSTR)pszString, (LPSTR)pszTemp );
- }
- /******************************************************************************
- * Load_Alloc_Data -- Allocates a buffer and loads the file into it. *
- * *
- * This is the C++ replacement for the Load_Alloc_Data function. It will *
- * allocate the memory big enough to hold the file & read the file into it. *
- * *
- * INPUT: file -- The file to read. *
- * mem -- The memory system to use for allocation. *
- * *
- * OUTPUT: Returns with a pointer to the allocated and filled memory block. *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 10/17/1994 JLB : Created. *
- *============================================================================*/
- void * Load_Alloc_Data( char *filename, long *filesize )
- {
- int size, bytes_read;
- void *ptr = NULL;
- StandardFileClass file;
- //-------------------------------------------------------------------------
- // Open file in READ ONLY mode. If fails, exit.
- //-------------------------------------------------------------------------
- file.Open( filename, MODE_READ_ONLY );
- if ( !file.Query_Open()) {
- return( NULL );
- }
- //-------------------------------------------------------------------------
- // Get filesize and create a buffer.
- //-------------------------------------------------------------------------
- size = file.Query_Size();
- ptr = (void*)malloc(size + 1);
- if ( !ptr ) {
- return( NULL );
- }
- //-------------------------------------------------------------------------
- // Read data into the buffer, close the file.
- //-------------------------------------------------------------------------
- memset( ptr, '\0', size + 1 );
- bytes_read = file.Read( ptr, size );
- file.Close();
- //-------------------------------------------------------------------------
- // Check return bytes. It should match the file size.
- //-------------------------------------------------------------------------
- assert( bytes_read == size );
- if ( bytes_read != size ) {
- free(ptr);
- return( NULL );
- }
- if ( filesize != NULL ) {
- *filesize = (long)size;
- }
- return( ptr );
- }
- /****************************************************************************
- * MIXFILECLASS::LOAD_FILE -- Returns a buffer loaded with file desired. *
- * *
- * INPUT: none. * *
- * *
- * OUTPUT: none. *
- * *
- * WARNINGS: Searches MixFile first, then local directory. *
- * Use free() to release buffer. * *
- * *
- * HISTORY: *
- * 04/13/1998 ML/MG : Created. *
- *==========================================================================*/
- void *Load_File ( char *filename, long *filesize )
- {
- void *ptr = NULL;
- if ( filename == NULL || filename[0] == '\0' ) {
- return( NULL );
- }
- //-------------------------------------------------------------------------
- // Try loading from local directory.
- //-------------------------------------------------------------------------
- ptr = Load_Alloc_Data( filename, filesize );
- return( ptr );
- }
- /****************************************************************************
- * MAKE_CURRENT_PATH_TO -- Returns a buffer to path desired. *
- * *
- * INPUT: none. * *
- * *
- * OUTPUT: none. *
- * *
- * WARNINGS: * *
- * *
- * HISTORY: *
- * 10/08/2001 MML : Created. *
- *==========================================================================*/
- char *Make_Current_Path_To ( char *filename, char *path )
- {
- char szPath [ _MAX_PATH ];
- char drive [ _MAX_DRIVE];
- char dir [ _MAX_DIR ];
- strcpy( szPath, Args->Get_argv(0));
- _splitpath( szPath, drive, dir, NULL, NULL );
- _makepath( szPath, drive, dir, NULL, NULL );
- Path_Add_Back_Slash( szPath );
- strcat( szPath, filename );
- if( path != NULL ) {
- strcpy( path, szPath );
- }
- return( path );
- }
- wchar_t *Make_Current_Path_To ( wchar_t *filename, wchar_t *path )
- {
- wchar_t szPath [ _MAX_PATH ];
- wchar_t drive [ _MAX_DRIVE];
- wchar_t dir [ _MAX_DIR ];
- wcscpy( szPath, (wchar_t *)Args->Get_argv(0));
- _wsplitpath( szPath, drive, dir, NULL, NULL );
- _wmakepath( szPath, drive, dir, NULL, NULL );
- Path_Add_Back_Slash( szPath );
- wcscat( szPath, filename );
- if( path != NULL ) {
- wcscpy( path, szPath );
- }
- return( path );
- }
- /******************************************************************************
- * Path_Add_Back_Slash -- Add a '\\' to the end of the path.
- *
- * INPUT: char * path -- Pointer to the string to be modified.
- *
- * OUTPUT: char * path
- *
- * WARNINGS: none
- *
- * HISTORY:
- * 08/14/1998 MML : Created.
- *============================================================================*/
- char *Path_Add_Back_Slash ( char *path )
- {
- if ( path != NULL && *path != '\0' ) {
- if ( path[ strlen( path )-1 ] != '\\' ) {
- strcat( path, "\\" );
- }
- }
- return( path );
- }
- wchar_t *Path_Add_Back_Slash ( wchar_t *path )
- {
- if ( path != NULL && *path != '\0' ) {
- if ( path[ wcslen( path )-1 ] != '\\' ) {
- wcscat( path, L"\\" );
- }
- }
- return( path );
- }
- /******************************************************************************
- * Path_Remove_Back_Slash -- Remove a '\\' from the end of the path.
- *
- * INPUT: char * path -- Pointer to the string to be modified.
- *
- * OUTPUT: char * path
- *
- * WARNINGS: none
- *
- * HISTORY:
- * 08/14/1998 MML : Created.
- *============================================================================*/
- char *Path_Remove_Back_Slash ( char *path )
- {
- if ( path != NULL && *path != '\0' ) {
- if ( path[ strlen( path )-1 ] == '\\' ) {
- path[ strlen( path )-1 ] = '\0';
- }
- }
- return( path );
- }
- wchar_t *Path_Remove_Back_Slash ( wchar_t *path )
- {
- if ( path != NULL && *path != '\0' ) {
- if ( path[ wcslen( path )-1 ] == L'\\' ) {
- path[ wcslen( path )-1 ] = L'\0';
- }
- }
- return( path );
- }
- /*--------------------------------------------------------------------------*/
- /* Function: PlugInProductName */
- /* */
- /* Descrip: The function plugs the product name defined in */
- /* SdProductName() into %P found in the static message. */
- /* It will search for the first nMax controls only. */
- /* Misc: */
- /* */
- /*--------------------------------------------------------------------------*/
- void PlugInProductName ( char *szString, char *szName )
- {
- int nCount, nMsgLength;
- char szTextBuf[ MAX_PATH ];
- char szOut[ MAX_PATH ];
- char szProduct[ MAX_PATH ];
- char * temp = NULL;
- char * next = NULL;
- if ( szName == NULL || szName[0] == '\0' ) {
- return;
- }
- //--------------------------------------------------------------------------
- // Find the first appearance of "%P".
- //--------------------------------------------------------------------------
- strcpy( szProduct, szName );
- strcpy( szTextBuf, szString );
- nMsgLength = strlen( szTextBuf );
- nCount = 0;
- temp = strstr( szTextBuf, "%s" );
- //-------------------------------------------------------------
- // Substitute each "%P" with "%s". nStrReturn is the index
- // into the buffer where "%P" was found.
- //-------------------------------------------------------------
- while ( temp != NULL && nCount < 6) {
- next = temp+1;
- nCount = nCount + 1;
- temp = strstr( next, "%s" );
- }
- //-------------------------------------------------------------
- // Only support up to 5 product name per message.
- // Do the substitution of the product name and store in szOut.
- //-------------------------------------------------------------
- switch( nCount ) {
- case 1:
- sprintf( szOut, szTextBuf, szProduct );
- break;
- case 2:
- sprintf( szOut, szTextBuf, szProduct, szProduct );
- break;
- case 3:
- sprintf( szOut, szTextBuf, szProduct, szProduct, szProduct );
- break;
- case 4:
- sprintf( szOut, szTextBuf, szProduct, szProduct, szProduct, szProduct );
- break;
- case 5:
- sprintf( szOut, szTextBuf, szProduct, szProduct, szProduct, szProduct, szProduct, szProduct );
- break;
- }
- //-------------------------------------------------------------
- // Replace szTextBuf with szOut.
- //-------------------------------------------------------------
- if ( nCount >= 1 ) {
- strcpy( szString, szOut );
- }
- }
- /*--------------------------------------------------------------------------*/
- /* Function: PlugInProductName */
- /* */
- /* Descrip: The function plugs the product name defined in */
- /* SdProductName() into %P found in the static message. */
- /* It will search for the first nMax controls only. */
- /* Misc: */
- /* */
- /*--------------------------------------------------------------------------*/
- void PlugInProductName( char *szString, int nName )
- {
- /*
- int nCount, nMsgLength;
- char szTextBuf[ MAX_PATH ];
- char szOut[ MAX_PATH ];
- char szProduct[ MAX_PATH ];
- char * temp = NULL;
- char * next = NULL;
- if ( nName <= STRNONE ) {
- nName = STRNONE;
- }
- //--------------------------------------------------------------------------
- // Find the first appearance of "%P".
- //-------------------------------------------------------------
- // LoadString( Main::hInstance, nName, szProduct, MAX_PATH );
- Locale_GetString( nName, szProduct );
- strcpy( szTextBuf, szString );
- nMsgLength = strlen( szTextBuf );
- nCount = 0;
- temp = strstr( szTextBuf, "%s" );
- //-------------------------------------------------------------
- // Substitute each "%P" with "%s". nStrReturn is the index
- // into the buffer where "%P" was found.
- //-------------------------------------------------------------
- while ( temp != NULL && nCount < 6) {
- next = temp+1;
- nCount = nCount + 1;
- temp = strstr( next, "%s" );
- }
- //-------------------------------------------------------------
- // Only support up to 5 product name per message.
- // Do the substitution of the product name and store in szOut.
- //-------------------------------------------------------------
- switch( nCount ) {
- case 1:
- sprintf( szOut, szTextBuf, szProduct );
- break;
- case 2:
- sprintf( szOut, szTextBuf, szProduct, szProduct );
- break;
- case 3:
- sprintf( szOut, szTextBuf, szProduct, szProduct, szProduct );
- break;
- case 4:
- sprintf( szOut, szTextBuf, szProduct, szProduct, szProduct, szProduct );
- break;
- case 5:
- sprintf( szOut, szTextBuf, szProduct, szProduct, szProduct, szProduct, szProduct, szProduct );
- break;
- }
- //-------------------------------------------------------------
- // Replace szTextBuf with szOut.
- //-------------------------------------------------------------
- if ( nCount >= 1 ) {
- strcpy( szString, szOut );
- }
- */
- }
- /*--------------------------------------------------------------------------*/
- /* Function: PlugInProductName */
- /* */
- /* Descrip: The function plugs the product name defined in */
- /* SdProductName() into %P found in the static message. */
- /* It will search for the first nMax controls only. */
- /* Misc: */
- /* */
- /*--------------------------------------------------------------------------*/
- void PlugInProductName ( wchar_t *szString, const wchar_t *szName )
- {
- int nCount, nMsgLength;
- wchar_t szTextBuf[ MAX_PATH ];
- wchar_t szOut[ MAX_PATH ];
- wchar_t szProduct[ MAX_PATH ];
- wchar_t *temp = NULL;
- wchar_t *next = NULL;
- if ( szName == NULL || szName[0] == '\0' ) {
- return;
- }
- //--------------------------------------------------------------------------
- // Find the first appearance of "%P".
- //--------------------------------------------------------------------------
- wcscpy( szProduct, szName );
- wcscpy( szTextBuf, szString );
- nMsgLength = wcslen( szTextBuf );
- nCount = 0;
- temp = wcsstr( szTextBuf, L"%s" );
- //-------------------------------------------------------------
- // Substitute each "%P" with "%s". nStrReturn is the index
- // into the buffer where "%P" was found.
- //-------------------------------------------------------------
- while ( temp != NULL && nCount < 6) {
- next = temp+1;
- nCount = nCount + 1;
- temp = wcsstr( next, L"%s" );
- }
- //-------------------------------------------------------------
- // Only support up to 5 product name per message.
- // Do the substitution of the product name and store in szOut.
- //-------------------------------------------------------------
- switch( nCount ) {
- case 1:
- swprintf( szOut, szTextBuf, szProduct );
- break;
- case 2:
- swprintf( szOut, szTextBuf, szProduct, szProduct );
- break;
- case 3:
- swprintf( szOut, szTextBuf, szProduct, szProduct, szProduct );
- break;
- case 4:
- swprintf( szOut, szTextBuf, szProduct, szProduct, szProduct, szProduct );
- break;
- case 5:
- swprintf( szOut, szTextBuf, szProduct, szProduct, szProduct, szProduct, szProduct, szProduct );
- break;
- }
- //-------------------------------------------------------------
- // Replace szTextBuf with szOut.
- //-------------------------------------------------------------
- if ( nCount >= 1 ) {
- wcscpy( szString, szOut );
- }
- }
|