windows-nt/Source/XPSP1/NT/shell/osshell/accesory/mspaint/imgfile.cpp
2020-09-26 16:20:57 +08:00

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