temporarily, to sort out new directory compare)
2005/06/22 Jochen Tucht Change recommended version of 7-Zip to 4.20
Remove noise from Nagbox
+2005/07/03 Jochen Tucht DIFFITEM has changed due to RFE [ 1205516 ]
+2005/07/04 Jochen Tucht New global ArchiveGuessFormat() checks for
+ formats to be handled by external command line
+ tools. These take precedence over Merge7z
+ internal handlers.
+2005/07/05 Jochen Tucht Move to Merge7z::Format::GetDefaultName() to
+ build intermediate filenames for multi-step
+ compression.
+2005/07/15 Jochen Tucht Remove external command line tool integration
+ for now. Rethink about it after 2.4 branch.
*/
// RCS ID line follows -- this is updated by CVS
#include "DirDoc.h"
#include "MainFrm.h"
#include "7zCommon.h"
+//#include "ExternalArchiveFormat.h"
#include "markdown.h"
#include <afxinet.h>
#include <shlwapi.h>
static char THIS_FILE[] = __FILE__;
#endif
+Merge7z::Format *ArchiveGuessFormat(LPCTSTR path)
+{
+ // Look for command line tool first
+ /*Merge7z::Format *pFormat;
+ if (CExternalArchiveFormat::GuessFormat(path, pFormat))
+ {
+ return pFormat;
+ }*/
+ // Default to Merge7z*.dll
+ return Merge7z->GuessFormat(path);
+}
+
/**
* @brief Self-initializing raw C character buffer class.
*/
}
/**
- * @brief Recursively delete folder.
+ * @brief Construct path to a temporary folder for pOwner, and clear the folder.
*/
-void CTempPath::Clear()
+CString NTAPI GetClearTempPath(LPVOID pOwner, LPCTSTR pchExt)
{
+ CString strPath;
+ strPath.Format
+ (
+ pOwner ? _T("%sWINMERGE.%08lX\\%08lX.%s") : _T("%sWINMERGE.%08lX"),
+ paths_GetTempPath(), GetCurrentProcessId(), pOwner, pchExt
+ );
// SHFileOperation expects a ZZ terminated list of paths!
- LPTSTR pchPath = m_strPath.GetBufferSetLength(lstrlen(m_strPath) + 1);
+ int cchPath = strPath.GetLength();
+ LPTSTR pchPath = strPath.GetBufferSetLength(cchPath + 1);
SHFILEOPSTRUCT fileop = {0, FO_DELETE, pchPath, 0, FOF_NOCONFIRMATION|FOF_SILENT|FOF_NOERRORUI, 0, 0, 0};
SHFileOperation(&fileop);
+ strPath.ReleaseBuffer(cchPath);
+ return strPath;
}
/**
- * @brief Prepare an additional sibling folder.
+ * @brief Delete head of temp path context list, and return its parent context.
*/
-void CTempPath::MakeSibling(LPCTSTR pchExt)
+CTempPathContext *CTempPathContext::DeleteHead()
{
- LPTSTR pchPath = m_strPath.GetBuffer(lstrlen(m_strPath) + lstrlen(pchExt) + 1);
- PathRenameExtension(pchPath, pchExt);
- m_strPath.ReleaseBuffer();
- Clear();
-}
-
-/**
- * @brief Prepare a temporary folder.
- */
-CTempPath::CTempPath(LPVOID pOwner)
-{
- m_strPath.Format
- (
- pOwner ? _T("%sWINMERGE.%08lX\\%08lX") : _T("%sWINMERGE.%08lX"),
- paths_GetTempPath(), GetCurrentProcessId(), pOwner
- );
- Clear();
+ CTempPathContext *pParent = m_pParent;
+ GetClearTempPath(this, _T("*"));
+ delete this;
+ return pParent;
}
/**
}
/**
- * @brief Guess 7z language file name from language id.
- */
-CString NTAPI LangFile7z()
-{
- CString langFile;
- if (HINSTANCE hinstLang = AfxGetResourceHandle())
- {
- WORD wLangID = 0;
- if (EnumResourceLanguages(hinstLang, RT_VERSION, MAKEINTRESOURCE(VS_VERSION_INFO), FindNextResLang, (LPARAM)&wLangID) == 0)
- {
- CRawString<TCHAR,4> sLng, sRgn;
- GetLocaleInfo(wLangID, LOCALE_SISO639LANGNAME, sLng.Data, sLng.Size);
- GetLocaleInfo(wLangID, LOCALE_SISO3166CTRYNAME, sRgn.Data, sRgn.Size);
- langFile.Format(_T("%s-%s"), sLng.Data, sRgn.Data);
- }
- }
- return langFile;
-}
-
-/**
* @brief Access dll functions through proxy.
*/
interface Merge7z *Merge7z::Proxy::operator->()
pCause
);
}
+ if (HINSTANCE hinstLang = AfxGetResourceHandle())
+ {
+ WORD wLangID = 0;
+ if (EnumResourceLanguages(hinstLang, RT_VERSION, MAKEINTRESOURCE(VS_VERSION_INFO), FindNextResLang, (LPARAM)&wLangID) == 0)
+ {
+ flags |= wLangID << 16;
+ }
+ }
((interface Merge7z *)Merge7z[1])->Initialize(flags);
-#if DllBuild_Merge7z >= 9
- ((interface Merge7z *)Merge7z[1])->LoadLang(LangFile7z());
-#endif
}
return ((interface Merge7z *)Merge7z[1]);
}
/**
* @brief Tell Merge7z we are going to enumerate just 1 item.
*/
-UINT CompressSingleFile::Open()
+UINT SingleItemEnumerator::Open()
{
return 1;
}
/**
* @brief Pass information about the item to Merge7z.
*/
-Merge7z::Envelope *CompressSingleFile::Enum(Item &item)
+Merge7z::Envelope *SingleItemEnumerator::Enum(Item &item)
{
item.Mask.Item = item.Mask.Name|item.Mask.FullPath|item.Mask.Recurse;
item.Name = Name;
}
/**
- * @brief CompressSingleFile constructor. Called like a function.
+ * @brief SingleFileEnumerator constructor.
*/
-CompressSingleFile::CompressSingleFile(LPCTSTR path, LPCTSTR FullPath, LPCTSTR Name)
+SingleItemEnumerator::SingleItemEnumerator(LPCTSTR path, LPCTSTR FullPath, LPCTSTR Name)
: FullPath(FullPath)
, Name(Name)
{
- if (Merge7z::Format *piHandler = Merge7z->GuessFormat(path))
- {
- HWND hwndOwner = CWnd::GetSafeOwner()->GetSafeHwnd();
- piHandler->CompressArchive(hwndOwner, path, this);
- }
- else
- {
- AfxMessageBox(IDS_UNKNOWN_ARCHIVE_FORMAT, MB_ICONEXCLAMATION);
- }
}
/**
if (!di.isSideLeft())
{
// Item is present on right side, i.e. folder is implied
- m_rgImpliedFoldersRight[di.sSubdir] = PVOID(1);
+ m_rgImpliedFoldersRight[di.sRightSubdir] = PVOID(1);
}
}
else
if (!di.isSideRight())
{
// Item is present on left side, i.e. folder is implied
- m_rgImpliedFoldersLeft[di.sSubdir] = PVOID(1);
+ m_rgImpliedFoldersLeft[di.sLeftSubdir] = PVOID(1);
}
}
}
return 0;
}
+ bool isSideLeft = di.isSideLeft();
+ bool isSideRight = di.isSideRight();
+
Envelope *envelope = new Envelope;
- envelope->Name = di.sfilename;
- if (di.sSubdir.GetLength())
+ const CString &sFilename = m_bRight ? di.sRightFilename : di.sLeftFilename;
+ const CString &sSubdir = m_bRight ? di.sRightSubdir : di.sLeftSubdir;
+ envelope->Name = sFilename;
+ if (sSubdir.GetLength())
{
envelope->Name.Insert(0, '\\');
- envelope->Name.Insert(0, di.sSubdir);
+ envelope->Name.Insert(0, sSubdir);
}
- envelope->FullPath = di.sfilename;
+ envelope->FullPath = sFilename;
envelope->FullPath.Insert(0, '\\');
envelope->FullPath.Insert(0, m_bRight ?
di.getRightFilepath(pDoc->GetRightBasePath()) :
if (m_bRight)
{
// Enumerating items on right side
- if (di.isSideLeft())
+ if (isSideLeft)
{
// Item is missing on right side
- PVOID &implied = m_rgImpliedFoldersRight[di.sSubdir];
+ PVOID &implied = m_rgImpliedFoldersRight[di.sLeftSubdir];
if (!implied)
{
// Folder is not implied by some other file, and has
// not been enumerated so far, so enumerate it now!
- envelope->Name = di.sSubdir;
+ envelope->Name = di.sLeftSubdir;
envelope->FullPath = di.getLeftFilepath(pDoc->GetLeftBasePath());
implied = PVOID(2); // Don't enumerate same folder twice!
+ isSideLeft = false;
}
}
}
else
{
// Enumerating items on left side
- if (di.isSideRight())
+ if (isSideRight)
{
// Item is missing on left side
- PVOID &implied = m_rgImpliedFoldersLeft[di.sSubdir];
+ PVOID &implied = m_rgImpliedFoldersLeft[di.sRightSubdir];
if (!implied)
{
// Folder is not implied by some other file, and has
// not been enumerated so far, so enumerate it now!
- envelope->Name = di.sSubdir;
+ envelope->Name = di.sRightSubdir;
envelope->FullPath = di.getRightFilepath(pDoc->GetRightBasePath());
implied = PVOID(2); // Don't enumerate same folder twice!
+ isSideRight = false;
}
}
}
}
+ if (m_bRight ? isSideLeft : isSideRight)
+ {
+ return envelope;
+ }
+
if (m_strFolderPrefix.GetLength())
{
envelope->Name.Insert(0, '\\');
item.FullPath = envelope->FullPath;
return envelope;
}
- //<winerror.h>
+
+/**
+ * @brief Apply appropriate handlers from left to right.
+ */
+bool CDirView::DirItemEnumerator::MultiStepCompressArchive(LPCTSTR path)
+{
+ DeleteFile(path);
+ Merge7z::Format *piHandler = ArchiveGuessFormat(path);
+ if (piHandler)
+ {
+ HWND hwndOwner = CWnd::GetSafeOwner()->GetSafeHwnd();
+ CString pathIntermediate;
+ SysFreeString(Assign(pathIntermediate, piHandler->GetDefaultName(hwndOwner, path)));
+ CString pathPrepend = path;
+ pathPrepend.ReleaseBuffer(pathPrepend.ReverseFind('\\') + 1);
+ pathIntermediate.Insert(0, pathPrepend);
+ bool bDone = MultiStepCompressArchive(pathIntermediate);
+ if (bDone)
+ {
+ piHandler->CompressArchive(hwndOwner, path,
+ &SingleItemEnumerator(path, pathIntermediate));
+ DeleteFile(pathIntermediate);
+ }
+ else
+ {
+ piHandler->CompressArchive(hwndOwner, path, this);
+ }
+ return true;
+ }
+ return false;
+}
+
/**
* @brief Generate archive from DirView items.
*/
//_T("z|*.z|")
_T("zip|*.zip|")
_T("jar (zip)|*.jar|")
+ _T("ear (zip)|*.ear|")
+ _T("war (zip)|*.war|")
_T("xpi (zip)|*.xpi|")
//_T("rar|*.rar|")
_T("tar|*.tar|")
+ _T("tar.z|*.tar.z|")
_T("tar.gz|*.tar.gz|")
_T("tar.bz2|*.tar.bz2|")
+ //_T("tz|*.tz|")
+ _T("tgz|*.tgz|")
+ _T("tbz2|*.tbz2|")
+ //_T("lzh|*.lzh|")
//_T("cab|*.cab|")
//_T("arj|*.arj|")
//_T("deb|*.deb|")
//_T("rpm|*.rpm|")
//_T("cpio|*.cpio|")
- _T("|")
+ //_T("|")
);
+ CString strFilter; // = CExternalArchiveFormat::GetOpenFileFilterString();
+ strFilter.Insert(0, _T_Filter);
+ strFilter += _T("|");
// Make CFileDialog static to preserve settings across invocations:
static CFileDialog dlg
(
0,
0,
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_NOREADONLYRETURN,
- _T_Filter
+ strFilter
);
dlg.m_ofn.nFilterIndex = AfxGetApp()->GetProfileInt(_T_Merge7z, _T_FilterIndex, 1);
// Use extension from current filter as default extension:
AfxGetApp()->WriteProfileInt(_T_Merge7z, _T_FilterIndex, dlg.m_ofn.nFilterIndex);
}
}
- if (path)
+ if (path && !MultiStepCompressArchive(path))
{
- LPCTSTR pathFinal = 0;
- CString strPathIntermediate;
- if (StrRStrI(path, 0, _T(".tar.")) == PathFindExtension(path) - 4)
- {
- // Extension is preceeded by .tar:
- // - Keep full path in pathFinal for actual compression.
- // - Cut off extension to produce an intermediate tar first.
- strPathIntermediate = pathFinal = path;
- path = strPathIntermediate.GetBufferSetLength(strPathIntermediate.ReverseFind('.'));
- }
- if (Merge7z::Format *piHandler = Merge7z->GuessFormat(path))
- {
- HWND hwndOwner = CWnd::GetSafeOwner()->GetSafeHwnd();
- piHandler->CompressArchive(hwndOwner, path, this);
- }
- else
- {
- AfxMessageBox(IDS_UNKNOWN_ARCHIVE_FORMAT, MB_ICONEXCLAMATION);
- }
- if (pathFinal)
- {
- // Compress the intermediate tar to pathFinal, then delete it.
- CompressSingleFile(pathFinal, path);
- DeleteFile(path);
- }
+ AfxMessageBox(IDS_UNKNOWN_ARCHIVE_FORMAT, MB_ICONEXCLAMATION);
}
#ifdef _DEBUG
afxDump << m_rgImpliedFoldersLeft;
cchBuffer +=
(
m_bRight ? di.getRightFilepath(sLeftRootPath) : di.getLeftFilepath(sRightRootPath)
- ).GetLength() + di.sfilename.GetLength() + 2;
+ ).GetLength() + (m_bRight ? di.sRightFilename : di.sLeftFilename).GetLength() + 2;
}
}
LPTSTR pchBuffer = strBuffer.GetBufferSetLength(cchBuffer);
pchBuffer,
_T("%s\\%s"),
m_bRight ? di.getRightFilepath(sLeftRootPath) : di.getLeftFilepath(sRightRootPath),
- di.sfilename
+ m_bRight ? di.sRightFilename : di.sLeftFilename
) + 1;
}
}
extern Merge7z::Proxy Merge7z;
-class CTempPath
+Merge7z::Format *ArchiveGuessFormat(LPCTSTR);
+
+CString NTAPI GetClearTempPath(LPVOID pOwner, LPCTSTR pchExt);
+
+/**
+ * @brief temp path context
+ */
+class CTempPathContext
{
- CString m_strPath;
public:
- operator LPCTSTR()
- {
- return m_strPath;
- }
- CTempPath(LPVOID);
- void Clear();
- void MakeSibling(LPCTSTR);
+ CTempPathContext *m_pParent;
+ CString m_strLeftDisplayRoot;
+ CString m_strRightDisplayRoot;
+ CString m_strLeftRoot;
+ CString m_strRightRoot;
+ CTempPathContext *DeleteHead();
};
/**
- * @brief Merge7z::DirItemEnumerator to compress a single file.
- *
- * Class has no extra leading C in its name because it is used like a function.
+ * @brief Merge7z::DirItemEnumerator to compress a single item.
*/
-class CompressSingleFile : public Merge7z::DirItemEnumerator
+class SingleItemEnumerator : public Merge7z::DirItemEnumerator
{
LPCTSTR FullPath;
LPCTSTR Name;
public:
virtual UINT Open();
virtual Merge7z::Envelope *Enum(Item &);
- CompressSingleFile(LPCTSTR path, LPCTSTR FullPath, LPCTSTR Name = _T(""));
+ SingleItemEnumerator(LPCTSTR path, LPCTSTR FullPath, LPCTSTR Name = _T(""));
};
/**
CMapStringToPtr m_rgImpliedFoldersRight;
// helper methods
DIFFITEM Next();
+ bool MultiStepCompressArchive(LPCTSTR);
public:
enum
{
void NTAPI Recall7ZipMismatchError();
DWORD NTAPI VersionOf7z(BOOL bLocal = FALSE);
-CString NTAPI LangFile7z();
/**
* @brief assign BSTR to CString, and return BSTR for optional SysFreeString()
{
UpdateVersion(di, dfi);
ASSERT(&dfi == &di.left || &dfi == &di.right);
- CString spath = &dfi == &di.left ? di.getLeftFilepath(GetNormalizedLeft()) :
- di.getRightFilepath(GetNormalizedRight());
- CString filepath = paths_ConcatPath(spath, di.sfilename);
+ CString filepath
+ (
+ &dfi == &di.left
+ ? paths_ConcatPath(di.getLeftFilepath(GetNormalizedLeft()), di.sLeftFilename)
+ : paths_ConcatPath(di.getRightFilepath(GetNormalizedRight()), di.sRightFilename)
+ );
dfi.Update(filepath);
GuessCodepageEncoding(filepath, &dfi.unicoding, &dfi.codepage, m_bGuessEncoding);
}
void CDiffContext::UpdateVersion(DIFFITEM & di, DiffFileInfo & dfi) const
{
// Check only binary files
- LPCTSTR ext = PathFindExtension(di.sfilename);
dfi.version = _T("");
dfi.bVersionChecked = true;
if (di.isDirectory())
return;
- if (!CheckFileForVersion(ext))
- return;
-
CString spath;
if (&dfi == &di.left)
{
if (di.isSideRight())
return;
+ LPCTSTR ext = PathFindExtension(di.sLeftFilename);
+ if (!CheckFileForVersion(ext))
+ return;
spath = di.getLeftFilepath(GetNormalizedLeft());
+ spath = paths_ConcatPath(spath, di.sLeftFilename);
}
else
{
ASSERT(&dfi == &di.right);
if (di.isSideLeft())
return;
+ LPCTSTR ext = PathFindExtension(di.sRightFilename);
+ if (!CheckFileForVersion(ext))
+ return;
spath = di.getRightFilepath(GetNormalizedRight());
+ spath = paths_ConcatPath(spath, di.sRightFilename);
}
- CString filepath = paths_ConcatPath(spath, di.sfilename);
- dfi.version = GetFixedFileVersion(filepath);
+ dfi.version = GetFixedFileVersion(spath);
}
/** @brief Forward call to retrieve plugin info (winds up in DirDoc) */
CString sPath;
if (!isSideRight())
{
- sPath = sLeftRoot;
- if (sSubdir.GetLength())
- {
- sPath = paths_ConcatPath(sPath, sSubdir);
- }
+ sPath = paths_ConcatPath(sLeftRoot, sLeftSubdir);
}
return sPath;
}
CString sPath;
if (!isSideLeft())
{
- sPath = sRightRoot;
- if (sSubdir.GetLength())
- {
- sPath = paths_ConcatPath(sPath, sSubdir);
- }
+ sPath = paths_ConcatPath(sRightRoot, sRightSubdir);
}
return sPath;
}
int diffcode;
- DIFFCODE() : diffcode(0) { }
- DIFFCODE(int diffcode) : diffcode(diffcode) { }
+ DIFFCODE(int diffcode = 0) : diffcode(diffcode) { }
// file/directory
bool isDirectory() const { return ((diffcode & DIFFCODE::DIRFLAG) == DIFFCODE::DIR); }
{
DiffFileInfo left; /**< Fileinfo for left file */
DiffFileInfo right; /**< Fileinfo for right file */
- CString sfilename; /**< Filename (without path!) */
- CString sSubdir; //*< Common subdirectory from root of comparison */
+ CString sLeftFilename; /**< Filename (without path!) */
+ CString sRightFilename; /**< Filename (without path!) */
+ CString sLeftSubdir; //*< Common subdirectory from root of comparison */
+ CString sRightSubdir; //*< Common subdirectory from root of comparison */
int nsdiffs; /**< Amount of non-ignored differences */
int ndiffs; /**< Total amount of differences */
bool casesensitive = false;
int depth = myStruct->bRecursive ? -1 : 0;
- CString subdir; // blank to start at roots specified in diff context
paths.SetLeft(myStruct->context->GetNormalizedLeft());
paths.SetRight(myStruct->context->GetNormalizedRight());
else
{
myStruct->context->m_pCompareStats->SetCompareState(CompareStats::STATE_COLLECT);
- DirScan_GetItems(paths, subdir, &itemList, casesensitive, depth, myStruct->context, myStruct->m_pAbortgate);
-
+ CString subdir; // blank to start at roots specified in diff context
+#ifdef _DEBUG
+ _CrtMemState memStateBefore;
+ _CrtMemState memStateAfter;
+ _CrtMemState memStateDiff;
+ _CrtMemCheckpoint(&memStateBefore);
+#endif
+ DirScan_GetItems(paths, subdir, subdir, &itemList, casesensitive, depth, myStruct->context, myStruct->m_pAbortgate);
+#ifdef _DEBUG
+ _CrtMemCheckpoint(&memStateAfter);
+ _CrtMemDifference(&memStateDiff, &memStateBefore, &memStateAfter);
+ _CrtMemDumpStatistics(&memStateDiff);
+#endif
myStruct->context->m_pCompareStats->SetCompareState(CompareStats::STATE_COMPARE);
DirScan_CompareItems(itemList, myStruct->context, myStruct->m_pAbortgate);
myStruct->context->m_pCompareStats->SetCompareState(CompareStats::STATE_READY);
{
static const TCHAR backslash[] = _T("\\");
- if (di.isSideLeft())
+ if (!di.isSideRight())
{
// Compare file to itself to detect encoding
left = pCtxt->GetNormalizedLeft() + backslash;
- if (!di.sSubdir.IsEmpty())
- left += di.sSubdir + backslash;
- left += di.sfilename;
- right = left;
+ if (!di.sLeftSubdir.IsEmpty())
+ left += di.sLeftSubdir + backslash;
+ left += di.sLeftFilename;
+ if (di.isSideLeft())
+ right = left;
}
- else if (di.isSideRight())
+ if (!di.isSideLeft())
{
// Compare file to itself to detect encoding
right = pCtxt->GetNormalizedRight() + backslash;
- if (!di.sSubdir.IsEmpty())
- right += di.sSubdir + backslash;
- right += di.sfilename;
- left = right;
- }
- else
- {
- left = pCtxt->GetNormalizedLeft() + backslash;
- right = pCtxt->GetNormalizedRight() + backslash;
- if (!di.sSubdir.IsEmpty())
- {
- left += di.sSubdir + backslash;
- right += di.sSubdir + backslash;
- }
- left += di.sfilename;
- right += di.sfilename;
+ if (!di.sRightSubdir.IsEmpty())
+ right += di.sRightSubdir + backslash;
+ right += di.sRightFilename;
+ if (di.isSideRight())
+ left = right;
}
}
{
CString sFullDest(destPath);
sFullDest += _T("\\");
- if (!di.sSubdir.IsEmpty())
- sFullDest += di.sSubdir + _T("\\");
- sFullDest += di.sfilename;
+ if (!di.sLeftSubdir.IsEmpty())
+ sFullDest += di.sLeftSubdir + _T("\\");
+ sFullDest += di.sLeftFilename;
fileOp.AddDestFile(sFullDest);
}
GetItemFileNames(sel, slFile, srFile);
{
CString sFullDest(destPath);
sFullDest += _T("\\");
- if (!di.sSubdir.IsEmpty())
- sFullDest += di.sSubdir + _T("\\");
- sFullDest += di.sfilename;
+ if (!di.sRightSubdir.IsEmpty())
+ sFullDest += di.sRightSubdir + _T("\\");
+ sFullDest += di.sRightFilename;
fileOp.AddDestFile(sFullDest);
}
GetItemFileNames(sel, slFile, srFile);
sFullDest += _T("\\");
if (GetDocument()->GetRecursive())
{
- if (!di.sSubdir.IsEmpty())
- sFullDest += di.sSubdir + _T("\\");
+ if (!di.sLeftSubdir.IsEmpty())
+ sFullDest += di.sLeftSubdir + _T("\\");
}
- sFullDest += di.sfilename;
+ sFullDest += di.sLeftFilename;
act.dest = sFullDest;
GetItemFileNames(sel, slFile, srFile);
sFullDest += _T("\\");
if (GetDocument()->GetRecursive())
{
- if (!di.sSubdir.IsEmpty())
- sFullDest += di.sSubdir + _T("\\");
+ if (!di.sRightSubdir.IsEmpty())
+ sFullDest += di.sRightSubdir + _T("\\");
}
- sFullDest += di.sfilename;
+ sFullDest += di.sRightFilename;
act.dest = sFullDest;
GetItemFileNames(sel, slFile, srFile);
*/
void CDirView::UpdateCopiedItems(ActionList & actionList)
{
+ CDirDoc *pDoc = GetDocument();
while (actionList.GetCount()>0)
{
ActionList::action act = actionList.actions.RemoveHead();
POSITION diffpos = GetItemKey(act.idx);
- const DIFFITEM & di = GetDocument()->GetDiffByKey(diffpos);
+ const DIFFITEM & di = pDoc->GetDiffByKey(diffpos);
if (actionList.atype == ActionList::ACT_COPY)
{
// Copy files and folders
- CDirDoc *pDoc = GetDocument();
pDoc->SetDiffSide(DIFFCODE::BOTH, act.idx);
// Folders don't have compare flag set!!
// Move files and folders
// If unique item is moved, don't bother updating statuses,
// just remove from list
- CDirDoc *pDoc = GetDocument();
if (actionList.atype == ActionList::ACT_MOVE_LEFT)
{
if (di.isSideLeft())
// Delete files and folders
// If both items or unique item is deleted, don't bother updating
// statuses, just remove from list
- CDirDoc *pDoc = GetDocument();
if (actionList.atype == ActionList::ACT_DEL_LEFT)
{
if (di.isSideLeft())
else
{
const DIFFITEM & di = GetDocument()->GetDiffByKey(diffpos);
- const CString relpath = paths_ConcatPath(di.sSubdir, di.sfilename);
+ const CString leftrelpath = paths_ConcatPath(di.sLeftSubdir, di.sLeftFilename);
+ const CString rightrelpath = paths_ConcatPath(di.sRightSubdir, di.sRightFilename);
const CString & leftpath = GetDocument()->GetLeftBasePath();
const CString & rightpath = GetDocument()->GetRightBasePath();
- strLeft = paths_ConcatPath(leftpath, relpath);
- strRight = paths_ConcatPath(rightpath, relpath);
+ strLeft = paths_ConcatPath(leftpath, leftrelpath);
+ strRight = paths_ConcatPath(rightpath, rightrelpath);
}
}
*/
void CDirView::GetItemFileNames(int sel, PathContext * paths) const
{
- ASSERT(paths);
- POSITION diffpos = GetItemKey(sel);
- if (diffpos == (POSITION)SPECIAL_ITEM_POS)
- {
- paths->SetLeft(_T(""));
- paths->SetRight(_T(""));
- }
- else
- {
- const DIFFITEM & di = GetDocument()->GetDiffByKey(diffpos);
- const CString relpath = paths_ConcatPath(di.sSubdir, di.sfilename);
- const CString & leftpath = GetDocument()->GetLeftBasePath();
- const CString & rightpath = GetDocument()->GetRightBasePath();
- CString strLeft = paths_ConcatPath(leftpath, relpath);
- CString strRight = paths_ConcatPath(rightpath, relpath);
- paths->SetLeft(strLeft);
- paths->SetRight(strRight);
- }
+ CString strLeft;
+ CString strRight;
+ GetItemFileNames(sel, strLeft, strRight);
+ paths->SetLeft(strLeft);
+ paths->SetRight(strRight);
}
/// Open selected file on specified side
, m_statusCursor(NULL)
, m_bReuseCloses(FALSE)
, m_bMarkedRescan(FALSE)
+, m_pTempPathContext(NULL)
+, m_cchLeftRoot(0)
{
DIFFOPTIONS options = {0};
CMergeDoc * pMergeDoc = m_MergeDocs.GetNext(pos);
pMergeDoc->DirDocClosing(this);
}
-
// Delete all temporary folders belonging to this document
- CTempPath(this);
+ while (m_pTempPathContext)
+ {
+ m_pTempPathContext = m_pTempPathContext->DeleteHead();
+ }
}
/**
* Previous compare context is first free'd.
* @param [in] paths Paths to compare
* @param [in] bRecursive If TRUE subdirectories are included to compare.
- * @return TRUE if initialisation succeeds.
*/
-BOOL CDirDoc::InitCompare(const PathContext & paths, BOOL bRecursive)
+void CDirDoc::InitCompare(const PathContext & paths, BOOL bRecursive, BOOL bInitRootLength, CTempPathContext *pTempPathContext)
{
- BOOL bRet = FALSE;
-
- if (m_pCtxt != NULL)
- delete m_pCtxt;
+ // Anything that can go wrong here will yield an exception.
+ // Default implementation of operator new() never returns NULL.
+ delete m_pCtxt;
if (m_pCompareStats == NULL)
m_pCompareStats = new CompareStats();
m_pCtxt = new CDiffContext(paths.GetLeft(), paths.GetRight());
-
- if (m_pCtxt != NULL && m_pCompareStats != NULL)
+
+ if (pTempPathContext)
+ {
+ ApplyLeftDisplayRoot(pTempPathContext->m_strLeftDisplayRoot);
+ ApplyRightDisplayRoot(pTempPathContext->m_strRightDisplayRoot);
+ pTempPathContext->m_pParent = m_pTempPathContext;
+ m_pTempPathContext = pTempPathContext;
+ m_pTempPathContext->m_strLeftRoot = m_pCtxt->GetLeftPath();
+ m_pTempPathContext->m_strRightRoot = m_pCtxt->GetRightPath();
+ }
+
+ if (bInitRootLength)
{
- m_bRecursive = bRecursive;
- // All plugin management is done by our plugin manager
- m_pCtxt->m_piPluginInfos = &m_pluginman;
- bRet = TRUE;
+ m_cchLeftRoot = m_pCtxt->GetLeftPath().GetLength();
}
- return bRet;
+
+ m_bRecursive = bRecursive;
+ // All plugin management is done by our plugin manager
+ m_pCtxt->m_piPluginInfos = &m_pluginman;
+}
+
+/**
+ * @brief Tell if user may use ".." and move to parents directory
+ *
+ * @return No : upward RESTRICTED
+ * ParentIsRegularPath : upward ENABLED
+ * ParentIsTempPath : upward ENABLED
+ */
+CDirDoc::AllowUpwardDirectory::ReturnCode CDirDoc::AllowUpwardDirectory()
+{
+ return
+ (
+ GetLeftBasePath().GetLength() > m_cchLeftRoot
+ ? AllowUpwardDirectory::ParentIsRegularPath
+ : m_pTempPathContext && m_pTempPathContext->m_pParent
+ ? AllowUpwardDirectory::ParentIsTempPath
+ : AllowUpwardDirectory::No
+ );
}
/**
m_pDirView->SetRedraw(FALSE);
// If non-recursive compare, add special item(s)
- if (!m_bRecursive)
+ if (!m_bRecursive || m_pTempPathContext && m_pTempPathContext->m_pParent)
cnt += m_pDirView->AddSpecialItems();
int alldiffs=0;
if (path1 == current.getLeftFilepath(GetLeftBasePath()) &&
path2 == current.getRightFilepath(GetRightBasePath()) &&
- file1 == current.sfilename)
+ file1 == current.sLeftFilename &&
+ file2 == current.sRightFilename)
{
return currentPos;
}
// clear diff display
ASSERT(m_pDirView);
- m_pDirView->ReusingDirView();
+ m_pDirView->DeleteAllDisplayItems();
// hide the floating state bar
CDirFrame *pf = m_pDirView->GetParentFrame();
delete m_pCtxt;
m_pCtxt = NULL;
+ while (m_pTempPathContext)
+ {
+ m_pTempPathContext = m_pTempPathContext->DeleteHead();
+ }
+
return TRUE;
}
if (!m_strLeftDesc.IsEmpty())
sText = m_strLeftDesc;
else
+ {
sText = m_pCtxt->GetLeftPath();
+ ApplyLeftDisplayRoot(sText);
+ }
nPane = 0;
}
else
if (!m_strRightDesc.IsEmpty())
sText = m_strRightDesc;
else
+ {
sText = m_pCtxt->GetRightPath();
+ ApplyRightDisplayRoot(sText);
+ }
nPane = 1;
}
}
/**
+ * @brief Replace internal root by display root (left)
+ */
+void CDirDoc::ApplyLeftDisplayRoot(CString &sText)
+{
+ if (m_pTempPathContext)
+ {
+ sText.Delete(0, m_pTempPathContext->m_strLeftRoot.GetLength());
+ sText.Insert(0, m_pTempPathContext->m_strLeftDisplayRoot);
+ }
+}
+
+/**
+ * @brief Replace internal root by display root (right)
+ */
+void CDirDoc::ApplyRightDisplayRoot(CString &sText)
+{
+ if (m_pTempPathContext)
+ {
+ sText.Delete(0, m_pTempPathContext->m_strRightRoot.GetLength());
+ sText.Insert(0, m_pTempPathContext->m_strRightDisplayRoot);
+ }
+}
+
+/**
* @brief Store a plugin setting for specified file comparison
*/
void CDirDoc::SetPluginPrediffSetting(const CString & filteredFilenames, int newsetting)
else
{
// PathCompactPath() supported in versions 4.71 and higher
- if (GetDllVersion(_T("shlwapi.dll")) >= PACKVERSION(4,71))
- {
- // Combine title from file/dir names
- TCHAR *pszLeftFile;
- TCHAR *pszRightFile;
- CString sLeftFile;
- CString sRightFile;
- CRect rcClient;
- CString strTitle;
- const TCHAR strSeparator[] = _T(" - ");
- CClientDC lDC(m_pDirView);
-
- m_pDirView->GetClientRect(&rcClient);
- const DWORD width = rcClient.right / 3;
-
- sLeftFile = m_pCtxt->GetLeftPath();
- pszLeftFile = sLeftFile.GetBuffer(MAX_PATH);
-
- if (PathCompactPath(lDC.GetSafeHdc(), pszLeftFile, width))
- strTitle = pszLeftFile;
- else
- strTitle = m_pCtxt->GetLeftPath();
-
- sLeftFile.ReleaseBuffer();
- strTitle += strSeparator;
-
- sRightFile = m_pCtxt->GetRightPath();
- pszRightFile = sRightFile.GetBuffer(MAX_PATH);
-
- if (PathCompactPath(lDC.GetSafeHdc(), pszRightFile, width))
- strTitle += pszRightFile;
- else
- strTitle += m_pCtxt->GetRightPath();
- sRightFile.ReleaseBuffer();
-
- CDocument::SetTitle(strTitle);
- }
+ // According to
+ // "http://members.ozemail.com.au/~geoffch/samples/win32/shell/shlwapi/functions/index.html",
+ // PathCompactPath() is supported since 4.70. Anyway, as we link to shlwapi import library,
+ // we wouldn't be running if any one of the functions we link to weren't implemented. This
+ // means there is no point in checking shlwapi.dll version here.
+
+ // Combine title from file/dir names
+ TCHAR *pszLeftFile;
+ TCHAR *pszRightFile;
+ CString sLeftFile;
+ CString sRightFile;
+ CRect rcClient;
+ CString strTitle;
+ const TCHAR strSeparator[] = _T(" - ");
+ CClientDC lDC(m_pDirView);
+
+ m_pDirView->GetClientRect(&rcClient);
+ const DWORD width = rcClient.right / 3;
+
+ sLeftFile = m_pCtxt->GetLeftPath();
+ pszLeftFile = sLeftFile.GetBuffer(MAX_PATH);
+
+ if (PathCompactPath(lDC.GetSafeHdc(), pszLeftFile, width))
+ strTitle = pszLeftFile;
else
- {
- CString title;
- VERIFY(title.LoadString(IDS_DIRECTORY_WINDOW_TITLE));
- CDocument::SetTitle(title);
- }
+ strTitle = m_pCtxt->GetLeftPath();
+
+ sLeftFile.ReleaseBuffer();
+ strTitle += strSeparator;
+
+ sRightFile = m_pCtxt->GetRightPath();
+ pszRightFile = sRightFile.GetBuffer(MAX_PATH);
+
+ if (PathCompactPath(lDC.GetSafeHdc(), pszRightFile, width))
+ strTitle += pszRightFile;
+ else
+ strTitle += m_pCtxt->GetRightPath();
+ sRightFile.ReleaseBuffer();
+
+ CDocument::SetTitle(strTitle);
}
}
class DirDocFilterGlobal;
class DirDocFilterByExtension;
class CustomStatusCursor;
-
+class CTempPathContext;
/////////////////////////////////////////////////////////////////////////////
// CDirDoc document
// Attributes
public:
+ CTempPathContext *m_pTempPathContext;
// Operations
public:
BOOL CloseMergeDocs();
// Implementation
public:
- BOOL InitCompare(const PathContext & paths, BOOL bRecursive);
+ void InitCompare(const PathContext & paths, BOOL bRecursive, BOOL bSetRootLength, CTempPathContext *);
void Rescan();
BOOL GetRecursive() { return m_bRecursive; }
BOOL GetReadOnly(BOOL bLeft) const;
void AbortCurrentScan();
bool IsCurrentScanAbortable() const;
void SetDescriptions(const CString &strLeftDesc, const CString &strRightDesc);
+ void ApplyLeftDisplayRoot(CString &);
+ void ApplyRightDisplayRoot(CString &);
void SetPluginPrediffSetting(const CString & filteredFilenames, int newsetting);
void FetchPluginInfos(const CString& filteredFilenames,
CString GetRightBasePath() const { return m_pCtxt->GetNormalizedRight(); }
void RemoveDiffByKey(POSITION key) { m_pCtxt->RemoveDiff(key); }
void SetMarkedRescan() {m_bMarkedRescan = TRUE; }
+ struct AllowUpwardDirectory
+ {
+ enum ReturnCode
+ {
+ No,
+ ParentIsRegularPath,
+ ParentIsTempPath
+ };
+ };
+ AllowUpwardDirectory::ReturnCode AllowUpwardDirectory();
protected:
CDiffWrapper m_diffWrapper;
PluginManager m_pluginman;
BOOL m_bReuseCloses; /**< Are we closing because of reuse? */
BOOL m_bMarkedRescan; /**< If TRUE next rescan scans only marked items */
+ int m_cchLeftRoot; /**< Don't go upward any further */
};
//{{AFX_INSERT_LOCATION}}
static int collstr(const CString & s1, const CString & s2, bool casesensitive);
static void StoreDiffResult(DIFFITEM &di, CDiffContext * pCtxt,
const DiffFileData * pDiffFileData);
-static void AddToList(CString sDir, const fentry * lent, const fentry * rent,
+static void AddToList(const CString & sLeftDir, const CString & sRightDir, const fentry * lent, const fentry * rent,
int code, DiffItemList * pList, CDiffContext *pCtxt);
static void UpdateDiffItem(DIFFITEM & di, BOOL & bExists, CDiffContext *pCtxt);
/** @brief CALL_MEMBER_FN calls a method through a pointer to a method */
#define CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember))
+/**
+ * @brief Help minimize memory footprint by sharing CStringData if possible.
+ *
+ * Use OPTIMIZE_SHARE_CSTRINGDATA to conditionally include code that is merely
+ * intended to minimize memory footprint by having two CStrings share one
+ * CStringData if possible. The rule is that semantics must be identical
+ * regardless of whether OPTIMIZE_SHARE_CSTRINGDATA(X) expands to X or to
+ * nothing. If you suspect some bug to be related to this kind of optimization,
+ * then you can simply change OPTIMIZE_SHARE_CSTRINGDATA to expand to nothing,
+ * recompile, and see if bug disappears.
+ */
+#define OPTIMIZE_SHARE_CSTRINGDATA(X) X
/**
* @brief Collect file- and directory-names to list.
* @param [in] piAbortable Interface allowing compare to be aborted
* @return 1 normally, -1 if compare was aborted
*/
-int DirScan_GetItems(const PathContext &paths, const CString & subdir, DiffItemList *pList,
+int DirScan_GetItems(const PathContext &paths, const CString & leftsubdir, const CString & rightsubdir, DiffItemList *pList,
bool casesensitive, int depth, CDiffContext * pCtxt, IAbortable * piAbortable)
{
static const TCHAR backslash[] = _T("\\");
CString sLeftDir = paths.GetLeft();
CString sRightDir = paths.GetRight();
- CString subprefix;
- if (!subdir.IsEmpty())
+ CString leftsubprefix;
+ CString rightsubprefix;
+ if (!leftsubdir.IsEmpty())
{
- sLeftDir += backslash + subdir;
- sRightDir += backslash + subdir;
- subprefix = subdir + backslash;
+ sLeftDir += backslash + leftsubdir;
+ sRightDir += backslash + rightsubdir;
+ leftsubprefix = leftsubdir + backslash;
+ // minimize memory footprint by having left/rightsubprefix share CStringData if possible
+ rightsubprefix = OPTIMIZE_SHARE_CSTRINGDATA
+ (
+ (LPCTSTR)leftsubdir == (LPCTSTR)rightsubdir ? leftsubprefix :
+ ) rightsubdir + backslash;
}
fentryArray leftDirs, leftFiles, rightDirs, rightFiles;
// Handle directories
// i points to current directory in left list (leftDirs)
// j points to current directory in right list (rightDirs)
+
+ bool bTreatDirAsEqual
+ (
+ leftDirs.GetSize() == 1
+ && rightDirs.GetSize() == 1
+ && leftFiles.GetSize() == 0
+ && rightFiles.GetSize() == 0
+ );
+
int i=0, j=0;
while (1)
{
TRACE(_T("Candidate left: leftDirs[i]=%s\n"), (LPCTSTR)leftDirs[i].name);
if (j<rightDirs.GetSize())
TRACE(_T("Candidate right: rightDirs[j]=%s\n"), (LPCTSTR)rightDirs[j].name);
- if (i<leftDirs.GetSize() && (j==rightDirs.GetSize() || collstr(leftDirs[i].name, rightDirs[j].name, casesensitive)<0))
+ if (!bTreatDirAsEqual)
{
- int nDiffCode = DIFFCODE::LEFT | DIFFCODE::DIR;
-
- // Advance left pointer over left-only entry, and then retest with new pointers
- AddToList(subdir, &leftDirs[i], 0, nDiffCode, pList, pCtxt);
- ++i;
- continue;
- }
- if (j<rightDirs.GetSize() && (i==leftDirs.GetSize() || collstr(leftDirs[i].name, rightDirs[j].name, casesensitive)>0))
- {
- int nDiffCode = DIFFCODE::RIGHT | DIFFCODE::DIR;
-
- // Advance right pointer over right-only entry, and then retest with new pointers
- AddToList(subdir, 0, &rightDirs[j], nDiffCode, pList, pCtxt);
- ++j;
- continue;
+ if (i<leftDirs.GetSize() && (j==rightDirs.GetSize() || collstr(leftDirs[i].name, rightDirs[j].name, casesensitive)<0))
+ {
+ int nDiffCode = DIFFCODE::LEFT | DIFFCODE::DIR;
+ AddToList(leftsubdir, rightsubdir, &leftDirs[i], 0, nDiffCode, pList, pCtxt);
+ // Advance left pointer over left-only entry, and then retest with new pointers
+ ++i;
+ continue;
+ }
+ if (j<rightDirs.GetSize() && (i==leftDirs.GetSize() || collstr(leftDirs[i].name, rightDirs[j].name, casesensitive)>0))
+ {
+ int nDiffCode = DIFFCODE::RIGHT | DIFFCODE::DIR;
+ AddToList(leftsubdir, rightsubdir, 0, &rightDirs[j], nDiffCode, pList, pCtxt);
+ // Advance right pointer over right-only entry, and then retest with new pointers
+ ++j;
+ continue;
+ }
}
if (i<leftDirs.GetSize())
{
ASSERT(j<rightDirs.GetSize());
- CString newsub = subprefix + leftDirs[i].name;
+ if (!depth)
+ {
+ // Non-recursive compare
+ // We are only interested about list of subdirectories to show - user can open them
+ // TODO: scan one level deeper to see if directories are identical/different
+ const int nDiffCode = DIFFCODE::BOTH | DIFFCODE::DIR;
+ AddToList(leftsubdir, rightsubdir, &leftDirs[i], &rightDirs[j], nDiffCode, pList, pCtxt);
+ }
+ else
{
- int nDiffCode = DIFFCODE::BOTH | DIFFCODE::DIR;
- if (!depth)
+ // Recursive compare
+ CString leftnewsub = leftsubprefix + leftDirs[i].name;
+ // minimize memory footprint by having left/rightnewsub share CStringData if possible
+ CString rightnewsub = OPTIMIZE_SHARE_CSTRINGDATA
+ (
+ (LPCTSTR)leftsubprefix == (LPCTSTR)rightsubprefix
+ && leftDirs[i].name == rightDirs[j].name ? leftnewsub :
+ ) rightsubprefix + rightDirs[j].name;
+ // Test against filter so we don't include contents of filtered out directories
+ // Also this is only place we can test for both-sides directories in recursive compare
+ if (!pCtxt->m_piFilterGlobal->includeDir(leftnewsub, rightnewsub))
{
- // Non-recursive compare
- // We are only interested about list of subdirectories to show - user can open them
- // TODO: scan one level deeper to see if directories are identical/different
- AddToList(subdir, &leftDirs[i], &rightDirs[j], nDiffCode, pList, pCtxt);
+ const int nDiffCode = DIFFCODE::BOTH | DIFFCODE::DIR | DIFFCODE::SKIPPED;
+ AddToList(leftsubdir, rightsubdir, &leftDirs[i], &rightDirs[j], nDiffCode, pList, pCtxt);
}
else
{
- // Recursive compare
- // Test against filter so we don't include contents of filtered out directories
- // Also this is only place we can test for both-sides directories in recursive compare
- if (!pCtxt->m_piFilterGlobal->includeDir(newsub))
+ // Scan recursively all subdirectories too, we are not adding folders
+ const int nDiffCode = DIFFCODE::BOTH | DIFFCODE::DIR | DIFFCODE::INCLUDED;
+ if (DirScan_GetItems(paths, leftnewsub, rightnewsub, pList, casesensitive,
+ depth - 1, pCtxt, piAbortable) == -1)
{
- nDiffCode |= DIFFCODE::SKIPPED;
- AddToList(subdir, &leftDirs[i], &rightDirs[j], nDiffCode, pList, pCtxt);
- }
- else
- {
- // Scan recursively all subdirectories too, we are not adding folders
- nDiffCode |= DIFFCODE::INCLUDED;
-
- if (DirScan_GetItems(paths, newsub, pList, casesensitive,
- depth - 1, pCtxt, piAbortable) == -1)
- {
- return -1;
- }
+ return -1;
}
}
}
if (i<leftFiles.GetSize() && (j==rightFiles.GetSize() ||
collstr(leftFiles[i].name, rightFiles[j].name, casesensitive) < 0))
{
- // Test against filter
- CString newsubfile = subprefix + leftFiles[i].name;
- int nDiffCode = DIFFCODE::LEFT | DIFFCODE::FILE;
- {
- AddToList(subdir, &leftFiles[i], 0, nDiffCode, pList, pCtxt);
- }
-
+ const int nDiffCode = DIFFCODE::LEFT | DIFFCODE::FILE;
+ AddToList(leftsubdir, rightsubdir, &leftFiles[i], 0, nDiffCode, pList, pCtxt);
// Advance left pointer over left-only entry, and then retest with new pointers
++i;
continue;
if (j<rightFiles.GetSize() && (i==leftFiles.GetSize() ||
collstr(leftFiles[i].name, rightFiles[j].name, casesensitive) > 0))
{
- // Test against filter
- CString newsubfile = subprefix + rightFiles[j].name;
- int nDiffCode = DIFFCODE::RIGHT | DIFFCODE::FILE;
- {
- AddToList(subdir, 0, &rightFiles[j], nDiffCode, pList, pCtxt);
- }
+ const int nDiffCode = DIFFCODE::RIGHT | DIFFCODE::FILE;
+ AddToList(leftsubdir, rightsubdir, 0, &rightFiles[j], nDiffCode, pList, pCtxt);
// Advance right pointer over right-only entry, and then retest with new pointers
++j;
continue;
if (i<leftFiles.GetSize())
{
ASSERT(j<rightFiles.GetSize());
- CString newsubfile = subprefix + leftFiles[i].name;
- int nDiffCode = DIFFCODE::BOTH | DIFFCODE::FILE;
-
- AddToList(subdir, &leftFiles[i], &rightFiles[j], nDiffCode, pList, pCtxt);
-
+ const int nDiffCode = DIFFCODE::BOTH | DIFFCODE::FILE;
+ AddToList(leftsubdir, rightsubdir, &leftFiles[i], &rightFiles[j], nDiffCode, pList, pCtxt);
++i;
++j;
continue;
void UpdateDiffItem(DIFFITEM & di, BOOL & bExists, CDiffContext *pCtxt)
{
struct _stat stats;
- CString leftpath;
- CString rightpath;
BOOL bLeftExists = FALSE;
BOOL bRightExists = FALSE;
bExists = TRUE;
- leftpath = di.getLeftFilepath(pCtxt->GetNormalizedLeft());
- leftpath = paths_ConcatPath(leftpath, di.sfilename);
- rightpath = di.getRightFilepath(pCtxt->GetNormalizedRight());
- rightpath = paths_ConcatPath(rightpath, di.sfilename);
+ CString leftpath = di.getLeftFilepath(pCtxt->GetNormalizedLeft());
+ leftpath = paths_ConcatPath(leftpath, di.sLeftFilename);
+ CString rightpath = di.getRightFilepath(pCtxt->GetNormalizedRight());
+ rightpath = paths_ConcatPath(rightpath, di.sRightFilename);
// Re-check if left/right sides still exists (or are added)
if (_tstat(leftpath, &stats) == 0)
// 1. Test against filters
if (di.isDirectory())
{
- if (!pCtxt->m_piFilterGlobal->includeDir(di.sfilename))
+ if (!pCtxt->m_piFilterGlobal->includeDir(di.sLeftFilename, di.sRightFilename))
di.diffcode |= DIFFCODE::SKIPPED;
else
di.diffcode |= DIFFCODE::INCLUDED;
}
else
{
- if (!pCtxt->m_piFilterGlobal->includeFile(di.sfilename))
+ if (!pCtxt->m_piFilterGlobal->includeFile(di.sLeftFilename, di.sRightFilename))
di.diffcode |= DIFFCODE::SKIPPED;
else
di.diffcode |= DIFFCODE::INCLUDED;
gLog.Write
(
LOGLEVEL::LCOMPAREDATA, _T("name=<%s>, leftdir=<%s>, rightdir=<%s>, code=%d"),
- (LPCTSTR)di.sfilename, (LPCTSTR)_T("di.left.spath"), (LPCTSTR)_T("di.right.spath"), di.diffcode
+ (LPCTSTR)di.sLeftFilename, (LPCTSTR)_T("di.left.spath"), (LPCTSTR)_T("di.right.spath"), di.diffcode
);
pCtxt->AddDiff(di);
}
/**
* @brief Add one compare item to list.
*/
-static void AddToList(CString sDir, const fentry * lent, const fentry * rent,
+static void AddToList(const CString & sLeftDir, const CString & sRightDir, const fentry * lent, const fentry * rent,
int code, DiffItemList * pList, CDiffContext *pCtxt)
{
// We must store both paths - we cannot get paths later
// change to identical
DIFFITEM di;
- di.left.unicoding = 0;
- di.left.codepage = 0;
- di.right.unicoding = 0;
- di.right.codepage = 0;
- if (!sDir.IsEmpty())
- di.sSubdir = sDir;
+ di.sLeftSubdir = sLeftDir;
+ di.sRightSubdir = sRightDir;
if (lent)
{
- di.sfilename = lent->name;
+ di.sLeftFilename = lent->name;
di.left.mtime = lent->mtime;
di.left.ctime = lent->ctime;
di.left.size = lent->size;
di.left.flags.attributes = lent->attrs;
}
+ else
+ {
+ // Don't break CDirView::DoCopyRightToLeft()
+ di.sLeftFilename = rent->name;
+ }
if (rent)
{
- di.sfilename = rent->name;
+ di.sRightFilename = OPTIMIZE_SHARE_CSTRINGDATA
+ (
+ di.sLeftFilename == rent->name ? di.sLeftFilename :
+ ) rent->name;
di.right.mtime = rent->mtime;
di.right.ctime = rent->ctime;
di.right.size = rent->size;
di.right.flags.attributes = rent->attrs;
}
+ else
+ {
+ // Don't break CDirView::DoCopyLeftToRight()
+ di.sRightFilename = lent->name;
+ }
di.diffcode = code;
gLog.Write
(
LOGLEVEL::LCOMPAREDATA, _T("name=<%s>, leftdir=<%s>, rightdir=<%s>, code=%d"),
- (LPCTSTR)di.sfilename, (LPCTSTR)_T("di.left.spath"), (LPCTSTR)_T("di.right.spath"), code
+ (LPCTSTR)di.sLeftFilename, (LPCTSTR)_T("di.left.spath"), (LPCTSTR)_T("di.right.spath"), code
);
pCtxt->m_pCompareStats->IncreaseTotalItems();
pList->AddDiff(di);
virtual bool ShouldAbort() = 0;
};
-int DirScan_GetItems(const PathContext &paths, const CString & subdir, DiffItemList * pLst,
+int DirScan_GetItems(const PathContext &paths, const CString & leftsubdir, const CString & rightsubdir, DiffItemList * pLst,
bool casesensitive, int depth, CDiffContext * pCtxt, IAbortable * piAbortable);
int DirScan_CompareItems(DiffItemList & list, CDiffContext * pCtxt, IAbortable * piAbortable);
}
/**
- * @brief Return nearest ancestor which is not a child window
- */
-static CWnd * GetNonChildAncestor(CWnd * w)
-{
- CWnd* parent = w;
- while (parent->GetStyle() & WS_CHILD)
- parent = parent->GetParent();
- return parent;
-}
-
-/**
* @brief Format context menu string and disable item if it cannot be applied.
*/
static void NTAPI FormatContextMenu(BCMenu *pPopup, UINT uIDItem, int n1, int n2 = 0, int n3 = 0)
if (!di.isDirectory() && !di.isBin() && !di.isSideLeft() && !di.isSideRight() && !di.isResultFiltered())
{
CString leftPath = di.getLeftFilepath(pDoc->GetLeftBasePath()) +
- _T("\\") + di.sfilename;
+ _T("\\") + di.sLeftFilename;
CString rightPath = di.getRightFilepath(pDoc->GetRightBasePath()) +
- _T("\\") + di.sfilename;
+ _T("\\") + di.sRightFilename;
CString filteredFilenames = leftPath + "|" + rightPath;
PackingInfo * unpacker;
PrediffingInfo * prediffer;
*/
void CDirView::OpenParentDirectory()
{
- const CString & left = GetDocument()->GetLeftBasePath();
- const CString & right = GetDocument()->GetRightBasePath();
+ CDirDoc *pDoc = GetDocument();
+ const CString & left = pDoc->GetLeftBasePath();
+ const CString & right = pDoc->GetRightBasePath();
CString leftParent = paths_GetParentPath(left);
CString rightParent = paths_GetParentPath(right);
if (paths_DoesPathExist(leftParent) == IS_EXISTING_DIR &&
- paths_DoesPathExist(rightParent) == IS_EXISTING_DIR &&
- AllowUpwardDirectory(left, right))
- mf->DoFileOpen(leftParent, rightParent,
- FFILEOPEN_NOMRU, FFILEOPEN_NOMRU, FALSE, GetDocument());
+ paths_DoesPathExist(rightParent) == IS_EXISTING_DIR) // &&
+ //(pDoc->AllowUpwardDirectory() || pDoc->m_pTempPathContext && pDoc->m_pTempPathContext->m_pParent))
+ {
+ switch (pDoc->AllowUpwardDirectory())
+ {
+ case CDirDoc::AllowUpwardDirectory::ParentIsRegularPath:
+ mf->DoFileOpen(leftParent, rightParent,
+ FFILEOPEN_NOMRU, FFILEOPEN_NOMRU, pDoc->GetRecursive(), pDoc);
+ break;
+ case CDirDoc::AllowUpwardDirectory::ParentIsTempPath:
+ pDoc->m_pTempPathContext = pDoc->m_pTempPathContext->DeleteHead();
+ mf->DoFileOpen(pDoc->m_pTempPathContext->m_strLeftRoot, pDoc->m_pTempPathContext->m_strRightRoot,
+ FFILEOPEN_NOMRU, FFILEOPEN_NOMRU, pDoc->GetRecursive(), pDoc);
+ break;
+ }
+ }
}
/**
DIFFITEM di = pDoc->GetDiffByKey((POSITION)diffpos);
+ PathContext paths;
+ GetItemFileNames(sel, &paths);
+
if (di.isDirectory() && (di.isSideLeft() == di.isSideRight()))
{
if (pDoc->GetRecursive())
{
// Open subfolders if non-recursive compare
// Don't add folders to MRU
- CString left, right;
- PathContext paths;
- GetItemFileNames(sel, &paths);
- mf->DoFileOpen(paths.GetLeft(), paths.GetRight(), FFILEOPEN_NOMRU, FFILEOPEN_NOMRU, FALSE, pDoc);
+ mf->DoFileOpen(paths.GetLeft(), paths.GetRight(), FFILEOPEN_NOMRU, FFILEOPEN_NOMRU, pDoc->GetRecursive(), pDoc);
}
break;
}
else if (di.isSideLeft() || di.isSideRight())
AfxMessageBox(IDS_FILEUNIQUE, MB_ICONINFORMATION);
+ else if (ArchiveGuessFormat(paths.GetLeft()) && ArchiveGuessFormat(paths.GetRight()))
+ {
+ // Open archives, not adding paths to MRU
+ mf->DoFileOpen(paths.GetLeft(), paths.GetRight(), FFILEOPEN_NOMRU, FFILEOPEN_NOMRU, pDoc->GetRecursive(), pDoc);
+ }
else if (di.isBin())
AfxMessageBox(IDS_FILEBINARY, MB_ICONSTOP);
else
BOOL bLeftRO = pDoc->GetReadOnly(TRUE);
BOOL bRightRO = pDoc->GetReadOnly(FALSE);
- PathContext paths;
- GetItemFileNames(sel, &paths);
mf->ShowMergeDoc(pDoc, paths.GetLeft(), paths.GetRight(),
bLeftRO, bRightRO,
di.left.codepage, di.right.codepage,
}
/**
- * @brief Prepare for reuse.
- *
- */
-void CDirView::ReusingDirView()
-{
- DeleteAllDisplayItems();
-}
-
-/**
* @brief Given key, get index of item which has it stored.
* This function searches from list in UI.
*/
if (sel != -1)
{
// let the user choose a handler
- CSelectUnpackerDlg dlg(GetDiffItem(sel).sfilename, this);
+ CSelectUnpackerDlg dlg(GetDiffItem(sel).sLeftFilename, this);
// create now a new infoUnpacker to initialize the manual/automatic flag
PackingInfo infoUnpacker;
dlg.SetInitialInfoHandler(&infoUnpacker);
if (paths_DoesPathExist(leftParent) == IS_EXISTING_DIR &&
paths_DoesPathExist(rightParent) == IS_EXISTING_DIR)
{
- BOOL bEnable = AllowUpwardDirectory(leftPath, rightPath);
+ BOOL bEnable = pDoc->AllowUpwardDirectory() != CDirDoc::AllowUpwardDirectory::No; //|| pDoc->m_pTempPathContext && pDoc->m_pTempPathContext->m_pParent;
AddParentFolderItem(bEnable);
retVal = 1;
}
}
/**
- * @brief Tell if user may use ".." and move to parents directory
- *
- * @return TRUE : upward ENABLED : both paths have the same rightmost subdirectory,
- * after we go upward, we may come back here with opening this subdirectory
- * FALSE : upward RESTRICTED : both paths have a different rightmost subdirectory,
- * the move can not be reversed (probably these are the original comparison directories)
- */
-BOOL CDirView::AllowUpwardDirectory(const CString &leftPath, const CString &rightPath)
-{
- int lastSegmentPos = leftPath.ReverseFind(_T('/'));
- if (lastSegmentPos == -1 || leftPath.ReverseFind(_T('\\')) > lastSegmentPos)
- lastSegmentPos = leftPath.ReverseFind(_T('\\'));
- ASSERT (lastSegmentPos != -1);
- lastSegmentPos ++;
-
- int nSegmentSize = leftPath.GetLength() - lastSegmentPos;
-
- return (leftPath.Right(nSegmentSize).CompareNoCase(rightPath.Right(nSegmentSize)) == 0);
-}
-
-/**
* @brief Add "Parent folder" ("..") item to directory view
*/
void CDirView::AddParentFolderItem(BOOL bEnable)
strPaths += di.getLeftFilepath(GetDocument()->GetLeftBasePath());
strPaths += _T("\\");
if (!di.isDirectory())
- strPaths += di.sfilename;
+ strPaths += di.sLeftFilename;
strPaths += _T("\r\n");
}
}
strPaths += di. getRightFilepath(pDoc->GetRightBasePath());
strPaths += _T("\\");
if (!di.isDirectory())
- strPaths += di.sfilename;
+ strPaths += di.sRightFilename;
strPaths += _T("\r\n");
}
}
strPaths += di.getLeftFilepath(pDoc->GetLeftBasePath());
strPaths += _T("\\");
if (!di.isDirectory())
- strPaths += di.sfilename;
+ strPaths += di.sLeftFilename;
strPaths += _T("\r\n");
}
strPaths += di. getRightFilepath(pDoc->GetRightBasePath());
strPaths += _T("\\");
if (!di.isDirectory())
- strPaths += di.sfilename;
+ strPaths += di.sRightFilename;
strPaths += _T("\r\n");
}
}
const DIFFITEM& di = GetDiffItem(sel);
if (!di.isDirectory())
{
- strPaths += di.sfilename;
+ strPaths += di.sLeftFilename;
strPaths += _T("\r\n");
}
}
int GetItemIndex(DWORD key);
// for populating list
void DeleteAllDisplayItems();
- void ReusingDirView();
void SetColumnWidths();
void SortColumnsAppropriately();
//DIFFITEM GetNextSelectedInd(int &ind);
DIFFITEM GetItemAt(int ind);
int AddSpecialItems();
- BOOL AllowUpwardDirectory(const CString &leftPath, const CString &rightPath);
void AddParentFolderItem(BOOL bEnable);
void RefreshOptions();
CMenu * m_pHeaderPopup;
BOOL m_bEscCloses; /**< Cached value for option for ESC closing window */
CFont *m_pFont; /**< User-selected font */
-
// Generated message map functions
afx_msg void OnColumnClick(NMHDR* pNMHDR, LRESULT* pResult);
afx_msg void OnContextMenu(CWnd*, CPoint point);
static CString ColFileNameGet(const CDiffContext *, const void *p) //sfilename
{
const DIFFITEM &di = *static_cast<const DIFFITEM*>(p);
- return di.sfilename;
+ return
+ (
+ di.sLeftFilename.IsEmpty() ? di.sRightFilename :
+ di.sRightFilename.IsEmpty() ? di.sLeftFilename :
+ di.sLeftFilename == di.sRightFilename ? di.sLeftFilename :
+ di.sLeftFilename + _T("|") + di.sRightFilename
+ );
}
static CString ColNameGet(const CDiffContext *, const void *p) //sfilename
{
}
static CString ColPathGet(const CDiffContext *, const void *p)
{
- const CString &r = *static_cast<const CString*>(p);
- if (r.IsEmpty())
- return _T(".");
- else
- return r;
+ const DIFFITEM &di = *static_cast<const DIFFITEM*>(p);
+ CString s = di.sRightSubdir;
+ const CString &t = di.sLeftSubdir;
+ int i = 0, j = 0;
+ do
+ {
+ int i_ahead = s.Find('\\', i);
+ int j_ahead = t.Find('\\', j);
+ int length_s = (i_ahead != -1 ? i_ahead : s.GetLength()) - i;
+ int length_t = (j_ahead != -1 ? j_ahead : t.GetLength()) - j;
+ if (length_s != length_t ||
+ !StrIsIntlEqual(FALSE, LPCTSTR(s) + i, LPCTSTR(t) + j, length_s))
+ {
+ CString u(LPCTSTR(t) + j, length_t + 1);
+ u.SetAt(length_t, '|');
+ s.Insert(i, u);
+ i_ahead += u.GetLength();
+ }
+ i = i_ahead + 1;
+ j = j_ahead + 1;
+ } while (i && j);
+ if (s.IsEmpty())
+ s = _T(".");
+ return s;
}
static CString ColStatusGet(const CDiffContext *pCtxt, const void *p)
{
* @name Functions to sort each type of column info.
*/
/* @{ */
-static int ColFileNameSort(const CDiffContext *, const void *p, const void *q)
+static int ColFileNameSort(const CDiffContext *pCtxt, const void *p, const void *q)
{
const DIFFITEM &ldi = *static_cast<const DIFFITEM *>(p);
const DIFFITEM &rdi = *static_cast<const DIFFITEM *>(q);
-
- if (ldi.isDirectory() && rdi.isDirectory())
- return ldi.sfilename.CompareNoCase(rdi.sfilename);
- else if (ldi.isDirectory() && !rdi.isDirectory())
+ if (ldi.isDirectory() && !rdi.isDirectory())
return -1;
- else if (!ldi.isDirectory() && rdi.isDirectory())
+ if (!ldi.isDirectory() && rdi.isDirectory())
return 1;
- else return ldi.sfilename.CompareNoCase(rdi.sfilename);
+ return ColFileNameGet(pCtxt, p).CompareNoCase(ColFileNameGet(pCtxt, q));
+ //return ldi.sLeftFilename.CompareNoCase(rdi.sLeftFilename);
}
static int ColNameSort(const CDiffContext *, const void *p, const void *q)
{
return lstrcmpi(PathFindExtension(r), PathFindExtension(s));
//return ColExtGet(pCtxt, p).CompareNoCase(ColExtGet(pCtxt, q));
}
+static int ColPathSort(const CDiffContext *pCtxt, const void *p, const void *q)
+{
+ return ColPathGet(pCtxt, p).CompareNoCase(ColPathGet(pCtxt, q));
+}
static int ColStatusSort(const CDiffContext *, const void *p, const void *q)
{
const DIFFITEM &ldi = *static_cast<const DIFFITEM *>(p);
DirColInfo g_cols[] =
{
{ _T("Name"), IDS_COLHDR_FILENAME, IDS_COLDESC_FILENAME, &ColFileNameGet, &ColFileNameSort, 0, 0, true, LVCFMT_LEFT },
- { _T("Path"), IDS_COLHDR_DIR, IDS_COLDESC_DIR, &ColPathGet, &ColNameSort, FIELD_OFFSET(DIFFITEM, sSubdir), 1, true, LVCFMT_LEFT },
+ { _T("Path"), IDS_COLHDR_DIR, IDS_COLDESC_DIR, &ColPathGet, &ColPathSort, 0, 1, true, LVCFMT_LEFT },
{ _T("Status"), IDS_COLHDR_RESULT, IDS_COLDESC_RESULT, &ColStatusGet, &ColStatusSort, 0, 2, true, LVCFMT_LEFT },
{ _T("Lmtime"), IDS_COLHDR_LTIMEM, IDS_COLDESC_LTIMEM, &ColTimeGet, &ColTimeSort, FIELD_OFFSET(DIFFITEM, left.mtime), 3, false, LVCFMT_LEFT },
{ _T("Rmtime"), IDS_COLHDR_RTIMEM, IDS_COLDESC_RTIMEM, &ColTimeGet, &ColTimeSort, FIELD_OFFSET(DIFFITEM, right.mtime), 4, false, LVCFMT_LEFT },
{ _T("Lctime"), IDS_COLHDR_LTIMEC, IDS_COLDESC_LTIMEC, &ColTimeGet, &ColTimeSort, FIELD_OFFSET(DIFFITEM, left.ctime), -1, false, LVCFMT_LEFT },
{ _T("Rctime"), IDS_COLHDR_RTIMEC, IDS_COLDESC_RTIMEC, &ColTimeGet, &ColTimeSort, FIELD_OFFSET(DIFFITEM, right.ctime), -1, false, LVCFMT_LEFT },
- { _T("Ext"), IDS_COLHDR_EXTENSION, IDS_COLDESC_EXTENSION, &ColExtGet, &ColExtSort, FIELD_OFFSET(DIFFITEM, sfilename), 5, true, LVCFMT_LEFT },
+ { _T("Ext"), IDS_COLHDR_EXTENSION, IDS_COLDESC_EXTENSION, &ColExtGet, &ColExtSort, FIELD_OFFSET(DIFFITEM, sLeftFilename), 5, true, LVCFMT_LEFT },
{ _T("Lsize"), IDS_COLHDR_LSIZE, IDS_COLDESC_LSIZE, &ColSizeGet, &ColSizeSort, FIELD_OFFSET(DIFFITEM, left.size), -1, false, LVCFMT_RIGHT },
{ _T("Rsize"), IDS_COLHDR_RSIZE, IDS_COLDESC_RSIZE, &ColSizeGet, &ColSizeSort, FIELD_OFFSET(DIFFITEM, right.size), -1, false, LVCFMT_RIGHT },
{ _T("Newer"), IDS_COLHDR_NEWER, IDS_COLDESC_NEWER, &ColNewerGet, &ColNewerSort, 0, -1, true, LVCFMT_LEFT },
public:
virtual BOOL includeFile(LPCTSTR szFileName) = 0;
virtual BOOL includeDir(LPCTSTR szDirName) = 0;
+ BOOL includeFile(LPCTSTR szFileName1, LPCTSTR szFileName2)
+ {
+ return
+ (
+ (szFileName1[0] == '\0' || includeFile(szFileName1))
+ && (szFileName2[0] == '\0' || includeFile(szFileName2))
+ );
+ }
+ BOOL includeDir(LPCTSTR szDirName1, LPCTSTR szDirName2)
+ {
+ return
+ (
+ (szDirName1[0] == '\0' || includeDir(szDirName1))
+ && (szDirName2[0] == '\0' || includeDir(szDirName2))
+ );
+ }
};
/**
// destroy the reg expression list
FreeRegExpList();
// Delete all temporary folders belonging to this process
- CTempPath(0);
+ GetClearTempPath(NULL, NULL);
delete m_pSyntaxColors;
}
BOOL CMainFrame::DoFileOpen(LPCTSTR pszLeft /*=NULL*/, LPCTSTR pszRight /*=NULL*/,
DWORD dwLeftFlags /*=0*/, DWORD dwRightFlags /*=0*/, BOOL bRecurse /*=FALSE*/, CDirDoc *pDirDoc/*=NULL*/)
{
+ // If the dirdoc we are supposed to use is busy doing a diff, bail out
+ if (IsComparing())
+ return FALSE;
+
+ if (pDirDoc && !pDirDoc->CloseMergeDocs())
+ return FALSE;
+
CString strLeft(pszLeft);
CString strRight(pszRight);
PackingInfo infoUnpacker;
BOOL bROLeft = dwLeftFlags & FFILEOPEN_READONLY;
BOOL bRORight = dwRightFlags & FFILEOPEN_READONLY;
- BOOL docNull;
-
- // If the dirdoc we are supposed to use is busy doing a diff, bail out
- if (IsComparing())
- return FALSE;
+ // jtuc: docNull used to be uninitialized so you couldn't tell whether
+ // pDirDoc->ReusingDirDoc() would be called for passed-in pDirDoc.
+ // However, pDirDoc->ReusingDirDoc() kills temp path contexts, and I
+ // need to avoid that. This is why I'm initializing docNull to TRUE here.
+ // Note that call to pDirDoc->CloseMergeDocs() above preserves me from
+ // keeping orphaned MergeDocs in that case.
+ BOOL docNull = TRUE;
// pop up dialog unless arguments exist (and are compatible)
PATH_EXISTENCE pathsType = GetPairComparability(strLeft, strRight);
bRecurse);
}
+ CTempPathContext *pTempPathContext = NULL;
try
{
// Handle archives using 7-zip
- if (Merge7z::Format *piHandler = Merge7z->GuessFormat(strLeft))
+ if (Merge7z::Format *piHandler = ArchiveGuessFormat(strLeft))
{
+ pTempPathContext = new CTempPathContext;
+ CString path = GetClearTempPath(pTempPathContext, _T("0"));
+ pTempPathContext->m_strLeftDisplayRoot = strLeft;
+ pTempPathContext->m_strRightDisplayRoot = strRight;
pathsType = IS_EXISTING_DIR;
- // Need DirDoc here to build temp path
- if (!pDirDoc)
- {
- pDirDoc = GetDirDocToShow(&docNull);
- }
if (strRight == strLeft)
{
strRight.Empty();
}
- CTempPath path = pDirDoc;
do
{
if FAILED(piHandler->DeCompressArchive(m_hWnd, strLeft, path))
break;
if (strLeft.Find(path) == 0)
{
- if (!::DeleteFile(strLeft))
- {
- LogErrorString(Fmt(_T("DeleteFile(%s) failed: %s"),
- strLeft, GetSysError(GetLastError())));
- }
- }
- strLeft.Delete(0, strLeft.ReverseFind('\\'));
- int dot = strLeft.ReverseFind('.');
- if (piHandler != &Merge7z->TarHandler && StrChr(_T("Tt"), strLeft[dot + 1]))
- {
- strLeft.GetBufferSetLength(dot + 2);
- strLeft += _T("ar");
- }
- else
- {
- strLeft.GetBufferSetLength(dot);
+ VERIFY(::DeleteFile(strLeft) || gLog::DeleteFileFailed(strLeft));
}
+ SysFreeString(Assign(strLeft, piHandler->GetDefaultName(m_hWnd, strLeft)));
+ strLeft.Insert(0, '\\');
strLeft.Insert(0, path);
- } while (piHandler = Merge7z->GuessFormat(strLeft));
+ } while (piHandler = ArchiveGuessFormat(strLeft));
strLeft = path;
- if (Merge7z::Format *piHandler = Merge7z->GuessFormat(strRight))
+ if (Merge7z::Format *piHandler = ArchiveGuessFormat(strRight))
{
- path.MakeSibling(_T(".1"));
+ path = GetClearTempPath(pTempPathContext, _T("1"));
do
{
if FAILED(piHandler->DeCompressArchive(m_hWnd, strRight, path))
break;;
if (strRight.Find(path) == 0)
{
- if (!::DeleteFile(strRight))
- {
- LogErrorString(Fmt(_T("DeleteFile(%s) failed: %s"),
- strRight, GetSysError(GetLastError())));
- }
- }
- strRight.Delete(0, strRight.ReverseFind('\\'));
- int dot = strRight.ReverseFind('.');
- if (piHandler != &Merge7z->TarHandler && StrChr(_T("Tt"), strRight[dot + 1]))
- {
- strRight.GetBufferSetLength(dot + 2);
- strRight += _T("ar");
- }
- else
- {
- strRight.GetBufferSetLength(dot);
+ VERIFY(::DeleteFile(strRight) || gLog::DeleteFileFailed(strRight));
}
+ SysFreeString(Assign(strRight, piHandler->GetDefaultName(m_hWnd, strRight)));
+ strRight.Insert(0, '\\');
strRight.Insert(0, path);
- } while (piHandler = Merge7z->GuessFormat(strRight));
+ } while (piHandler = ArchiveGuessFormat(strRight));
strRight = path;
}
else if (strRight.IsEmpty())
// not a Perry style patch: diff with itself...
strLeft = strRight = path;
}
+ else
+ {
+ pTempPathContext->m_strLeftDisplayRoot += _T("\\ORIGINAL");
+ pTempPathContext->m_strRightDisplayRoot += _T("\\ALTERED");
+ }
}
}
}
// Determine if we want new a dirview open now that we know if it was
// and archive. Don't open new dirview if we are comparing files.
+ BOOL bSetRootLenght = FALSE;
if (!pDirDoc)
{
if (pathsType == IS_EXISTING_DIR)
+ {
pDirDoc = GetDirDocToShow(&docNull);
+ bSetRootLenght = TRUE;
+ }
else
{
pDirDoc = (CDirDoc*)theApp.m_pDirTemplate->CreateNewDocument();
docNull = TRUE;
}
- }
+ }
if (!docNull)
{
if (pDirDoc)
{
PathContext paths(strLeft, strRight);
- if (pDirDoc->InitCompare(paths, bRecurse))
- {
- gLog.Write(LOGLEVEL::LNOTICE, _T("Open dirs: Left: %s\n\tRight: %s."),
- strLeft, strRight);
-
- pDirDoc->SetReadOnly(TRUE, bROLeft);
- pDirDoc->SetReadOnly(FALSE, bRORight);
- pDirDoc->SetDescriptions(m_strLeftDesc, m_strRightDesc);
- pDirDoc->SetTitle(NULL);
- m_strLeftDesc.Empty();
- m_strRightDesc.Empty();
-
- pDirDoc->Rescan();
- }
+ // Anything that can go wrong inside InitCompare() will yield an
+ // exception. There is no point in checking return value.
+ pDirDoc->InitCompare(paths, bRecurse, bSetRootLenght, pTempPathContext);
+ gLog.Write(LOGLEVEL::LNOTICE, _T("Open dirs: Left: %s\n\tRight: %s."),
+ strLeft, strRight);
+
+ pDirDoc->SetReadOnly(TRUE, bROLeft);
+ pDirDoc->SetReadOnly(FALSE, bRORight);
+ pDirDoc->SetDescriptions(m_strLeftDesc, m_strRightDesc);
+ pDirDoc->SetTitle(NULL);
+ m_strLeftDesc.Empty();
+ m_strRightDesc.Empty();
+
+ pDirDoc->Rescan();
}
}
else
CString leftFile = item.getLeftFilepath(pDoc->GetLeftBasePath());
if (!leftFile.IsEmpty())
- leftFile += _T("\\") + item.sfilename;
+ leftFile += _T("\\") + item.sLeftFilename;
CString rightFile = item.getRightFilepath(pDoc->GetRightBasePath());
if (!rightFile.IsEmpty())
- rightFile += _T("\\") + item.sfilename;
+ rightFile += _T("\\") + item.sRightFilename;
patcher.AddFiles(leftFile, rightFile);
}
sText = m_strLeftDesc;
}
else
+ {
sText = m_filePaths.GetLeft();
+ m_pDirDoc->ApplyLeftDisplayRoot(sText);
+ }
bChanges = m_ltBuf.IsModified();
nPane = 0;
}
sText = m_strRightDesc;
}
else
+ {
sText = m_filePaths.GetRight();
+ m_pDirDoc->ApplyRightDisplayRoot(sText);
+ }
bChanges = m_rtBuf.IsModified();
nPane = 1;
}