601 lines
17 KiB
C++
601 lines
17 KiB
C++
/*
|
|
=======================================================================================
|
|
Name :ModifLst.cpp
|
|
|
|
Author :vincent lhullier Date :23/07/97
|
|
|
|
Description :manage list of modifications
|
|
=======================================================================================
|
|
Modification -> Author : Date :
|
|
Description :
|
|
=======================================================================================
|
|
*/
|
|
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
#include "stdafx.h"
|
|
|
|
#include "IniData.h"
|
|
#include "ModifLst.h"
|
|
#include "SCR.h"
|
|
#include "dlgmodif.h"
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
|
|
/*
|
|
=======================================================================================
|
|
Globals
|
|
=======================================================================================
|
|
*/
|
|
tdstModif *g_p_stLastModif = NULL;
|
|
tdstModif *g_p_stFirstModif = NULL;
|
|
long g_lNumberOfModifs = 0;
|
|
long g_lNumberOfChildModifs = 0;
|
|
long g_lNumberOfFatherModifs = 0;
|
|
|
|
/*
|
|
=======================================================================================
|
|
Functions to decompose modif name
|
|
=======================================================================================
|
|
*/
|
|
|
|
|
|
/*
|
|
----------------------------------------------------------------------------------------
|
|
Description : extract from a modif name the filename and short filename
|
|
_p_stModif -> modif
|
|
szFileName -> string to store filename
|
|
szShortFileName -> string to store short name
|
|
Returns (BOOL) TRUE if section modified is the file, FALSE if it's a section in the
|
|
file
|
|
----------------------------------------------------------------------------------------
|
|
*/
|
|
BOOL fn_bGetModifiedFile( tdstModif *_p_stModif, char *_szFileName, char *_szShortFileName )
|
|
{
|
|
char *p_szEnd;
|
|
BOOL bResult;
|
|
|
|
strcpy( _szFileName, _p_stModif->szName );
|
|
p_szEnd = strchr( _szFileName, '^' );
|
|
if (p_szEnd != NULL)
|
|
*p_szEnd = 0;
|
|
bResult = ( p_szEnd == NULL );
|
|
|
|
p_szEnd = strrchr( _szFileName, '\\');
|
|
if (p_szEnd == NULL)
|
|
p_szEnd = _szFileName;
|
|
else
|
|
p_szEnd++;
|
|
strcpy( _szShortFileName, p_szEnd );
|
|
|
|
return bResult;
|
|
}
|
|
|
|
|
|
/*
|
|
----------------------------------------------------------------------------------------
|
|
Description : find in modif first child modif of given father modif
|
|
_p_stFather -> father of modif searched
|
|
Returns (tdstModif ) a child modif
|
|
----------------------------------------------------------------------------------------
|
|
*/
|
|
tdstModif *fn_p_stGetChildModif( tdstModif *_p_stFather )
|
|
{
|
|
tdstModif *p_stChild = g_p_stFirstModif;
|
|
while (p_stChild != NULL)
|
|
{
|
|
if (p_stChild->p_stFather == _p_stFather)
|
|
return p_stChild;
|
|
p_stChild = p_stChild->p_stNext;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
----------------------------------------------------------------------------------------
|
|
Description : return number of children of a section modification
|
|
_p_stFather -> father
|
|
Returns (long ) number of children
|
|
----------------------------------------------------------------------------------------
|
|
*/
|
|
long fn_lNumberOfChildModif( tdstModif *_p_stFather )
|
|
{
|
|
long lNumber = 0;
|
|
tdstModif *p_stChild = g_p_stFirstModif;
|
|
tdstModif *p_stFather;
|
|
|
|
while (p_stChild != NULL)
|
|
{
|
|
p_stFather = p_stChild->p_stFather;
|
|
while (p_stFather != NULL)
|
|
{
|
|
if (p_stFather == _p_stFather )
|
|
{
|
|
lNumber++;
|
|
break;
|
|
}
|
|
p_stFather = p_stFather->p_stFather;
|
|
}
|
|
p_stChild = p_stChild->p_stNext;
|
|
}
|
|
return lNumber;
|
|
}
|
|
|
|
/*
|
|
----------------------------------------------------------------------------------------
|
|
Description : delete a modification on a section and restore all modification on
|
|
subsection of this section
|
|
----------------------------------------------------------------------------------------
|
|
*/
|
|
void fn_vRestoreSubModif(tdstModif *_p_stModif )
|
|
{
|
|
tdstModif *p_stSubModif = g_p_stFirstModif;
|
|
|
|
while (p_stSubModif != NULL)
|
|
{
|
|
if (p_stSubModif->p_stFather == _p_stModif)
|
|
{
|
|
p_stSubModif->p_stFather = NULL;
|
|
g_lNumberOfChildModifs--;
|
|
g_lNumberOfFatherModifs++;
|
|
}
|
|
p_stSubModif = p_stSubModif->p_stNext;
|
|
}
|
|
//fn_lDeleteModif( _p_stModif, FALSE );
|
|
}
|
|
|
|
/*
|
|
---------------------------------------------------------------------------------------
|
|
delete a modif from list
|
|
---------------------------------------------------------------------------------------
|
|
*/
|
|
long fn_lDeleteModif( tdstModif *_p_stModif, BOOL _bDeleteChild )
|
|
{
|
|
tdstModif *p_stChild;
|
|
long lDeleted = 0;
|
|
|
|
if (_p_stModif == NULL)
|
|
return 0;
|
|
|
|
// free all child modification
|
|
if (_bDeleteChild)
|
|
while ( (p_stChild = fn_p_stGetChildModif( _p_stModif )) != NULL)
|
|
lDeleted += fn_lDeleteModif( p_stChild, _bDeleteChild );
|
|
|
|
//deallocate memory for name
|
|
free (_p_stModif->szName );
|
|
// keep link between modification
|
|
if (_p_stModif == g_p_stFirstModif )
|
|
g_p_stFirstModif = _p_stModif->p_stNext;
|
|
if (_p_stModif == g_p_stLastModif)
|
|
g_p_stLastModif = _p_stModif->p_stPrevious;
|
|
|
|
if (_p_stModif->p_stPrevious != NULL)
|
|
_p_stModif->p_stPrevious->p_stNext = _p_stModif->p_stNext;
|
|
if (_p_stModif->p_stNext != NULL)
|
|
_p_stModif->p_stNext->p_stPrevious = _p_stModif->p_stPrevious;
|
|
//deallocate memory for modif
|
|
if (_p_stModif->p_stFather == NULL)
|
|
g_lNumberOfFatherModifs--;
|
|
else
|
|
g_lNumberOfChildModifs--;
|
|
g_lNumberOfModifs--;
|
|
|
|
free( _p_stModif );
|
|
return lDeleted + 1;
|
|
}
|
|
|
|
/*
|
|
---------------------------------------------------------------------------------------
|
|
delete all modif in list
|
|
---------------------------------------------------------------------------------------
|
|
*/
|
|
void fn_vDeleteAllModifs( void )
|
|
{
|
|
tdstModif *p_stModif = g_p_stFirstModif;
|
|
while (p_stModif != NULL)
|
|
{
|
|
fn_lDeleteModif( p_stModif, FALSE );
|
|
p_stModif = g_p_stFirstModif;
|
|
}
|
|
g_lNumberOfFatherModifs = g_lNumberOfChildModifs = g_lNumberOfModifs = 0;
|
|
}
|
|
|
|
/*
|
|
---------------------------------------------------------------------------------------
|
|
search for a modification in the same file
|
|
---------------------------------------------------------------------------------------
|
|
*/
|
|
tdstModif *fnp_stGetModifInFile( char *_szFileName, BOOL _bChild, BOOL _bAll )
|
|
{
|
|
tdstModif *p_stModif = g_p_stFirstModif;
|
|
size_t xSize = strlen( _szFileName );
|
|
|
|
while (p_stModif != NULL)
|
|
{
|
|
if (
|
|
((_bChild) || (p_stModif->p_stFather == NULL)) &&
|
|
((_bAll) || (!p_stModif->bConflict)) &&
|
|
(strnicmp(p_stModif->szName, _szFileName, xSize ) == 0)
|
|
)
|
|
break;
|
|
p_stModif = p_stModif->p_stNext;
|
|
}
|
|
return p_stModif;
|
|
}
|
|
|
|
/*
|
|
---------------------------------------------------------------------------------------
|
|
delete all modif that are in a given file
|
|
returns nuumber of modif deleted from list
|
|
---------------------------------------------------------------------------------------
|
|
*/
|
|
int fn_iDeleteAllModifForAFile( char *_szFileName )
|
|
{
|
|
int iIndex = 0;
|
|
|
|
tdstModif *p_stModif = fnp_stGetModifInFile( _szFileName, TRUE, TRUE );
|
|
while (p_stModif != NULL)
|
|
{
|
|
iIndex ++;
|
|
fn_lDeleteModif( p_stModif, TRUE );
|
|
p_stModif = fnp_stGetModifInFile( _szFileName, TRUE, TRUE );
|
|
}
|
|
return iIndex;
|
|
}
|
|
|
|
/*
|
|
---------------------------------------------------------------------------------------
|
|
Mark all modif that are in a given file
|
|
returns number of modif deleted from list
|
|
---------------------------------------------------------------------------------------
|
|
*/
|
|
int fn_iMarkAllModifForAFile( char *_szFileName )
|
|
{
|
|
int iIndex = 0;
|
|
|
|
tdstModif *p_stModif = fnp_stGetModifInFile( _szFileName, TRUE, FALSE );
|
|
while (p_stModif != NULL)
|
|
{
|
|
iIndex ++;
|
|
p_stModif->bConflict = TRUE;
|
|
p_stModif = fnp_stGetModifInFile( _szFileName, TRUE, FALSE );
|
|
}
|
|
return iIndex;
|
|
}
|
|
|
|
|
|
/*
|
|
----------------------------------------------------------------------------------------
|
|
Description : get first not marked modification
|
|
Returns (tdstModif ) first not marked modification
|
|
----------------------------------------------------------------------------------------
|
|
*/
|
|
tdstModif *fn_p_stGetFirstNotMarkedModif( void )
|
|
{
|
|
tdstModif *p_stModif;
|
|
|
|
p_stModif = g_p_stFirstModif;
|
|
while ( (p_stModif != NULL) && ((p_stModif->bConflict) || (p_stModif->p_stFather != NULL)) )
|
|
p_stModif = p_stModif->p_stNext;
|
|
|
|
return p_stModif;
|
|
}
|
|
|
|
|
|
/*
|
|
---------------------------------------------------------------------------------------
|
|
delete modif file
|
|
---------------------------------------------------------------------------------------
|
|
*/
|
|
BOOL fn_bDeleteModifFile( void )
|
|
{
|
|
char szTxtFullName[ MAX_PATH ];
|
|
char szBakFullName[ MAX_PATH ];
|
|
|
|
sprintf( szTxtFullName, "%s\\%s", g_stIniData.szLocalPath, g_stIniData.szModifFile );
|
|
strcpy ( szBakFullName, szTxtFullName );
|
|
strcpy( strrchr( szBakFullName, '.'), ".bak" );
|
|
|
|
if (_access( szTxtFullName, 0) == 0)
|
|
{
|
|
if (_access( szBakFullName, 0) == 0)
|
|
remove( szBakFullName );
|
|
|
|
return MoveFile( szTxtFullName, szBakFullName);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
---------------------------------------------------------------------------------------
|
|
rewrite modif file with all modif that are always in file
|
|
---------------------------------------------------------------------------------------
|
|
*/
|
|
void fn_vWriteModifInFile( BOOL _bDelete )
|
|
{
|
|
char szFullName[ MAX_PATH ];
|
|
FILE *hpFile;
|
|
tdstModif *p_stModif = g_p_stFirstModif;
|
|
tdstModif *p_stDeleteModif;
|
|
|
|
fn_bDeleteModifFile();
|
|
|
|
sprintf( szFullName, "%s\\%s", g_stIniData.szLocalPath, g_stIniData.szModifFile );
|
|
hpFile = fopen( szFullName, "wt" );
|
|
|
|
while ( p_stModif != NULL )
|
|
{
|
|
fprintf( hpFile, "(%c)%s\n", *g_a_szModifName[ p_stModif->cType ], p_stModif->szName );
|
|
p_stDeleteModif = p_stModif;
|
|
p_stModif = p_stModif->p_stNext;
|
|
if (_bDelete)
|
|
fn_lDeleteModif (p_stDeleteModif, FALSE);
|
|
}
|
|
fclose( hpFile );
|
|
}
|
|
|
|
/*
|
|
---------------------------------------------------------------------------------------
|
|
function that read file where Modification list was saved.
|
|
returns number of modification
|
|
---------------------------------------------------------------------------------------
|
|
*/
|
|
int fn_iReadModificationFile( void )
|
|
{
|
|
char szFullName[ MAX_PATH ];
|
|
char szLine[1024];
|
|
char *p_szEnd;
|
|
FILE *hpFile;
|
|
tdstModif *p_stModif;
|
|
char *p_szLine;
|
|
long lCurrentLine = 0;
|
|
|
|
/* emptied list before reading file */
|
|
fn_vDeleteAllModifs();
|
|
|
|
/* building full name of modif file */
|
|
sprintf( szFullName, "%s\\%s", g_stIniData.szLocalPath, g_stIniData.szModifFile );
|
|
|
|
/* open file */
|
|
if ( (hpFile = fopen( szFullName, "rt" ) ) == NULL )
|
|
return 0;
|
|
|
|
/* for each line */
|
|
while (fgets(szLine, 1023, hpFile) != NULL)
|
|
{
|
|
lCurrentLine++;
|
|
/* go to last character, swap \r\n char */
|
|
p_szEnd = szLine + strlen(szLine) - 1;
|
|
while (
|
|
(p_szEnd != szLine - 1) &&
|
|
(
|
|
(isspace(*p_szEnd)) ||
|
|
(*p_szEnd == '\n') ||
|
|
(*p_szEnd == '\r')
|
|
)
|
|
)
|
|
*p_szEnd--;
|
|
*(++p_szEnd) = 0;
|
|
|
|
if (strlen(szLine) == 0)
|
|
continue;
|
|
|
|
/* create a new modif */
|
|
p_stModif = (tdstModif *) malloc (sizeof(tdstModif));
|
|
p_stModif->lLine = lCurrentLine;
|
|
p_stModif->bConflict = FALSE;
|
|
p_stModif->p_stFather = NULL;
|
|
|
|
if ( *(p_szLine = szLine) == '(' )
|
|
{
|
|
switch( *(p_szLine + 1) )
|
|
{
|
|
case C_ModifChar_cAdd: p_stModif->cType = C_ModifType_cAdd; break;
|
|
case C_ModifChar_cRebuild: p_stModif->cType = C_ModifType_cRebuild; break;
|
|
case C_ModifChar_cModif: p_stModif->cType = C_ModifType_cModif; break;
|
|
case C_ModifChar_cDelete: p_stModif->cType = C_ModifType_cDelete; break;
|
|
}
|
|
p_szLine += 3;
|
|
}
|
|
else
|
|
p_stModif->cType = C_ModifType_cModif;
|
|
|
|
if (strnicmp( p_szLine, "GameData\\", 9) == 0)
|
|
p_szLine += 9;
|
|
|
|
p_stModif->szName = (char *) malloc (strlen( p_szLine ) + 1);
|
|
strcpy( p_stModif->szName, p_szLine );
|
|
|
|
p_stModif->p_stNext = NULL;
|
|
p_stModif->p_stPrevious = g_p_stLastModif;
|
|
|
|
/* add it in modif list */
|
|
if (g_p_stFirstModif == NULL)
|
|
g_p_stFirstModif = p_stModif;
|
|
else
|
|
g_p_stLastModif->p_stNext = p_stModif;
|
|
|
|
g_p_stLastModif = p_stModif;
|
|
|
|
g_lNumberOfModifs ++;
|
|
}
|
|
g_lNumberOfFatherModifs = g_lNumberOfModifs;
|
|
g_lNumberOfChildModifs = 0;
|
|
/* close file */
|
|
fclose( hpFile );
|
|
|
|
/* clean modif list : delete all redondant modifications */
|
|
fn_vCleanModifList();
|
|
|
|
return g_lNumberOfModifs;
|
|
}
|
|
|
|
/*
|
|
---------------------------------------------------------------------------------------
|
|
update modification file
|
|
delete it, rewrite it with all modif that causes conflict
|
|
display conflict if there's some
|
|
---------------------------------------------------------------------------------------
|
|
*/
|
|
void fn_vUpdateModifFile( void )
|
|
{
|
|
/* delete modif file */
|
|
fn_bDeleteModifFile();
|
|
fn_vWriteModifInFile( FALSE );
|
|
}
|
|
|
|
|
|
/*
|
|
----------------------------------------------------------------------------------------
|
|
Description : delete all redondant modification such as a modified sub section when
|
|
it's parent section is modified too
|
|
----------------------------------------------------------------------------------------
|
|
*/
|
|
char g_aa_cComposedType[5][5] =
|
|
{
|
|
/* Destroy , Add , Rebuild , Modif , Delete */
|
|
{ C_ModifType_cError, C_ModifType_cAdd , C_ModifType_cError , C_ModifType_cError, C_ModifType_cError }, /* Destroy */
|
|
{ C_ModifType_cError, C_ModifType_cError, C_ModifType_cAdd , C_ModifType_cAdd , C_ModifType_cDestroy}, /* Add */
|
|
{ C_ModifType_cError, C_ModifType_cError, C_ModifType_cRebuild, C_ModifType_cModif, C_ModifType_cDelete }, /* Rebuild */
|
|
{ C_ModifType_cError, C_ModifType_cError, C_ModifType_cRebuild, C_ModifType_cModif, C_ModifType_cDelete }, /* Modif */
|
|
{ C_ModifType_cError, C_ModifType_cModif, C_ModifType_cError , C_ModifType_cError, C_ModifType_cError } /* Delete */
|
|
};
|
|
|
|
char *g_a_szModifName[5] =
|
|
{
|
|
"Destroyed",
|
|
"Added",
|
|
"Rebuild",
|
|
"Modified",
|
|
"Deleted"
|
|
};
|
|
|
|
void fn_vCleanModifList( void )
|
|
{
|
|
tdstModif *p_stModif = g_p_stFirstModif;
|
|
tdstModif *p_stOtherModif;
|
|
char cNextChar;
|
|
char cNewType;
|
|
long lNumberOfErrors = 0;
|
|
char **d_szError = NULL;
|
|
long lError;
|
|
long lCurrentFatherLength, lFatherLength;
|
|
|
|
/*
|
|
* First : find all error and all double notification
|
|
*/
|
|
while ( p_stModif != NULL )
|
|
{
|
|
p_stOtherModif = p_stModif->p_stNext;
|
|
while (p_stOtherModif != NULL)
|
|
{
|
|
if ( stricmp( p_stOtherModif->szName, p_stModif->szName ) == 0)
|
|
{
|
|
p_stOtherModif->bConflict = TRUE;
|
|
p_stOtherModif->cPrevType = p_stModif->cType;
|
|
cNewType = g_aa_cComposedType[ p_stModif->cType ][ p_stOtherModif->cType ];
|
|
if (cNewType != C_ModifType_cError)
|
|
p_stModif->cType = cNewType;
|
|
}
|
|
p_stOtherModif = p_stOtherModif->p_stNext;
|
|
}
|
|
do
|
|
{
|
|
p_stModif = p_stModif->p_stNext;
|
|
} while ( (p_stModif != NULL) && (p_stModif->bConflict) );
|
|
}
|
|
|
|
/* count eventual errors */
|
|
p_stModif = g_p_stFirstModif;
|
|
while (p_stModif != NULL)
|
|
{
|
|
if (p_stModif->bConflict)
|
|
{
|
|
cNewType = g_aa_cComposedType[ p_stModif->cPrevType ][ p_stModif->cType ];
|
|
if (cNewType == C_ModifType_cError)
|
|
lNumberOfErrors++;
|
|
}
|
|
p_stModif = p_stModif->p_stNext;
|
|
}
|
|
|
|
if (lNumberOfErrors)
|
|
d_szError = (char **) malloc( lNumberOfErrors * sizeof(char *) );
|
|
|
|
/* get errors and delete eventual doublon */
|
|
p_stModif = g_p_stFirstModif;
|
|
lError = 0;
|
|
while (p_stModif != NULL)
|
|
{
|
|
p_stOtherModif = p_stModif->p_stNext;
|
|
if (p_stModif->bConflict)
|
|
{
|
|
cNewType = g_aa_cComposedType[ p_stModif->cPrevType ][ p_stModif->cType ];
|
|
if (cNewType == C_ModifType_cError)
|
|
{
|
|
d_szError[ lError] = (char *) malloc ( strlen( p_stModif->szName) + 100 );
|
|
sprintf( d_szError[lError] , "(Line %4d) %s section has been %s after being %s", p_stModif->lLine, p_stModif->szName, g_a_szModifName[ p_stModif->cType ], g_a_szModifName[ p_stModif->cPrevType ] );
|
|
lError++;
|
|
}
|
|
fn_lDeleteModif( p_stModif, FALSE );
|
|
}
|
|
p_stModif = p_stOtherModif;
|
|
}
|
|
|
|
/* build section / sous section hierarchy */
|
|
p_stModif = g_p_stFirstModif;
|
|
while (p_stModif != NULL)
|
|
{
|
|
lCurrentFatherLength = 0;
|
|
p_stOtherModif = g_p_stFirstModif;
|
|
while (p_stOtherModif != NULL)
|
|
{
|
|
if (p_stOtherModif != p_stModif)
|
|
{
|
|
lFatherLength = strlen( p_stOtherModif->szName );
|
|
if ( (lFatherLength > lCurrentFatherLength) && strnicmp( p_stOtherModif->szName, p_stModif->szName, lFatherLength ) == 0)
|
|
{
|
|
cNextChar = p_stModif->szName[lFatherLength];
|
|
if (cNextChar == SCR_CC_c_Cfg_NameSeparator)
|
|
{
|
|
if (lCurrentFatherLength != 0)
|
|
{
|
|
g_lNumberOfFatherModifs--;
|
|
g_lNumberOfChildModifs++;
|
|
}
|
|
lCurrentFatherLength = lFatherLength;
|
|
p_stModif->p_stFather = p_stOtherModif;
|
|
}
|
|
}
|
|
}
|
|
p_stOtherModif = p_stOtherModif->p_stNext;
|
|
}
|
|
p_stModif = p_stModif->p_stNext;
|
|
}
|
|
|
|
/* delete eventual destroyed modif */
|
|
p_stModif = g_p_stFirstModif;
|
|
while (p_stModif != NULL)
|
|
{
|
|
if (p_stModif->cType == C_ModifType_cDestroy)
|
|
{
|
|
fn_lDeleteModif( p_stModif, TRUE );
|
|
p_stModif = g_p_stFirstModif;
|
|
}
|
|
else
|
|
p_stModif = p_stModif->p_stNext;
|
|
}
|
|
|
|
/*
|
|
* display error if that happens
|
|
*/
|
|
if (lNumberOfErrors )
|
|
{
|
|
CModifListErrorDlg oErrorDlg( lNumberOfErrors, d_szError );
|
|
oErrorDlg.DoModal();
|
|
|
|
for ( lError = 0; lError < lNumberOfErrors; lError++)
|
|
free ( d_szError[ lError ] );
|
|
free ( d_szError );
|
|
}
|
|
}
|