644 lines
18 KiB
C++
644 lines
18 KiB
C++
/*
|
|
=======================================================================================
|
|
Name :SaveMngr.cpp
|
|
|
|
Author :Vincent Lhullier Date :11/07/97
|
|
|
|
Description :manage save of data before modification
|
|
Create a copy of GameData tree with all file that would be modified. That will allow
|
|
someone to recuperate previous version if save generate some problem in data.
|
|
=======================================================================================
|
|
Modification -> Author : Date :
|
|
Description :
|
|
=======================================================================================
|
|
*/
|
|
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
#include "stdafx.h"
|
|
|
|
#ifdef ACTIVE_EDITOR
|
|
|
|
#include <io.h>
|
|
#include "SaveMngr.h"
|
|
|
|
#include "acp_base.h"
|
|
#include "itf/CPAProj.hpp"
|
|
|
|
#include "DPT.h"
|
|
#include "SCR.h"
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
|
|
/*
|
|
=======================================================================================
|
|
STRUCTURE
|
|
=======================================================================================
|
|
*/
|
|
typedef struct SAVE_tdstFile_
|
|
{
|
|
char *szName;
|
|
char cNew;
|
|
} SAVE_tdstFile;
|
|
|
|
|
|
/*
|
|
=======================================================================================
|
|
GLOBALS
|
|
=======================================================================================
|
|
*/
|
|
/*
|
|
* indicate next number of version to use to save files
|
|
* Warning : to be valid you must call SAVE_fn_vAnalyseCurrentUsedVersion before using
|
|
* this number
|
|
*/
|
|
static long SAVE_g_lNextVersionNumber;
|
|
static BOOL SAVE_g_bContinue;
|
|
static BOOL SAVE_g_bGenerateIsActive = 2;
|
|
static char SAVE_g_szDirName[ _MAX_PATH ];
|
|
|
|
static SAVE_tdstFile *SAVE_gs_d_stFile;
|
|
static long SAVE_gs_lNumberOfFiles;
|
|
|
|
static char *SAVE_g_szGameData;
|
|
static long SAVE_g_lGameDataLength;
|
|
|
|
/*
|
|
=======================================================================================
|
|
=======================================================================================
|
|
FUNCTIONS
|
|
=======================================================================================
|
|
=======================================================================================
|
|
*/
|
|
|
|
/*
|
|
=======================================================================================
|
|
Directory Functions
|
|
=======================================================================================
|
|
*/
|
|
|
|
/*
|
|
----------------------------------------------------------------------------------------
|
|
Don't call this function directly, it is used by SAVE_fn_bDeleteTree
|
|
Description : delete recursively a directory
|
|
Returns (BOOL ) true if success
|
|
----------------------------------------------------------------------------------------
|
|
*/
|
|
BOOL fn_bDeleteTree( void )
|
|
{
|
|
WIN32_FIND_DATA stFindData;
|
|
HANDLE hFind;
|
|
char *p_szEndDirName;
|
|
|
|
p_szEndDirName = SAVE_g_szDirName + strlen( SAVE_g_szDirName );
|
|
strcpy( p_szEndDirName, "\\*.*" );
|
|
if( (hFind = FindFirstFile(SAVE_g_szDirName, &stFindData )) == INVALID_HANDLE_VALUE)
|
|
return TRUE;
|
|
*p_szEndDirName = 0;
|
|
|
|
do
|
|
{
|
|
*p_szEndDirName = '\\';
|
|
strcpy( p_szEndDirName + 1, stFindData.cFileName );
|
|
|
|
if ( stFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
|
|
{
|
|
if ( *stFindData.cFileName != '.')
|
|
{
|
|
if ( !fn_bDeleteTree() )
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (_access( SAVE_g_szDirName, 2) == -1 )
|
|
_chmod( SAVE_g_szDirName, _S_IWRITE );
|
|
|
|
if ( !DeleteFile( SAVE_g_szDirName ) )
|
|
return FALSE;
|
|
}
|
|
*p_szEndDirName = 0;
|
|
} while(FindNextFile( hFind, &stFindData ));
|
|
|
|
FindClose( hFind );
|
|
|
|
return RemoveDirectory( SAVE_g_szDirName );
|
|
}
|
|
|
|
|
|
/*
|
|
----------------------------------------------------------------------------------------
|
|
Description : delete completely a directory
|
|
szDirName -> name of dir to delete
|
|
Returns (BOOL ) true if success
|
|
----------------------------------------------------------------------------------------
|
|
*/
|
|
BOOL SAVE_fn_bDeleteTree( char *szDirName )
|
|
{
|
|
strcpy( SAVE_g_szDirName, szDirName );
|
|
return fn_bDeleteTree();
|
|
}
|
|
|
|
|
|
/*
|
|
----------------------------------------------------------------------------------------
|
|
Description : create a directory
|
|
szDirName -> name of directory
|
|
Returns (BOOL ) true if sucess
|
|
----------------------------------------------------------------------------------------
|
|
*/
|
|
BOOL SAVE_fn_bCreateDirectory( char *szDirName )
|
|
{
|
|
if ( (!CreateDirectory( szDirName, NULL )) && (GetLastError() != ERROR_ALREADY_EXISTS) )
|
|
{
|
|
char *p_szCur;
|
|
|
|
p_szCur = strchr( szDirName, '\\');
|
|
while (p_szCur != NULL)
|
|
{
|
|
*p_szCur = 0;
|
|
if ((!CreateDirectory (szDirName, NULL)) && (GetLastError() != ERROR_ALREADY_EXISTS) )
|
|
{
|
|
char szMessage[ 512 ];
|
|
sprintf( szMessage, "Can't create local path %s", szDirName );
|
|
SAVE_fn_vErrorMessage( szMessage );
|
|
return FALSE;
|
|
}
|
|
*p_szCur++ = '\\';
|
|
p_szCur = strchr( p_szCur, '\\');
|
|
};
|
|
|
|
if ((!CreateDirectory (szDirName, NULL)) && (GetLastError() != ERROR_ALREADY_EXISTS) )
|
|
{
|
|
char szMessage[ 512 ];
|
|
sprintf( szMessage, "Can't create local path %s", szDirName );
|
|
SAVE_fn_vErrorMessage( szMessage );
|
|
return FALSE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
=======================================================================================
|
|
Error functions
|
|
=======================================================================================
|
|
*/
|
|
|
|
/*
|
|
----------------------------------------------------------------------------------------
|
|
Description : display an error message
|
|
_szMessage -> message to display
|
|
----------------------------------------------------------------------------------------
|
|
*/
|
|
void SAVE_fn_vErrorMessage( char *_szMessage )
|
|
{
|
|
char szError[1024];
|
|
char *p_szError = szError;
|
|
|
|
p_szError += sprintf( p_szError, "Error saving current version before saving new data\n" );
|
|
p_szError += sprintf( p_szError, "You will not be able to get local previous version\n" );
|
|
p_szError += sprintf( p_szError, "---------------------------------------------------\n" );
|
|
p_szError += sprintf( p_szError, "%s\n\n", _szMessage );
|
|
p_szError += sprintf( p_szError, " Save anyway ?" );
|
|
SAVE_g_bContinue = AfxMessageBox( szError, MB_ICONSTOP | MB_YESNO );
|
|
}
|
|
|
|
/*
|
|
=======================================================================================
|
|
Version functions
|
|
=======================================================================================
|
|
*/
|
|
|
|
/*
|
|
----------------------------------------------------------------------------------------
|
|
Description :
|
|
_szSavedDirectoryName -> name of directory from which function extract version number
|
|
Returns (long ) version number if it's a valid directory, -1 else
|
|
----------------------------------------------------------------------------------------
|
|
*/
|
|
long SAVE_fn_lGetVersionNumberFromDirExt( char *_szSavedDirectoryName )
|
|
{
|
|
char *p_szExt;
|
|
long lVersionNumber = -1;
|
|
|
|
p_szExt = strchr( _szSavedDirectoryName, '.' );
|
|
if (p_szExt != NULL)
|
|
{
|
|
if ( strlen( ++p_szExt ) == 3)
|
|
{
|
|
lVersionNumber = 0;
|
|
while (*p_szExt != 0)
|
|
{
|
|
if ( !isdigit (*p_szExt) )
|
|
return -1;
|
|
lVersionNumber = lVersionNumber * 10 + (*p_szExt++ - '0');
|
|
}
|
|
}
|
|
}
|
|
return lVersionNumber;
|
|
}
|
|
|
|
|
|
/*
|
|
----------------------------------------------------------------------------------------
|
|
Description : return name of directory used to store data for a given version
|
|
lVersion -> version number
|
|
szVersionDirName -> to put dir name (assumed to be long enough )
|
|
----------------------------------------------------------------------------------------
|
|
*/
|
|
void SAVE_fn_vGetVersionDirName( long _lVersion, char *_szVersionDirName )
|
|
{
|
|
sprintf( _szVersionDirName, "%s.%03d", fn_szGetGameDataPath(), _lVersion );
|
|
}
|
|
|
|
|
|
/*
|
|
----------------------------------------------------------------------------------------
|
|
Description : delete a version directory
|
|
_lVersion -> number of version
|
|
Returns (BOOL ) true if success
|
|
----------------------------------------------------------------------------------------
|
|
*/
|
|
BOOL SAVE_fn_bDeleteVersion( long _lVersion )
|
|
{
|
|
char szVersionName[ _MAX_PATH ];
|
|
SAVE_fn_vGetVersionDirName( _lVersion, szVersionName );
|
|
if (!SAVE_fn_bDeleteTree( szVersionName ))
|
|
{
|
|
char szMessage[100];
|
|
sprintf( szMessage, "Can't delete old %s version directory", szVersionName );
|
|
SAVE_fn_vErrorMessage( szMessage );
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
----------------------------------------------------------------------------------------
|
|
Description : rename a version
|
|
_lOldVersion -> old version number
|
|
_lNewVersion -> new version number
|
|
Returns (BOOL )
|
|
----------------------------------------------------------------------------------------
|
|
*/
|
|
BOOL SAVE_fn_bRenameVersion( long _lOldVersion, long _lNewVersion )
|
|
{
|
|
char szOldVersion[ _MAX_PATH ];
|
|
char szNewVersion[ _MAX_PATH ];
|
|
|
|
SAVE_fn_vGetVersionDirName( _lOldVersion, szOldVersion );
|
|
SAVE_fn_vGetVersionDirName( _lNewVersion, szNewVersion );
|
|
|
|
if ( !MoveFile( szOldVersion, szNewVersion) )
|
|
{
|
|
char szMessage[100];
|
|
sprintf( szMessage, "Can't rename old %s version to new version %s ", szOldVersion, szNewVersion );
|
|
SAVE_fn_vErrorMessage( szMessage );
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
----------------------------------------------------------------------------------------
|
|
Description : analyse the current version that are on disk
|
|
a_cVersion -> array of 1000 char that will be filled
|
|
each case is a flag that indicate if a version number is used or not
|
|
return (long) number of used version
|
|
----------------------------------------------------------------------------------------
|
|
*/
|
|
long SAVE_fn_lGetUsedVersion( char *a_cVersion )
|
|
{
|
|
WIN32_FIND_DATA stFindData;
|
|
HANDLE hFind;
|
|
char szFilter[ _MAX_PATH ];
|
|
long lNumberOfVersions = 0;
|
|
long lVersion;
|
|
|
|
/*
|
|
* set all version as unused
|
|
*/
|
|
memset ( a_cVersion , 0, 1000 );
|
|
|
|
sprintf( szFilter, "%s.*", fn_szGetGameDataPath() );
|
|
|
|
if( (hFind = FindFirstFile(szFilter, &stFindData )) == INVALID_HANDLE_VALUE)
|
|
return 0;
|
|
|
|
do
|
|
{
|
|
if ( stFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
|
|
{
|
|
lVersion = SAVE_fn_lGetVersionNumberFromDirExt( stFindData.cFileName );
|
|
if (lVersion != -1)
|
|
{
|
|
a_cVersion[ lVersion ] = 1;
|
|
lNumberOfVersions++ ;
|
|
}
|
|
}
|
|
} while(FindNextFile( hFind, &stFindData ));
|
|
|
|
FindClose( hFind );
|
|
|
|
return lNumberOfVersions;
|
|
}
|
|
|
|
|
|
/*
|
|
----------------------------------------------------------------------------------------
|
|
Description : analyse the current version that are on disk
|
|
----------------------------------------------------------------------------------------
|
|
*/
|
|
BOOL SAVE_fn_bAnalyseCurrentUsedVersion( void )
|
|
{
|
|
char a_cVersion[1000];
|
|
long lNumberOfVersions;
|
|
long lVersion;
|
|
long lVersionIndex;
|
|
long lLastUnusedVersion = -1;
|
|
|
|
|
|
/*
|
|
* get used versions
|
|
*/
|
|
lNumberOfVersions = SAVE_fn_lGetUsedVersion( a_cVersion );
|
|
if (lNumberOfVersions == 0)
|
|
{
|
|
SAVE_g_lNextVersionNumber = 0;
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* check for hole in version number
|
|
*/
|
|
lVersion = 0;
|
|
for (lVersionIndex = 0; lVersion < lNumberOfVersions; lVersionIndex ++)
|
|
{
|
|
if (a_cVersion[ lVersionIndex ])
|
|
{
|
|
lVersion ++;
|
|
}
|
|
else
|
|
{
|
|
lLastUnusedVersion = lVersionIndex;
|
|
}
|
|
}
|
|
|
|
if (lLastUnusedVersion == -1)
|
|
{
|
|
SAVE_g_lNextVersionNumber = lNumberOfVersions;
|
|
}
|
|
else
|
|
{
|
|
for (lVersionIndex = 0; lVersionIndex < lLastUnusedVersion; lVersionIndex++)
|
|
{
|
|
if (a_cVersion[ lVersionIndex ])
|
|
{
|
|
if (!SAVE_fn_bDeleteVersion( lVersionIndex ))
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
lVersion = 0;
|
|
for (lVersionIndex = lLastUnusedVersion + 1; a_cVersion[ lVersionIndex ]; lVersionIndex ++)
|
|
{
|
|
if (!SAVE_fn_bRenameVersion( lVersionIndex, lVersion ++ ))
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
SAVE_g_lNextVersionNumber = lVersion;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
=======================================================================================
|
|
modified File functions
|
|
=======================================================================================
|
|
*/
|
|
|
|
/*
|
|
----------------------------------------------------------------------------------------
|
|
Description : Add Gamedata dir behind name if not already here and check if file
|
|
exist
|
|
szFile -> name to check
|
|
Returns (BOOL ) true if file exist
|
|
----------------------------------------------------------------------------------------
|
|
*/
|
|
BOOL SAVE_fn_bGetGameDataFile( char *szFile )
|
|
{
|
|
if (strnicmp( szFile, SAVE_g_szGameData, SAVE_g_lGameDataLength ) != 0)
|
|
{
|
|
memmove( szFile + SAVE_g_lGameDataLength + 1, szFile, strlen( szFile ));
|
|
memcpy ( szFile, SAVE_g_szGameData, SAVE_g_lGameDataLength );
|
|
*(szFile + SAVE_g_lGameDataLength) = '\\';
|
|
}
|
|
return ( _access( szFile, 0) == 0);
|
|
}
|
|
|
|
|
|
/*
|
|
----------------------------------------------------------------------------------------
|
|
Description : add file in array of file to save. check if file doesn't still exist
|
|
szFile -> name to add
|
|
----------------------------------------------------------------------------------------
|
|
*/
|
|
void SAVE_fn_vAddFile( char *_szFile, char _cNew )
|
|
{
|
|
long lFile;
|
|
/*
|
|
* check if file doesn't till exist in list
|
|
*/
|
|
for (lFile = 0; lFile < SAVE_gs_lNumberOfFiles; lFile++)
|
|
{
|
|
if (stricmp( _szFile, SAVE_gs_d_stFile[ lFile ].szName ) == 0 )
|
|
return;
|
|
}
|
|
/*
|
|
* Add file
|
|
*/
|
|
SAVE_gs_d_stFile[ SAVE_gs_lNumberOfFiles ].szName = (char *) malloc( strlen( _szFile ) + 1 );
|
|
strcpy( SAVE_gs_d_stFile[ SAVE_gs_lNumberOfFiles ].szName, _szFile );
|
|
SAVE_gs_d_stFile[ SAVE_gs_lNumberOfFiles ].cNew = _cNew;
|
|
SAVE_gs_lNumberOfFiles++;
|
|
}
|
|
|
|
|
|
/*
|
|
----------------------------------------------------------------------------------------
|
|
Description : delete file list
|
|
----------------------------------------------------------------------------------------
|
|
*/
|
|
void SAVE_fn_vFreeFileList( void )
|
|
{
|
|
long lFile;
|
|
|
|
if ( SAVE_gs_d_stFile != NULL)
|
|
{
|
|
for (lFile = 0; lFile < SAVE_gs_lNumberOfFiles; lFile++)
|
|
free ( SAVE_gs_d_stFile[ lFile ].szName );
|
|
|
|
free ( SAVE_gs_d_stFile );
|
|
SAVE_gs_d_stFile = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
----------------------------------------------------------------------------------------
|
|
Description : read all notification to buil list of files that would be modified
|
|
return (long ) : number of file in list
|
|
----------------------------------------------------------------------------------------
|
|
*/
|
|
long SAVE_fn_lGetNotifiedFileList( void )
|
|
{
|
|
unsigned int uiPos;
|
|
SCR_tdst_Ntfy_Description *p_stNtfy;
|
|
char szFile[ _MAX_PATH ];
|
|
char *p_szEndFile;
|
|
long lNbMaxFiles;
|
|
|
|
/*
|
|
* get number max of files and allocate array to store filenames
|
|
*/
|
|
lNbMaxFiles = SCR_g_st_Ntfy_Array.uiNumValues;
|
|
SAVE_gs_lNumberOfFiles = 0;
|
|
SAVE_gs_d_stFile = (SAVE_tdstFile *) malloc( (lNbMaxFiles + 1) * sizeof( SAVE_tdstFile ) );
|
|
|
|
/*
|
|
* add eventually modification file
|
|
*/
|
|
strcpy( szFile, "modiflst.txt" );
|
|
SAVE_fn_vAddFile( szFile, SAVE_fn_bGetGameDataFile( szFile ) ? 0 : 1 );
|
|
|
|
/*
|
|
* parse all notifications
|
|
*/
|
|
for (uiPos = 0; uiPos < (unsigned short) lNbMaxFiles; uiPos ++)
|
|
{
|
|
SCR_M_DyAr_GetNextElement(SCR_tdst_Ntfy_Description, uiPos, p_stNtfy, SCR_g_st_Ntfy_Array);
|
|
|
|
if (p_stNtfy == NULL)
|
|
break;
|
|
|
|
strcpy( szFile, p_stNtfy->a_szSectionName );
|
|
p_szEndFile = strchr( szFile, '^' );
|
|
if (p_szEndFile != NULL)
|
|
*p_szEndFile = 0;
|
|
|
|
SAVE_fn_vAddFile( szFile, SAVE_fn_bGetGameDataFile( szFile ) ? 0 : 1 );
|
|
}
|
|
|
|
return SAVE_gs_lNumberOfFiles;
|
|
}
|
|
|
|
|
|
/*
|
|
----------------------------------------------------------------------------------------
|
|
Description : create new tree with saved file
|
|
----------------------------------------------------------------------------------------
|
|
*/
|
|
BOOL SAVE_fn_bCreateNewVersion( void )
|
|
{
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
long lFile;
|
|
char szNewFile[ _MAX_PATH ];
|
|
char *p_szNewFile;
|
|
char *p_szEndPath;
|
|
FILE *hpFile;
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
|
|
SAVE_fn_vGetVersionDirName( SAVE_g_lNextVersionNumber, szNewFile );
|
|
p_szNewFile = szNewFile + strlen( szNewFile );
|
|
*p_szNewFile++ = '\\';
|
|
|
|
/*
|
|
* copy file that exist and are going to be modified
|
|
*/
|
|
for (lFile = 0; lFile < SAVE_gs_lNumberOfFiles; lFile ++)
|
|
{
|
|
if ( SAVE_gs_d_stFile[lFile].cNew == 0)
|
|
{
|
|
strcpy( p_szNewFile, SAVE_gs_d_stFile[ lFile ].szName + SAVE_g_lGameDataLength + 1 );
|
|
p_szEndPath = strrchr( szNewFile, '\\' );
|
|
*p_szEndPath = 0;
|
|
if ( !SAVE_fn_bCreateDirectory( szNewFile ) )
|
|
return FALSE;
|
|
*p_szEndPath = '\\';
|
|
if ( !CopyFile( SAVE_gs_d_stFile[ lFile ].szName, szNewFile, FALSE ) )
|
|
{
|
|
//char szMessage[ 512 ];
|
|
//sprintf( szMessage, "Can't copy %s to %s", SAVE_g_d_szFile[ lFile ], szNewFile );
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* create a file with all file that are going to be created
|
|
*/
|
|
strcpy( p_szNewFile, "delete.lst" );
|
|
if ((hpFile = fopen( szNewFile, "wt" )) == NULL)
|
|
return FALSE;
|
|
|
|
for (lFile = 0; lFile < SAVE_gs_lNumberOfFiles; lFile ++)
|
|
{
|
|
if ( SAVE_gs_d_stFile[lFile].cNew )
|
|
fprintf( hpFile, "%s\n", SAVE_gs_d_stFile[ lFile ].szName + SAVE_g_lGameDataLength + 1 );
|
|
}
|
|
fclose( hpFile );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
=======================================================================================
|
|
principal function
|
|
=======================================================================================
|
|
*/
|
|
|
|
/*
|
|
----------------------------------------------------------------------------------------
|
|
Description : make a copy of file that will be deleted.
|
|
----------------------------------------------------------------------------------------
|
|
*/
|
|
BOOL SAVE_fn_bGenerateACopyOfFilesBeforeModification( void )
|
|
{
|
|
SAVE_g_bContinue = TRUE;
|
|
|
|
if (SAVE_g_bGenerateIsActive == 2)
|
|
{
|
|
CString csFileName;
|
|
csFileName = M_GetMainApp()->m_csEditorDataPath + C_szInterfaceIniFile;
|
|
SAVE_g_bGenerateIsActive = GetPrivateProfileInt ("SecuritySave", "Active", 1, (char*)(LPCSTR) csFileName);
|
|
}
|
|
|
|
if ( !SAVE_g_bGenerateIsActive )
|
|
return TRUE;
|
|
|
|
if (SCR_g_st_Ntfy_Array.uiNumValues == 0)
|
|
return TRUE;
|
|
|
|
/*
|
|
* init
|
|
*/
|
|
SAVE_g_szGameData = fn_szGetGameDataPath();
|
|
SAVE_g_lGameDataLength = strlen( SAVE_g_szGameData );
|
|
|
|
if (SAVE_fn_bAnalyseCurrentUsedVersion())
|
|
{
|
|
if (SAVE_fn_lGetNotifiedFileList())
|
|
{
|
|
SAVE_fn_bCreateNewVersion();
|
|
SAVE_fn_vFreeFileList();
|
|
}
|
|
}
|
|
return SAVE_g_bContinue;
|
|
}
|
|
|
|
#endif /*ACTIVE_EDITOR*/ |