return (nChanged != 0);
}
-String GetUnpackedFileExtension(const String& filepath, const PackingInfo* handler)
+String GetUnpackedFileExtension(const String& filteredFilenames, const PackingInfo* handler)
{
PluginInfo* plugin = nullptr;
if (handler->m_PluginOrPredifferMode == PLUGIN_MODE::PLUGIN_MANUAL && !handler->m_PluginName.empty())
plugin = CAllThreadsScripts::GetActiveSet()->GetPluginByName(nullptr, handler->m_PluginName.c_str());
else
- plugin = CAllThreadsScripts::GetActiveSet()->GetUnpackerPluginByFilter(filepath);
+ plugin = CAllThreadsScripts::GetActiveSet()->GetUnpackerPluginByFilter(filteredFilenames);
return plugin ? plugin->m_ext : _T("");
}
*/
bool Interactive(String & text, const wchar_t *TransformationEvent, int iFncChosen);
-String GetUnpackedFileExtension(const String& filepath, const PackingInfo* handler);
+String GetUnpackedFileExtension(const String& filteredFilenames, const PackingInfo* handler);
}
}
}
-void CHexMergeDoc::DoFileSaveAs(int nBuffer)
+void CHexMergeDoc::DoFileSaveAs(int nBuffer, bool packing)
{
const String &path = m_filePaths.GetPath(nBuffer);
String strPath;
title = _("Save Middle File As");
if (SelectFile(AfxGetMainWnd()->GetSafeHwnd(), strPath, false, path.c_str(), title))
{
- if (Try(m_pView[nBuffer]->SaveFile(strPath.c_str())) == IDCANCEL)
+ if (Try(m_pView[nBuffer]->SaveFile(strPath.c_str(), packing)) == IDCANCEL)
return;
if (path.empty())
{
#include "PathContext.h"
#include "FileLocation.h"
#include "IMergeDoc.h"
+#include "FileTransform.h"
class CDirDoc;
class CHexMergeFrame;
void DirDocClosing(CDirDoc * pDirDoc) override;
bool CloseNow() override;
bool GenerateReport(const String& sFileName) const override { return true; }
+ const PackingInfo* GetUnpacker() const { return &m_infoUnpacker; };
+ PackingInfo* GetUnpacker() { return &m_infoUnpacker; };
+ void SetUnpacker(const PackingInfo* infoUnpacker) override { if (infoUnpacker) m_infoUnpacker = *infoUnpacker; };
CHexMergeFrame * GetParentFrame() const;
void UpdateHeaderPath(int pane);
void RefreshOptions();
void MoveOnLoad(int nPane = -1, int nLineIndex = -1);
void CheckFileChanged(void) override;
String GetDescription(int pane) const { return m_strDesc[pane]; };
+ void SaveAs(int nBuffer, bool packing = true) { DoFileSaveAs(nBuffer, packing); }
private:
void DoFileSave(int nBuffer);
- void DoFileSaveAs(int nBuffer);
+ void DoFileSaveAs(int nBuffer, bool packing = true);
HRESULT LoadOneFile(int index, LPCTSTR filename, bool readOnly, const String& strDesc);
void RecompareAs(UINT id);
// Implementation data
CDirDoc * m_pDirDoc;
String m_strDesc[3]; /**< Left/right side description text */
BUFFERTYPE m_nBufferType[3];
+ PackingInfo m_infoUnpacker;
// Generated message map functions
protected:
#include "Merge.h"
#include "MainFrm.h"
#include "HexMergeView.h"
+#include "HexMergeDoc.h"
#include "OptionsDef.h"
#include "OptionsMgr.h"
#include "Environment.h"
CHexMergeView::CHexMergeView()
: m_pif(nullptr)
, m_nThisPane(0)
+, m_unpackerSubcode(0)
{
}
*/
HRESULT CHexMergeView::LoadFile(LPCTSTR path)
{
- HANDLE h = CreateFile(path, GENERIC_READ,
+ CHexMergeDoc *pDoc = static_cast<CHexMergeDoc *>(GetDocument());
+ String strTempFileName = path;
+ if (!FileTransform::Unpacking(pDoc->GetUnpacker(), &m_unpackerSubcode, strTempFileName, path))
+ return E_FAIL;
+ HANDLE h = CreateFile(strTempFileName.c_str(), GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
HRESULT hr = SE(h != INVALID_HANDLE_VALUE);
/**
* @brief Save file
*/
-HRESULT CHexMergeView::SaveFile(LPCTSTR path)
+HRESULT CHexMergeView::SaveFile(LPCTSTR path, bool packing)
{
// Warn user in case file has been changed by someone else
if (IsFileChangedOnDisk(path) == IMergeDoc::FileChange::Changed)
CloseHandle(h);
if (hr != S_OK)
return hr;
- hr = SE(CopyFile(sIntermediateFilename.c_str(), path, FALSE));
- if (hr != S_OK)
- return hr;
+
+ if (packing)
+ {
+ CHexMergeDoc* pDoc = static_cast<CHexMergeDoc*>(GetDocument());
+ if (!FileTransform::Packing(sIntermediateFilename, path, *pDoc->GetUnpacker(), m_unpackerSubcode))
+ {
+ String str = CMergeApp::GetPackingErrorMessage(m_nThisPane, pDoc->m_nBuffers, path, pDoc->GetUnpacker()->m_PluginName);
+ int answer = AfxMessageBox(str.c_str(), MB_OKCANCEL | MB_ICONWARNING);
+ if (answer == IDOK)
+ {
+ pDoc->SaveAs(m_nThisPane, false);
+ return S_OK;
+ }
+ return S_OK;
+ }
+ }
+ else
+ {
+ hr = SE(CopyFile(sIntermediateFilename.c_str(), path, FALSE));
+ if (hr != S_OK)
+ return hr;
+ }
+
m_fileInfo.Update(path);
SetSavePoint();
hr = SE(DeleteFile(sIntermediateFilename.c_str()));
protected: // create from serialization only
CHexMergeView();
DECLARE_DYNCREATE(CHexMergeView)
+ int m_unpackerSubcode;
public:
HRESULT LoadFile(LPCTSTR);
- HRESULT SaveFile(LPCTSTR);
+ HRESULT SaveFile(LPCTSTR, bool packing = true);
IHexEditorWindow *GetInterface() const { return m_pif; }
BYTE *GetBuffer(int);
int GetLength();
#include "UnicodeString.h"\r
\r
class CDirDoc;\r
+class PackingInfo;\r
\r
struct IMergeDoc\r
{\r
virtual bool GenerateReport(const String &path) const = 0;\r
virtual void DirDocClosing(CDirDoc * pDirDoc) = 0;\r
virtual void CheckFileChanged() = 0;\r
+ virtual void SetUnpacker(const PackingInfo *infoUnpacker) = 0;\r
};\r
\r
#include "FileLocation.h"
#include "Constants.h"
#include "DropHandler.h"
+#include "Environment.h"
#include <cmath>
#ifdef _DEBUG
, m_nBufferType{BUFFERTYPE::NORMAL, BUFFERTYPE::NORMAL, BUFFERTYPE::NORMAL}
, m_bRO{}
, m_nActivePane(-1)
+, m_unpackerSubcode{}
{
}
m_nBufferType[nBuffer] = BUFFERTYPE::NORMAL;
m_strDesc[nBuffer] = _T("");
- if (m_filePaths.GetSize() == 2)
- m_pImgMergeWindow->OpenImages(ucr::toUTF16(m_filePaths[0]).c_str(), ucr::toUTF16(m_filePaths[1]).c_str());
- else
- m_pImgMergeWindow->OpenImages(ucr::toUTF16(m_filePaths[0]).c_str(), ucr::toUTF16(m_filePaths[1]).c_str(), ucr::toUTF16(m_filePaths[2]).c_str());
-
+ OpenImages();
for (int pane = 0; pane < m_filePaths.GetSize(); ++pane)
- {
m_fileInfo[pane].Update(m_filePaths[pane]);
- RegisterDragDrop(m_pImgMergeWindow->GetPaneHWND(pane),
- new DropHandler(std::bind(&CImgMergeFrame::OnDropFiles, this, pane, std::placeholders::_1)));
- }
-
UpdateHeaderPath(nBuffer);
UpdateLastCompareResult();
}
}
else
{
- if (m_filePaths.GetSize() == 2)
- bResult = m_pImgMergeWindow->OpenImages(ucr::toUTF16(m_filePaths[0]).c_str(), ucr::toUTF16(m_filePaths[1]).c_str());
- else
- bResult = m_pImgMergeWindow->OpenImages(ucr::toUTF16(m_filePaths[0]).c_str(), ucr::toUTF16(m_filePaths[1]).c_str(), ucr::toUTF16(m_filePaths[2]).c_str());
+ bResult = OpenImages();
}
for (int pane = 0; pane < m_filePaths.GetSize(); ++pane)
if (CMergeApp::HandleReadonlySave(m_filePaths[pane], false, bApplyToAll) == IDCANCEL)
return false;
CMergeApp::CreateBackup(false, m_filePaths[pane]);
+ int savepoint = m_pImgMergeWindow->GetSavePoint(pane);
if (!m_pImgMergeWindow->SaveImage(pane))
{
String str = strutils::format_string2(_("Saving file failed.\n%1\n%2\nDo you want to:\n\t- use a different filename (Press OK)\n\t- abort the current operation (Press Cancel)?"), filename, GetSysError());
return DoFileSaveAs(pane);
return false;
}
+ if (filename != m_filePaths[pane])
+ {
+ if (!FileTransform::Packing(filename, m_filePaths[pane], m_infoUnpacker, m_unpackerSubcode[pane]))
+ {
+ // Restore save point
+ m_pImgMergeWindow->SetSavePoint(pane, savepoint);
+
+ String str = CMergeApp::GetPackingErrorMessage(pane, m_pImgMergeWindow->GetPaneCount(), m_filePaths[pane], m_infoUnpacker.m_PluginName);
+ int answer = AfxMessageBox(str.c_str(), MB_OKCANCEL | MB_ICONWARNING);
+ if (answer == IDOK)
+ return DoFileSaveAs(pane, false);
+ return false;
+ }
+ }
}
UpdateDiffItem(m_pDirDoc);
m_fileInfo[pane].Update(m_filePaths[pane]);
return true;
}
-bool CImgMergeFrame::DoFileSaveAs(int pane)
+bool CImgMergeFrame::DoFileSaveAs(int pane, bool packing)
{
const String &path = m_filePaths.GetPath(pane);
String strPath;
if (SelectFile(AfxGetMainWnd()->GetSafeHwnd(), strPath, false, path.c_str(), title))
{
std::wstring filename = ucr::toUTF16(strPath);
+ if (packing && !m_infoUnpacker.m_PluginName.empty())
+ {
+ String tempPath = env::GetTemporaryPath();
+ filename = ucr::toUTF16(env::GetTemporaryFileName(tempPath, _T("MRG_"), 0)
+ + paths::FindExtension(m_pImgMergeWindow->GetFileName(pane)));
+ }
+ int savepoint = m_pImgMergeWindow->GetSavePoint(pane);
if (!m_pImgMergeWindow->SaveImageAs(pane, filename.c_str()))
{
String str = strutils::format_string2(_("Saving file failed.\n%1\n%2\nDo you want to:\n\t- use a different filename (Press OK)\n\t- abort the current operation (Press Cancel)?"), strPath, GetSysError());
goto RETRY;
return false;
}
+ if (filename != strPath)
+ {
+ if (!FileTransform::Packing(filename, strPath, m_infoUnpacker, m_unpackerSubcode[pane]))
+ {
+ // Restore save point
+ m_pImgMergeWindow->SetSavePoint(pane, savepoint);
+
+ String str = CMergeApp::GetPackingErrorMessage(pane, m_pImgMergeWindow->GetPaneCount(), strPath, m_infoUnpacker.m_PluginName);
+ int answer = AfxMessageBox(str.c_str(), MB_OKCANCEL | MB_ICONWARNING);
+ if (answer == IDOK)
+ return DoFileSaveAs(pane, false);
+ return false;
+ }
+ }
if (path.empty())
{
// We are saving scratchpad (unnamed file)
{
if (!PromptAndSaveIfNeeded(true))
return;
- m_pImgMergeWindow->ReloadImages();
+ OpenImages();
for (int pane = 0; pane < m_filePaths.GetSize(); ++pane)
m_fileInfo[pane].Update(m_filePaths[pane]);
}
{
}
+bool CImgMergeFrame::OpenImages()
+{
+ bool bResult;
+ String filteredFilenames = strutils::join(m_filePaths.begin(), m_filePaths.end(), _T("|"));
+ String strTempFileName[3];
+ for (int pane = 0; pane < m_filePaths.GetSize(); ++pane)
+ {
+ strTempFileName[pane] = m_filePaths[pane];
+ if (!FileTransform::Unpacking(&m_infoUnpacker, &m_unpackerSubcode[pane], strTempFileName[pane], filteredFilenames))
+ return false;
+ }
+ if (m_filePaths.GetSize() == 2)
+ bResult = m_pImgMergeWindow->OpenImages(ucr::toUTF16(strTempFileName[0]).c_str(), ucr::toUTF16(strTempFileName[1]).c_str());
+ else
+ bResult = m_pImgMergeWindow->OpenImages(ucr::toUTF16(strTempFileName[0]).c_str(), ucr::toUTF16(strTempFileName[1]).c_str(), ucr::toUTF16(strTempFileName[2]).c_str());
+ return bResult;
+}
+
/**
* @brief Update associated diff item
*/
#include "LocationBar.h"
#include "FileLocation.h"
#include "MergeFrameCommon.h"
+#include "FileTransform.h"
class CDirDoc;
void UpdateAutoPaneResize();
void UpdateSplitter();
bool GenerateReport(const String& sFileName) const override;
+ void SetUnpacker(const PackingInfo* infoUnpacker) override { if (infoUnpacker) m_infoUnpacker = *infoUnpacker; };
void DoAutoMerge(int dstPane);
bool IsModified() const;
IMergeDoc::FileChange IsFileChangedOnDisk(int pane) const;
void CreateImgWndStatusBar(CStatusBar &, CWnd *);
// Generated message map functions
private:
+ bool OpenImages();
int UpdateDiffItem(CDirDoc * pDirDoc);
void UpdateHeaderSizes();
void UpdateHeaderPath(int pane);
void SetTitle(LPCTSTR lpszTitle);
bool DoFileSave(int pane);
- bool DoFileSaveAs(int pane);
+ bool DoFileSaveAs(int pane, bool packing = true);
bool PromptAndSaveIfNeeded(bool bAllowCancel);
bool MergeModeKeyDown(MSG* pMsg);
static void OnChildPaneEvent(const IImgMergeWindow::Event& evt);
bool m_bAutoMerged;
CDirDoc *m_pDirDoc;
int m_nActivePane;
+ PackingInfo m_infoUnpacker;
+ int m_unpackerSubcode[3];
//{{AFX_MSG(CImgMergeFrame)
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
const DWORD dwFlags[], const String strDesc[], const String& sReportFile /*= _T("")*/,
const PackingInfo * infoUnpacker /*= nullptr*/)
{
+ ASSERT(pDirDoc != nullptr);
+
if (sReportFile.empty() && pDirDoc->CompareFilesIfFilesAreLarge(nFiles, ifileloc))
return false;
+ String unpackedFileExtension;
+ if (infoUnpacker && GetOptionsMgr()->GetBool(OPT_PLUGINS_ENABLED))
+ {
+ std::vector<String> filepaths(nFiles);
+ std::transform(ifileloc, ifileloc + nFiles, filepaths.begin(),
+ [](auto& file) { return file.filepath; });
+ String filteredFilenames = strutils::join(filepaths.begin(), filepaths.end(), _T("|"));
+ unpackedFileExtension = FileTransform::GetUnpackedFileExtension(filteredFilenames, infoUnpacker);
+ }
FileFilterHelper filterImg, filterBin;
filterImg.UseMask(true);
filterImg.SetMask(GetOptionsMgr()->GetString(OPT_CMP_IMG_FILEPATTERNS));
filterBin.SetMask(GetOptionsMgr()->GetString(OPT_CMP_BIN_FILEPATTERNS));
for (int pane = 0; pane < nFiles; ++pane)
{
- if (filterImg.includeFile(ifileloc[pane].filepath) && CImgMergeFrame::IsLoadable())
+ String filepath = ifileloc[pane].filepath + unpackedFileExtension;
+ if (filterImg.includeFile(filepath) && CImgMergeFrame::IsLoadable())
return ShowImgMergeDoc(pDirDoc, nFiles, ifileloc, dwFlags, strDesc, sReportFile, infoUnpacker);
- else if (filterBin.includeFile(ifileloc[pane].filepath) && CHexMergeView::IsLoadable())
+ else if (filterBin.includeFile(filepath) && CHexMergeView::IsLoadable())
return ShowHexMergeDoc(pDirDoc, nFiles, ifileloc, dwFlags, strDesc, sReportFile, infoUnpacker);
}
return ShowTextOrTableMergeDoc({}, pDirDoc, nFiles, ifileloc, dwFlags, strDesc, sReportFile, infoUnpacker);
if (pHexMergeDoc == nullptr)
return false;
+ pHexMergeDoc->SetUnpacker(infoUnpacker);
+
if (!pHexMergeDoc->OpenDocs(nFiles, fileloc, GetROFromFlags(nFiles, dwFlags).data(), strDesc))
return false;
if (!CImgMergeFrame::menu.m_hMenu)
CImgMergeFrame::menu.m_hMenu = NewImgMergeViewMenu();
pImgMergeFrame->SetSharedMenu(CImgMergeFrame::menu.m_hMenu);
-
+ pImgMergeFrame->SetUnpacker(infoUnpacker);
pImgMergeFrame->SetDirDoc(pDirDoc);
pDirDoc->AddMergeDoc(pImgMergeFrame);
return nRetVal;
}
+String CMergeApp::GetPackingErrorMessage(int pane, int paneCount, const String& path, const String& pluginName)
+{
+ return strutils::format_string2(
+ pane == 0 ?
+ _("Plugin '%2' cannot pack your changes to the left file back into '%1'.\n\nThe original file will not be changed.\n\nDo you want to save the unpacked version to another file?")
+ : (pane == paneCount - 1) ?
+ _("Plugin '%2' cannot pack your changes to the right file back into '%1'.\n\nThe original file will not be changed.\n\nDo you want to save the unpacked version to another file?")
+ : _("Plugin '%2' cannot pack your changes to the middle file back into '%1'.\n\nThe original file will not be changed.\n\nDo you want to save the unpacked version to another file?"),
+ path, pluginName);
+}
+
/**
* @brief Is specified file a project file?
* @param [in] filepath Full path to file to check.
static void OpenFileToExternalEditor(const String& file, int nLineNumber = 1);
static bool CreateBackup(bool bFolder, const String& pszPath);
static int HandleReadonlySave(String& strSavePath, bool bMultiFile, bool &bApplyToAll);
+ static String GetPackingErrorMessage(int pane, int paneCount, const String& path, const String& pluginName);
bool GetMergingMode() const;
void SetMergingMode(bool bMergingMode);
static void SetupTempPath();
// Select message based on reason function called
if (nSaveResult == SAVE_PACK_FAILED)
{
- if (m_nBuffers == 3)
- {
- str = strutils::format_string2(
- nBuffer == 0 ?
- _("Plugin '%2' cannot pack your changes to the left file back into '%1'.\n\nThe original file will not be changed.\n\nDo you want to save the unpacked version to another file?")
- : (nBuffer == 1 ?
- _("Plugin '%2' cannot pack your changes to the middle file back into '%1'.\n\nThe original file will not be changed.\n\nDo you want to save the unpacked version to another file?"):
- _("Plugin '%2' cannot pack your changes to the right file back into '%1'.\n\nThe original file will not be changed.\n\nDo you want to save the unpacked version to another file?")),
- strPath, pInfoTempUnpacker->m_PluginName);
- }
- else
- {
- str = strutils::format_string2(nBuffer == 0 ? _("Plugin '%2' cannot pack your changes to the left file back into '%1'.\n\nThe original file will not be changed.\n\nDo you want to save the unpacked version to another file?") :
- _("Plugin '%2' cannot pack your changes to the right file back into '%1'.\n\nThe original file will not be changed.\n\nDo you want to save the unpacked version to another file?"),
- strPath, pInfoTempUnpacker->m_PluginName);
- }
+ str = CMergeApp::GetPackingErrorMessage(nBuffer, m_nBuffers, strPath, pInfoTempUnpacker->m_PluginName);
// replace the unpacker with a "do nothing" unpacker
pInfoTempUnpacker->Initialize(PLUGIN_MODE::PLUGIN_MANUAL);
}