/* ======================================================================================= 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 ); } }