OSDN Git Service

Plugins: Fix a crash on Window XP
[winmerge-jp/winmerge-jp.git] / Src / MergeDoc.cpp
index eb941ea..1e68421 100644 (file)
@@ -42,7 +42,7 @@
 #include "SubstitutionFiltersList.h"
 #include "TempFile.h"
 #include "codepage_detect.h"
-#include "SelectUnpackerDlg.h"
+#include "SelectPluginDlg.h"
 #include "EncodingErrorBar.h"
 #include "MergeCmdLineInfo.h"
 #include "TFile.h"
@@ -80,14 +80,14 @@ BEGIN_MESSAGE_MAP(CMergeDoc, CDocument)
        ON_COMMAND(ID_FILE_SAVEAS_MIDDLE, OnFileSaveAsMiddle)
        ON_COMMAND(ID_FILE_SAVEAS_RIGHT, OnFileSaveAsRight)
        ON_UPDATE_COMMAND_UI(ID_STATUS_DIFFNUM, OnUpdateStatusNum)
-       ON_UPDATE_COMMAND_UI(ID_STATUS_PLUGIN, OnUpdatePluginName)
        ON_COMMAND(ID_TOOLS_GENERATEREPORT, OnToolsGenerateReport)
        ON_COMMAND(ID_TOOLS_GENERATEPATCH, OnToolsGeneratePatch)
        ON_COMMAND(ID_RESCAN, OnFileReload)
        ON_COMMAND(ID_FILE_ENCODING, OnFileEncoding)
        ON_COMMAND_RANGE(ID_VIEW_DIFFCONTEXT_ALL, ID_VIEW_DIFFCONTEXT_INVERT, OnDiffContext)
        ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_DIFFCONTEXT_ALL, ID_VIEW_DIFFCONTEXT_INVERT, OnUpdateDiffContext)
-       ON_COMMAND(ID_POPUP_OPEN_WITH_UNPACKER, OnCtxtOpenWithUnpacker)
+       ON_COMMAND(ID_OPEN_WITH_UNPACKER, OnOpenWithUnpacker)
+       ON_COMMAND(ID_APPLY_PREDIFFER, OnApplyPrediffer)
        ON_BN_CLICKED(IDC_FILEENCODING, OnBnClickedFileEncoding)
        ON_BN_CLICKED(IDC_PLUGIN, OnBnClickedPlugin)
        ON_BN_CLICKED(IDC_HEXVIEW, OnBnClickedHexView)
@@ -96,9 +96,8 @@ BEGIN_MESSAGE_MAP(CMergeDoc, CDocument)
        ON_UPDATE_COMMAND_UI(ID_MERGE_COMPARE_TEXT, OnUpdateFileRecompareAsText)
        ON_COMMAND(ID_MERGE_COMPARE_TABLE, OnFileRecompareAsTable)
        ON_UPDATE_COMMAND_UI(ID_MERGE_COMPARE_TABLE, OnUpdateFileRecompareAsTable)
-       ON_COMMAND(ID_MERGE_COMPARE_XML, OnFileRecompareAsXML)
-       ON_UPDATE_COMMAND_UI(ID_MERGE_COMPARE_XML, OnUpdateFileRecompareAsXML)
        ON_COMMAND_RANGE(ID_MERGE_COMPARE_HEX, ID_MERGE_COMPARE_IMAGE, OnFileRecompareAs)
+       ON_COMMAND_RANGE(ID_UNPACKERS_FIRST, ID_UNPACKERS_LAST, OnFileRecompareAs)
        ON_UPDATE_COMMAND_UI_RANGE(ID_SWAPPANES_SWAP23, ID_SWAPPANES_SWAP13, OnUpdateSwapContext)
        //}}AFX_MSG_MAP
 END_MESSAGE_MAP()
@@ -115,7 +114,6 @@ CMergeDoc::CMergeDoc()
 , m_CurWordDiff{ -1, static_cast<size_t>(-1), -1 }
 , m_pDirDoc(nullptr)
 , m_bMixedEol(false)
-, m_pInfoUnpacker(new PackingInfo)
 , m_pEncodingErrorBar(nullptr)
 , m_bHasSyncPoints(false)
 , m_bAutoMerged(false)
@@ -217,7 +215,7 @@ void CMergeDoc::SetUnpacker(const PackingInfo * infoNewHandler)
 {
        if (infoNewHandler != nullptr)
        {
-               *m_pInfoUnpacker = *infoNewHandler;
+               m_infoUnpacker = *infoNewHandler;
        }
 }
 
@@ -225,11 +223,19 @@ void CMergeDoc::SetPrediffer(const PrediffingInfo * infoPrediffer)
 {
        m_diffWrapper.SetPrediffer(infoPrediffer);
 }
+
 void CMergeDoc::GetPrediffer(PrediffingInfo * infoPrediffer)
 {
        m_diffWrapper.GetPrediffer(infoPrediffer);
 }
 
+const PrediffingInfo* CMergeDoc::GetPrediffer() const
+{
+       static PrediffingInfo infoPrediffer;
+       m_diffWrapper.GetPrediffer(&infoPrediffer);
+       return &infoPrediffer;
+}
+
 /////////////////////////////////////////////////////////////////////////////
 // CMergeDoc serialization
 
@@ -255,7 +261,7 @@ void CMergeDoc::Serialize(CArchive& ar)
 static void SaveBuffForDiff(CDiffTextBuffer & buf, const String& filepath, int nStartLine, int nLines)
 {
        // and we don't repack the file
-       PackingInfo * tempPacker = nullptr;
+       PackingInfo tempPacker(false);
 
        // write buffer out to temporary file
        String sError;
@@ -511,7 +517,7 @@ int CMergeDoc::Rescan(bool &bBinary, IDENTLEVEL &identical,
                // Apply flags to lines that are trivial
                PrediffingInfo infoPrediffer;
                GetPrediffer(&infoPrediffer);
-               if (!infoPrediffer.m_PluginName.empty())
+               if (!infoPrediffer.GetPluginPipeline().empty())
                        FlagTrivialLines();
                
                // Apply flags to lines that moved, to differentiate from appeared/disappeared lines
@@ -1126,7 +1132,7 @@ void CMergeDoc::DoAutoMerge(int dstPane)
 
        ShowMessageBox(
                strutils::format_string2(
-                       _T("The number of automatically merged changes: %1\nThe number of unresolved conflicts: %2"), 
+                       _("The number of automatically merged changes: %1\nThe number of unresolved conflicts: %2"), 
                        strutils::format(_T("%d"), autoMergedCount),
                        strutils::format(_T("%d"), unresolvedConflictCount)),
                MB_ICONINFORMATION);
@@ -1531,7 +1537,7 @@ bool CMergeDoc::WordListCopy(int srcPane, int dstPane, int nDiff, int firstWordD
  * @sa CMergeDoc::CDiffTextBuffer::SaveToFile()
  */
 bool CMergeDoc::TrySaveAs(String &strPath, int &nSaveResult, String & sError,
-       int nBuffer, PackingInfo * pInfoTempUnpacker)
+       int nBuffer, PackingInfo& infoTempUnpacker)
 {
        String s;
        String str;
@@ -1546,24 +1552,9 @@ bool CMergeDoc::TrySaveAs(String &strPath, int &nSaveResult, String & sError,
        // 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, infoTempUnpacker);
                // replace the unpacker with a "do nothing" unpacker
-               pInfoTempUnpacker->Initialize(PLUGIN_MODE::PLUGIN_MANUAL);
+               infoTempUnpacker.Initialize(false);
        }
        else
        {
@@ -1590,7 +1581,7 @@ bool CMergeDoc::TrySaveAs(String &strPath, int &nSaveResult, String & sError,
                        CDiffTextBuffer *pBuffer = m_ptBuf[nBuffer].get();
                        strSavePath = s;
                        nSaveResult = pBuffer->SaveToFile(strSavePath, false, sError,
-                               pInfoTempUnpacker);
+                               infoTempUnpacker);
 
                        if (nSaveResult == SAVE_DONE)
                        {
@@ -1659,9 +1650,9 @@ bool CMergeDoc::DoSave(LPCTSTR szPath, bool &bSaveSuccess, int nBuffer)
        }
 
        // use a temp packer
-       // first copy the m_pInfoUnpacker
+       // first copy the m_infoUnpacker
        // if an error arises during packing, change and take a "do nothing" packer
-       PackingInfo infoTempUnpacker = *m_pInfoUnpacker;
+       PackingInfo infoTempUnpacker = m_infoUnpacker;
 
        bSaveSuccess = false;
        
@@ -1680,11 +1671,11 @@ bool CMergeDoc::DoSave(LPCTSTR szPath, bool &bSaveSuccess, int nBuffer)
                        strSavePath = theApp.m_strSaveAsPath;   
        }
 
-       nRetVal = theApp.HandleReadonlySave(strSavePath, false, bApplyToAll);
+       nRetVal = CMergeApp::HandleReadonlySave(strSavePath, false, bApplyToAll);
        if (nRetVal == IDCANCEL)
                return false;
 
-       if (!theApp.CreateBackup(false, strSavePath))
+       if (!CMergeApp::CreateBackup(false, strSavePath))
                return false;
 
        // false as long as the user is not satisfied
@@ -1708,13 +1699,13 @@ bool CMergeDoc::DoSave(LPCTSTR szPath, bool &bSaveSuccess, int nBuffer)
        String sError;
        if (nSaveErrorCode == SAVE_DONE)
                // We have a filename, just try to save
-               nSaveErrorCode = pBuffer->SaveToFile(strSavePath, false, sError, &infoTempUnpacker);
+               nSaveErrorCode = pBuffer->SaveToFile(strSavePath, false, sError, infoTempUnpacker);
 
        if (nSaveErrorCode != SAVE_DONE)
        {
                // Saving failed, user may save to another location if wants to
                do
-                       result = TrySaveAs(strSavePath, nSaveErrorCode, sError, nBuffer, &infoTempUnpacker);
+                       result = TrySaveAs(strSavePath, nSaveErrorCode, sError, nBuffer, infoTempUnpacker);
                while (!result);
        }
 
@@ -1773,9 +1764,9 @@ bool CMergeDoc::DoSaveAs(LPCTSTR szPath, bool &bSaveSuccess, int nBuffer)
        String strSavePath(szPath);
 
        // use a temp packer
-       // first copy the m_pInfoUnpacker
+       // first copy the m_infoUnpacker
        // if an error arises during packing, change and take a "do nothing" packer
-       PackingInfo infoTempUnpacker = *m_pInfoUnpacker;
+       PackingInfo infoTempUnpacker = m_infoUnpacker;
 
        bSaveSuccess = false;
        // false as long as the user is not satisfied
@@ -1792,7 +1783,7 @@ bool CMergeDoc::DoSaveAs(LPCTSTR szPath, bool &bSaveSuccess, int nBuffer)
        // Loop until user succeeds saving or cancels
        String sError;
        do
-               result = TrySaveAs(strSavePath, nSaveErrorCode, sError, nBuffer, &infoTempUnpacker);
+               result = TrySaveAs(strSavePath, nSaveErrorCode, sError, nBuffer, infoTempUnpacker);
        while (!result);
 
        // Saving succeeded with given/selected filename
@@ -2121,22 +2112,6 @@ void CMergeDoc::OnUpdateStatusNum(CCmdUI* pCmdUI)
 }
 
 /**
- * @brief Update plugin name
- * @param [in] pCmdUI UI component to update.
- */
-void CMergeDoc::OnUpdatePluginName(CCmdUI* pCmdUI)
-{
-       String pluginNames;
-       if (m_pInfoUnpacker && !m_pInfoUnpacker->m_PluginName.empty())
-               pluginNames += m_pInfoUnpacker->m_PluginName + _T("&");
-       PrediffingInfo prediffer;
-       GetPrediffer(&prediffer);
-       if (!prediffer.m_PluginName.empty())
-               pluginNames += prediffer.m_PluginName + _T("&");
-       pCmdUI->SetText(pluginNames.substr(0, pluginNames.length() - 1).c_str());
-}
-
-/**
  * @brief Change number of diff context lines
  */
 void CMergeDoc::OnDiffContext(UINT nID)
@@ -2661,7 +2636,7 @@ bool CMergeDoc::CloseNow()
        if (!PromptAndSaveIfNeeded(true))
                return false;
 
-       GetParentFrame()->CloseNow();
+       GetParentFrame()->DestroyWindow();
        return true;
 }
 
@@ -2684,7 +2659,7 @@ int CMergeDoc::LoadFile(CString sFileName, int nBuffer, bool & readOnly, const F
 
        CRLFSTYLE nCrlfStyle = CRLFSTYLE::AUTOMATIC;
        CString sOpenError;
-       retVal = pBuf->LoadFromFile(sFileName, m_pInfoUnpacker.get(),
+       retVal = pBuf->LoadFromFile(sFileName, m_infoUnpacker,
                m_strBothFilenames.c_str(), readOnly, nCrlfStyle, encoding, sOpenError);
 
        // if CMergeDoc::CDiffTextBuffer::LoadFromFile failed,
@@ -2775,9 +2750,13 @@ DWORD CMergeDoc::LoadOneFile(int index, String filename, bool readOnly, const St
                loadSuccess = LoadFile(filename.c_str(), index, readOnly, encoding);
                if (FileLoadResult::IsLossy(loadSuccess))
                {
-                       m_ptBuf[index]->FreeAll();
-                       loadSuccess = LoadFile(filename.c_str(), index, readOnly,
-                               GuessCodepageEncoding(filename, GetOptionsMgr()->GetInt(OPT_CP_DETECT), -1));
+                       // Determine the file encoding by looking at all the contents of the file, not just part of it
+                       FileTextEncoding encodingNew = codepage_detect::Guess(filename, GetOptionsMgr()->GetInt(OPT_CP_DETECT), -1);
+                       if (encoding != encodingNew)
+                       {
+                               m_ptBuf[index]->FreeAll();
+                               loadSuccess = LoadFile(filename.c_str(), index, readOnly, encodingNew);
+                       }
                }
        }
        else
@@ -2909,11 +2888,21 @@ bool CMergeDoc::OpenDocs(int nFiles, const FileLocation ifileloc[],
        m_strBothFilenames.erase(m_strBothFilenames.length() - 1);
 
        // Load files
-       DWORD nSuccess[3];
+       DWORD nSuccess[3] = { FileLoadResult::FRESULT_ERROR,  FileLoadResult::FRESULT_ERROR,  FileLoadResult::FRESULT_ERROR };
        for (nBuffer = 0; nBuffer < m_nBuffers; nBuffer++)
        {
                nSuccess[nBuffer] = LoadOneFile(nBuffer, fileloc[nBuffer].filepath, bRO[nBuffer], strDesc ? strDesc[nBuffer] : _T(""),
                        fileloc[nBuffer].encoding);
+               if (!FileLoadResult::IsOk(nSuccess[nBuffer]))
+               {
+                       CMergeEditFrame* pFrame = GetParentFrame();
+                       if (pFrame != nullptr)
+                       {
+                               // Use verify macro to trap possible error in debug.
+                               VERIFY(pFrame->DestroyWindow());
+                       }
+                       return false;
+               }
        }
 
        SetTableProperties();
@@ -2926,22 +2915,10 @@ bool CMergeDoc::OpenDocs(int nFiles, const FileLocation ifileloc[],
        { 
                if (std::count(m_nBufferType, m_nBufferType + m_nBuffers, BUFFERTYPE::UNNAMED) == m_nBuffers)
                {
-                       m_pInfoUnpacker->Initialize(PLUGIN_MODE::PLUGIN_MANUAL);
+                       m_infoUnpacker.Initialize(false);
                }
        }
 
-       // Bail out if either side failed
-       if (std::find_if(nSuccess, nSuccess + m_nBuffers, [](DWORD d){return !FileLoadResult::IsOk(d);} ) != nSuccess + m_nBuffers)
-       {
-               CMergeEditFrame *pFrame = GetParentFrame();
-               if (pFrame != nullptr)
-               {
-                       // Use verify macro to trap possible error in debug.
-                       VERIFY(pFrame->DestroyWindow());
-               }
-               return false;
-       }
-
        // Warn user if file load was lossy (bad encoding)
        int idres=0;
        int nLossyBuffers = 0;
@@ -3043,10 +3020,7 @@ bool CMergeDoc::OpenDocs(int nFiles, const FileLocation ifileloc[],
 
                for (nBuffer = 0; nBuffer < m_nBuffers; nBuffer++)
                {
-                       if (bFiltersEnabled && m_pInfoUnpacker->m_textType.length())
-                               sext[nBuffer] = m_pInfoUnpacker->m_textType;
-                       else
-                               sext[nBuffer] = GetFileExt(fileloc[nBuffer].filepath.c_str(), m_strDesc[nBuffer].c_str());
+                       sext[nBuffer] = GetFileExt(m_ptBuf[nBuffer]->GetTempFileName().c_str(), m_strDesc[nBuffer].c_str());
                        ForEachView(nBuffer, [&](auto& pView) {
                                bTyped[nBuffer] = pView->SetTextType(sext[nBuffer].c_str());
                                if (bTyped[nBuffer])
@@ -3172,7 +3146,7 @@ void CMergeDoc::ChangeFile(int nBuffer, const String& path, int nLineIndex)
 
        strDesc[nBuffer] = _T("");
        fileloc[nBuffer].setPath(path);
-       fileloc[nBuffer].encoding = GuessCodepageEncoding(path, GetOptionsMgr()->GetInt(OPT_CP_DETECT));
+       fileloc[nBuffer].encoding = codepage_detect::Guess(path, GetOptionsMgr()->GetInt(OPT_CP_DETECT));
        
        if (OpenDocs(m_nBuffers, fileloc, bRO, strDesc))
                MoveOnLoad(nBuffer, nLineIndex);
@@ -3292,7 +3266,9 @@ bool CMergeDoc::IsEditedAfterRescan(int nBuffer) const
  */
 void CMergeDoc::SetTitle(LPCTSTR lpszTitle)
 {
-       String sTitle = (lpszTitle != nullptr) ? lpszTitle : CMergeFrameCommon::GetTitleString(m_filePaths, m_strDesc);
+       PrediffingInfo infoPrediffer;
+       GetPrediffer(&infoPrediffer);
+       String sTitle = (lpszTitle != nullptr) ? lpszTitle : CMergeFrameCommon::GetTitleString(m_filePaths, m_strDesc, &m_infoUnpacker, &infoPrediffer);
        CDocument::SetTitle(sTitle.c_str());
 }
 
@@ -3378,41 +3354,6 @@ void CMergeDoc::SwapFiles(int nFromIndex, int nToIndex)
 }
 
 /**
- * @brief Display unpacker dialog to user & handle user's choices
- */
-bool CMergeDoc::OpenWithUnpackerDialog()
-{
-       // let the user choose a handler
-       CSelectUnpackerDlg dlg(m_filePaths[0], nullptr);
-       // create now a new infoUnpacker to initialize the manual/automatic flag
-       PackingInfo infoUnpacker(PLUGIN_MODE::PLUGIN_AUTO);
-       dlg.SetInitialInfoHandler(&infoUnpacker);
-
-       if (dlg.DoModal() == IDOK)
-       {
-               infoUnpacker = dlg.GetInfoHandler();
-               Merge7zFormatMergePluginScope scope(&infoUnpacker);
-               if (HasZipSupport() && std::count_if(m_filePaths.begin(), m_filePaths.end(), ArchiveGuessFormat) == m_nBuffers)
-               {
-                       DWORD dwFlags[3] = {FFILEOPEN_NOMRU, FFILEOPEN_NOMRU, FFILEOPEN_NOMRU};
-                       GetMainFrame()->DoFileOpen(&m_filePaths, dwFlags, m_strDesc, _T(""), 
-                               GetOptionsMgr()->GetBool(OPT_CMP_INCLUDE_SUBDIRS), nullptr, _T(""), &infoUnpacker);
-                       CloseNow();
-               }
-               else
-               {
-                       SetUnpacker(&infoUnpacker);
-                       OnFileReload();
-               }
-               return true;
-       }
-       else
-       {
-               return false;
-       }
-}
-
-/**
  * @brief Reloads the opened files
  */
 void CMergeDoc::OnFileReload()
@@ -3442,9 +3383,40 @@ void CMergeDoc::OnFileEncoding()
        DoFileEncodingDialog();
 }
 
-void CMergeDoc::OnCtxtOpenWithUnpacker() 
+void CMergeDoc::OnOpenWithUnpacker()
 {
-       OpenWithUnpackerDialog();
+       CSelectPluginDlg dlg(m_infoUnpacker.GetPluginPipeline(),
+               strutils::join(m_filePaths.begin(), m_filePaths.end(), _T("|")), true, false);
+       if (dlg.DoModal() != IDOK)
+               return;
+
+       if (!PromptAndSaveIfNeeded(true))
+               return;
+
+       PackingInfo infoUnpacker(dlg.GetPluginPipeline());
+       PathContext paths = m_filePaths;
+       DWORD dwFlags[3] = { FFILEOPEN_NOMRU, FFILEOPEN_NOMRU, FFILEOPEN_NOMRU };
+       String strDesc[3] = { m_strDesc[0], m_strDesc[1], m_strDesc[2] };
+       int nID = m_ptBuf[0]->GetTableEditing() ? ID_MERGE_COMPARE_TABLE : ID_MERGE_COMPARE_TEXT;
+       nID = GetOptionsMgr()->GetBool(OPT_PLUGINS_OPEN_IN_SAME_FRAME_TYPE) ? nID : -1;
+
+       if (GetMainFrame()->DoFileOpen(nID, &paths, dwFlags, strDesc, _T(""), &infoUnpacker))
+               GetParentFrame()->DestroyWindow();
+}
+
+void CMergeDoc::OnApplyPrediffer() 
+{
+       PrediffingInfo prediffer;
+       GetPrediffer(&prediffer);
+       // let the user choose a handler
+       CSelectPluginDlg dlg(prediffer.GetPluginPipeline(),
+               strutils::join(m_filePaths.begin(), m_filePaths.end(), _T("|")), false, false);
+       if (dlg.DoModal() != IDOK)
+               return;
+       prediffer.SetPluginPipeline(dlg.GetPluginPipeline());
+       SetPrediffer(&prediffer);
+       FlushAndRescan(true);
+       SetTitle(nullptr);
 }
 
 void CMergeDoc::OnBnClickedFileEncoding()
@@ -3460,7 +3432,7 @@ void CMergeDoc::OnBnClickedPlugin()
        if (m_pEncodingErrorBar == nullptr || m_pView[0][0] == nullptr)
                return;
        m_pView[0][0]->GetParentFrame()->ShowControlBar(m_pEncodingErrorBar.get(), FALSE, FALSE);
-       OpenWithUnpackerDialog();
+       OnOpenWithUnpacker();
 }
 
 void CMergeDoc::OnBnClickedHexView()
@@ -3478,22 +3450,17 @@ void CMergeDoc::OnOK()
 void CMergeDoc::OnFileRecompareAsText()
 {
        m_bEnableTableEditing = false;
-       PackingInfo infoUnpacker;
-       SetUnpacker(&infoUnpacker);
        OnFileReload();
 }
 
 void CMergeDoc::OnUpdateFileRecompareAsText(CCmdUI *pCmdUI)
 {
-       pCmdUI->Enable(m_pInfoUnpacker->m_PluginOrPredifferMode == PLUGIN_MODE::PLUGIN_BUILTIN_XML ||
-               m_ptBuf[0]->GetTableEditing());
+       pCmdUI->Enable(m_ptBuf[0]->GetTableEditing());
 }
 
 void CMergeDoc::OnFileRecompareAsTable()
 {
        m_bEnableTableEditing = true;
-       PackingInfo infoUnpacker;
-       SetUnpacker(&infoUnpacker);
        OnFileReload();
 }
 
@@ -3502,33 +3469,34 @@ void CMergeDoc::OnUpdateFileRecompareAsTable(CCmdUI *pCmdUI)
        pCmdUI->Enable(!m_ptBuf[0]->GetTableEditing());
 }
 
-void CMergeDoc::OnFileRecompareAsXML()
-{
-       m_bEnableTableEditing = false;
-       PackingInfo infoUnpacker(PLUGIN_MODE::PLUGIN_BUILTIN_XML);
-       SetUnpacker(&infoUnpacker);
-       OnFileReload();
-}
-
-void CMergeDoc::OnUpdateFileRecompareAsXML(CCmdUI *pCmdUI)
-{
-       pCmdUI->Enable(m_pInfoUnpacker->m_PluginOrPredifferMode != PLUGIN_MODE::PLUGIN_BUILTIN_XML);
-}
-
 void CMergeDoc::OnFileRecompareAs(UINT nID)
 {
+       if (!PromptAndSaveIfNeeded(true))
+               return;
+       
        DWORD dwFlags[3] = { 0 };
        FileLocation fileloc[3];
+       String strDesc[3];
+       int nBuffers = m_nBuffers;
+       CDirDoc *pDirDoc = m_pDirDoc->GetMainView() ? m_pDirDoc : 
+               static_cast<CDirDoc*>(theApp.m_pDirTemplate->CreateNewDocument());
+       PackingInfo infoUnpacker(m_infoUnpacker.GetPluginPipeline());
+
        for (int pane = 0; pane < m_nBuffers; pane++)
        {
                fileloc[pane].setPath(m_filePaths[pane]);
                dwFlags[pane] |= FFILEOPEN_NOMRU | (m_ptBuf[pane]->GetReadOnly() ? FFILEOPEN_READONLY : 0);
+               strDesc[pane] = m_strDesc[pane];
        }
-       if (m_pEncodingErrorBar!=nullptr && m_pEncodingErrorBar->IsWindowVisible())
-               m_pView[0][0]->GetParentFrame()->ShowControlBar(m_pEncodingErrorBar.get(), FALSE, FALSE);
-       GetMainFrame()->ShowMergeDoc(nID, m_pDirDoc, m_nBuffers, fileloc, dwFlags, m_strDesc);
-       GetParentFrame()->ShowWindow(SW_RESTORE);
-       GetParentFrame()->DestroyWindow();
+       if (ID_UNPACKERS_FIRST <= nID && nID <= ID_UNPACKERS_LAST)
+       {
+               infoUnpacker.SetPluginPipeline(CMainFrame::GetPluginPipelineByMenuId(nID, FileTransform::UnpackerEventNames, ID_UNPACKERS_FIRST));
+               nID = m_ptBuf[0]->GetTableEditing() ? ID_MERGE_COMPARE_TABLE : ID_MERGE_COMPARE_TEXT;
+               nID = GetOptionsMgr()->GetBool(OPT_PLUGINS_OPEN_IN_SAME_FRAME_TYPE) ? nID : -1;
+       }
+
+       if (GetMainFrame()->ShowMergeDoc(nID, pDirDoc, nBuffers, fileloc, dwFlags, strDesc, _T(""), &infoUnpacker))
+               GetParentFrame()->DestroyWindow();
 }
 
 // Return file extension either from file name