315 lines
8.7 KiB
C++
315 lines
8.7 KiB
C++
// File import/export for icons, cursors, and bitmaps
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include <direct.h>
|
|
#include <sys\stat.h>
|
|
|
|
#include "global.h"
|
|
#include "pbrush.h"
|
|
#include "pbrusdoc.h"
|
|
#include "pbrusfrm.h"
|
|
#include "bmobject.h"
|
|
#include "imgsuprt.h"
|
|
#include "imgwnd.h"
|
|
#include "imgfile.h"
|
|
#include "ferr.h"
|
|
#include "cmpmsg.h"
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static CHAR BASED_CODE THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
#include "memtrace.h"
|
|
|
|
// base for temp file names
|
|
const TCHAR BASED_CODE CFileSaver::c_szAps [] = TEXT("TMP");
|
|
|
|
/***************************************************************************/
|
|
|
|
BOOL FileExists(const TCHAR* szFileName)
|
|
{
|
|
CFileStatus fs;
|
|
return CFile::GetStatus(szFileName, fs) != 0;
|
|
}
|
|
|
|
/***************************************************************************/
|
|
|
|
BOOL RenameFile(const TCHAR* szOldName, const TCHAR* szNewName)
|
|
{
|
|
TRACE2("RenameFile: \"%s\" to \"%s\"\n", szOldName, szNewName);
|
|
|
|
TRY
|
|
{
|
|
if (FileExists(szNewName))
|
|
CFile::Remove(szNewName);
|
|
CFile::Rename(szOldName, szNewName);
|
|
}
|
|
CATCH(CFileException, e)
|
|
{
|
|
TRACE(TEXT("Rename failed!\n"));
|
|
theApp.SetFileError( IDS_ERROR_EXPORT, e->m_cause );
|
|
return FALSE;
|
|
}
|
|
END_CATCH
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/***************************************************************************/
|
|
|
|
CFileSaver::CFileSaver(const TCHAR* szFileName)
|
|
{
|
|
CString strDir = StripName(szFileName);
|
|
CString strTempDir;
|
|
|
|
GetTempPath( _MAX_PATH, strTempDir.GetBuffer( _MAX_PATH ) );
|
|
|
|
strTempDir.ReleaseBuffer();
|
|
|
|
GetTempFileName( strTempDir, c_szAps, 0, m_strTempName.GetBuffer( _MAX_PATH ));
|
|
GetTempFileName( strTempDir, c_szAps, 0, m_strBackupName.GetBuffer( _MAX_PATH ));
|
|
|
|
CFile::Remove( m_strTempName );
|
|
CFile::Remove( m_strBackupName );
|
|
|
|
m_strName = szFileName;
|
|
m_strTempName = strDir + StripPath( m_strTempName );
|
|
m_strBackupName = strDir + StripPath( m_strBackupName );
|
|
}
|
|
|
|
/***************************************************************************/
|
|
|
|
CFileSaver::~CFileSaver()
|
|
{
|
|
if (FileExists(m_strTempName))
|
|
CFile::Remove(m_strTempName);
|
|
|
|
if (FileExists(m_strBackupName))
|
|
CFile::Remove(m_strBackupName);
|
|
}
|
|
|
|
/***************************************************************************/
|
|
|
|
BOOL CFileSaver::CanSave() const
|
|
{
|
|
CFileStatus fs;
|
|
|
|
if ( CFile::GetStatus(m_strName, fs) != 0 )
|
|
{
|
|
if ((fs.m_attribute & CFile::readOnly) != 0)
|
|
{
|
|
theApp.SetFileError( IDS_ERROR_SAVE, ferrCantSaveReadOnly);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/***************************************************************************/
|
|
|
|
BOOL CFileSaver::Finish()
|
|
{
|
|
if (FileExists(m_strName) != 0)
|
|
{
|
|
if (!RenameFile(m_strName, m_strBackupName))
|
|
{
|
|
CFile::Remove(m_strTempName);
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// no backup was made since the "original" didn't exists,
|
|
// wipe out the name so we don't delete the file later...
|
|
|
|
m_strBackupName.Empty();
|
|
}
|
|
|
|
if (!RenameFile(m_strTempName, m_strName))
|
|
{
|
|
if (!m_strBackupName.IsEmpty() &&
|
|
RenameFile(m_strBackupName, m_strName))
|
|
{
|
|
CFile::Remove(m_strTempName);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if (!m_strBackupName.IsEmpty())
|
|
CFile::Remove(m_strBackupName);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/***************************************************************************/
|
|
/* strrchrs() -- find the last instance in a string of any one of
|
|
** a set of characters. Return a pointer into the string at
|
|
** the matchpoint. Analogous to strrchr() in the CRT.
|
|
*/
|
|
|
|
TCHAR *strrchrs(TCHAR *szText, TCHAR * szSSet)
|
|
{
|
|
register TCHAR *pchSSet;
|
|
register TCHAR *pchStep;
|
|
register TCHAR *pchLast = NULL;
|
|
|
|
if ((NULL == szText) || (NULL == szSSet))
|
|
return NULL;
|
|
for (pchStep = szText; TEXT('\0') != *pchStep; pchStep = CharNext(pchStep))
|
|
for (pchSSet = szSSet; TEXT('\0') != *pchSSet; pchSSet = CharNext(pchSSet))
|
|
if ((pchSSet[0] == pchStep[0]) && (
|
|
#ifndef UNICODE
|
|
!IsDBCSLeadByte((CHAR)pchSSet[0]) ||
|
|
#endif // UNICODE
|
|
(pchSSet[1] == pchStep[1])))
|
|
pchLast = pchStep;
|
|
return pchLast;
|
|
}
|
|
|
|
/***************************************************************************/
|
|
/* MkPath() -- Make any directories necessary to ensure that a
|
|
** directory name passed in exists. Essentially, if the
|
|
** argument exists and is a directory, return success. If
|
|
** not, strip off the last path component and recurse,
|
|
** creating the directories on returning up the stack.
|
|
*/
|
|
int MkPath(TCHAR *szPath)
|
|
{
|
|
TCHAR *pchSlash;
|
|
TCHAR chSep;
|
|
DWORD dwAtts;
|
|
|
|
//Does it exist?
|
|
if ( (dwAtts = GetFileAttributes(szPath)) & FILE_ATTRIBUTE_DIRECTORY )
|
|
{
|
|
return 0;
|
|
}
|
|
else if (-1 != dwAtts)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
//Can we create it?
|
|
else
|
|
{
|
|
if ( CreateDirectory(szPath, NULL))
|
|
return 0;
|
|
// are we out of path components?
|
|
else
|
|
{
|
|
if (NULL == (pchSlash = strrchrs(szPath, TEXT("\\/"))))
|
|
return -1;
|
|
// Can we make its parent directory?
|
|
else
|
|
{
|
|
if ((chSep = *pchSlash), (*pchSlash = TEXT('\0')), MkPath(szPath))
|
|
{
|
|
#ifndef DEBUG
|
|
*pchSlash = chSep;
|
|
#endif
|
|
return -1;
|
|
}
|
|
// Can we make it now that we've made its parent?
|
|
else
|
|
{
|
|
if ((*pchSlash = chSep), (TEXT('\0') != pchSlash[1]))
|
|
{
|
|
if (!CreateDirectory (szPath, NULL))
|
|
{
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
else //don't try trailing slash
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/***************************************************************************/
|
|
|
|
void MkFullPath(CString& strFullPath, const CString& strRelPath,
|
|
BOOL bPathOnly)
|
|
{
|
|
strFullPath.Empty();
|
|
|
|
ASSERT(strRelPath.GetLength() > 0);
|
|
if (strRelPath[0] != TEXT('\\') &&
|
|
(strRelPath.GetLength() <= 1 || (
|
|
#ifndef UNICODE
|
|
!IsDBCSLeadByte((CHAR)strRelPath[0]) &&
|
|
#endif // UNICODE
|
|
strRelPath[1] != TEXT(':'))))
|
|
{
|
|
CHAR *szPathName = _getdcwd(0, NULL, 1);
|
|
#ifdef UNICODE
|
|
WCHAR *szPW = new WCHAR[lstrlenA (szPathName)+1];
|
|
AtoW (szPathName, szPW);
|
|
strFullPath = szPW;
|
|
delete szPW;
|
|
#else
|
|
strFullPath = szPathName;
|
|
#endif //UNICODE
|
|
free(szPathName);
|
|
|
|
if (strFullPath.Right(1) != TEXT('\\'))
|
|
strFullPath += (TCHAR)TEXT('\\');
|
|
}
|
|
|
|
if (bPathOnly)
|
|
{
|
|
int iLastSep = strRelPath.ReverseFind(TEXT('\\'));
|
|
if (iLastSep == -1)
|
|
iLastSep = strRelPath.GetLength();
|
|
strFullPath += strRelPath.Left(iLastSep);
|
|
}
|
|
else
|
|
{
|
|
strFullPath += strRelPath;
|
|
}
|
|
}
|
|
|
|
/***************************************************************************/
|
|
|
|
BOOL OpenSubFile(CFile& file, const CFileSaver& saver, UINT nOpenFlags,
|
|
CFileException* pError)
|
|
{
|
|
BOOL bResult = file.Open(saver.GetSafeName(), nOpenFlags, pError);
|
|
|
|
if (!bResult && (pError->m_cause == CFileException::badPath ||
|
|
pError->m_cause == CFileException::accessDenied))
|
|
{
|
|
CString strFileName = saver.GetRealName();
|
|
CString strPathName;
|
|
|
|
MkFullPath(strPathName, strFileName, TRUE);
|
|
strPathName.MakeUpper();
|
|
|
|
// suppress the message box upon return, but keep error info!
|
|
// (ie. user only needs one message box)
|
|
pError->m_cause = -pError->m_cause;
|
|
|
|
strFileName.MakeUpper();
|
|
int nResult = CmpMessageBoxPrintf(IDS_QUERY_MKDIR, AFX_IDS_APP_TITLE,
|
|
MB_YESNO | MB_ICONQUESTION,
|
|
(LPCTSTR)strPathName, (LPCTSTR) strFileName);
|
|
if (nResult == IDYES)
|
|
{
|
|
MkPath(strPathName.GetBuffer(strPathName.GetLength()));
|
|
strPathName.ReleaseBuffer();
|
|
bResult = file.Open(saver.GetSafeName(), nOpenFlags, pError);
|
|
}
|
|
}
|
|
|
|
return bResult;
|
|
}
|
|
|
|
/***************************************************************************/
|
|
|