// File import/export for icons, cursors, and bitmaps #include "stdafx.h" #include #include #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; } /***************************************************************************/