OSDN Git Service

Binary Compare: Fix the problem that the file cannot be saved after creating a new one
[winmerge-jp/winmerge-jp.git] / Src / HexMergeDoc.cpp
index 7b9e645..824a81e 100644 (file)
@@ -2,21 +2,7 @@
 //    WinMerge:  an interactive diff/merge utility
 //    Copyright (C) 1997-2000  Thingamahoochie Software
 //    Author: Dean Grimm
-//
-//    This program is free software; you can redistribute it and/or modify
-//    it under the terms of the GNU General Public License as published by
-//    the Free Software Foundation; either version 2 of the License, or
-//    (at your option) any later version.
-//
-//    This program is distributed in the hope that it will be useful,
-//    but WITHOUT ANY WARRANTY; without even the implied warranty of
-//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-//    GNU General Public License for more details.
-//
-//    You should have received a copy of the GNU General Public License
-//    along with this program; if not, write to the Free Software
-//    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-//
+//    SPDX-License-Identifier: GPL-2.0-or-later
 /////////////////////////////////////////////////////////////////////////////
 /** 
  * @file  HexMergeDoc.cpp
@@ -73,8 +59,8 @@ static void UpdateDiffItem(int nBuffers, DIFFITEM &di, CDiffContext *pCtxt)
        // Clear flags
        di.diffcode.diffcode &= ~(DIFFCODE::TEXTFLAGS | DIFFCODE::COMPAREFLAGS | DIFFCODE::COMPAREFLAGS3WAY);
        // Really compare
-       FolderCmp folderCmp;
-       di.diffcode.diffcode |= folderCmp.prepAndCompareFiles(pCtxt, di);
+       FolderCmp folderCmp(pCtxt);
+       di.diffcode.diffcode |= folderCmp.prepAndCompareFiles(di);
 }
 
 /**
@@ -125,11 +111,11 @@ END_MESSAGE_MAP()
  */
 CHexMergeDoc::CHexMergeDoc()
 : m_pDirDoc(nullptr)
+, m_nBuffers(m_nBuffersTemp)
+, m_pView{}
+, m_nBufferType{BUFFERTYPE::NORMAL, BUFFERTYPE::NORMAL, BUFFERTYPE::NORMAL}
 {
-       m_nBuffers = m_nBuffersTemp;
        m_filePaths.SetSize(m_nBuffers);
-       std::fill_n(m_pView, m_nBuffers, static_cast<CHexMergeView *>(nullptr));
-       std::fill_n(m_nBufferType, m_nBuffers, BUFFER_NORMAL);
 }
 
 /**
@@ -164,7 +150,7 @@ int CHexMergeDoc::UpdateDiffItem(CDirDoc *pDirDoc)
        if (pDirDoc != nullptr && pDirDoc->HasDiffs())
        {
                CDiffContext &ctxt = pDirDoc->GetDiffContext();
-               if (UINT_PTR pos = FindItemFromPaths(ctxt, m_filePaths))
+               if (DIFFITEM *pos = FindItemFromPaths(ctxt, m_filePaths))
                {
                        DIFFITEM &di = ctxt.GetDiffRefAt(pos);
                        ::UpdateDiffItem(m_nBuffers, di, &ctxt);
@@ -244,15 +230,9 @@ bool CHexMergeDoc::PromptAndSaveIfNeeded(bool bAllowCancel)
                {
                        if (dlg.m_leftSave == SaveClosingDlg::SAVECLOSING_SAVE)
                        {
-                               switch (Try(m_pView[0]->SaveFile(pathLeft.c_str())))
-                               {
-                               case 0:
-                                       bLSaveSuccess = true;
-                                       break;
-                               case IDCANCEL:
+                               bLSaveSuccess = DoFileSave(0);
+                               if (!bLSaveSuccess)
                                        result = false;
-                                       break;
-                               }
                        }
                        else
                        {
@@ -263,15 +243,9 @@ bool CHexMergeDoc::PromptAndSaveIfNeeded(bool bAllowCancel)
                {
                        if (dlg.m_middleSave == SaveClosingDlg::SAVECLOSING_SAVE)
                        {
-                               switch (Try(m_pView[1]->SaveFile(pathMiddle.c_str())))
-                               {
-                               case 0:
-                                       bMSaveSuccess = true;
-                                       break;
-                               case IDCANCEL:
+                               bMSaveSuccess = DoFileSave(1);
+                               if (!bMSaveSuccess)
                                        result = false;
-                                       break;
-                               }
                        }
                        else
                        {
@@ -282,15 +256,9 @@ bool CHexMergeDoc::PromptAndSaveIfNeeded(bool bAllowCancel)
                {
                        if (dlg.m_rightSave == SaveClosingDlg::SAVECLOSING_SAVE)
                        {
-                               switch (Try(m_pView[m_nBuffers - 1]->SaveFile(pathRight.c_str())))
-                               {
-                               case 0:
-                                       bRSaveSuccess = true;
-                                       break;
-                               case IDCANCEL:
+                               bRSaveSuccess = DoFileSave(m_nBuffers - 1);
+                               if (!bRSaveSuccess)
                                        result = false;
-                                       break;
-                               }
                        }
                        else
                        {
@@ -330,23 +298,30 @@ void CHexMergeDoc::OnFileSave()
                DoFileSave(nBuffer);
 }
 
-void CHexMergeDoc::DoFileSave(int nBuffer)
+bool CHexMergeDoc::DoFileSave(int nBuffer)
 {
+       bool result = false;
        if (m_pView[nBuffer]->GetModified())
        {
-               if (m_nBufferType[nBuffer] == BUFFER_UNNAMED)
-                       DoFileSaveAs(nBuffer);
+               if (m_nBufferType[nBuffer] == BUFFERTYPE::UNNAMED)
+                       result = DoFileSaveAs(nBuffer);
                else
                {
                        const String &path = m_filePaths.GetPath(nBuffer);
-                       if (Try(m_pView[nBuffer]->SaveFile(path.c_str())) == IDCANCEL)
-                               return;
+                       HRESULT hr = m_pView[nBuffer]->SaveFile(path.c_str());
+                       if (Try(hr) == IDCANCEL)
+                               return false;
+                       if (FAILED(hr))
+                               return DoFileSaveAs(nBuffer);
+                       result = true;
+                       if (result)
+                               UpdateDiffItem(m_pDirDoc);
                }
-               UpdateDiffItem(m_pDirDoc);
        }
+       return result;
 }
 
-void CHexMergeDoc::DoFileSaveAs(int nBuffer)
+bool CHexMergeDoc::DoFileSaveAs(int nBuffer, bool packing)
 {
        const String &path = m_filePaths.GetPath(nBuffer);
        String strPath;
@@ -359,19 +334,24 @@ void CHexMergeDoc::DoFileSaveAs(int nBuffer)
                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)
-                       return;
+               HRESULT hr = m_pView[nBuffer]->SaveFile(strPath.c_str());
+               if (Try(hr) == IDCANCEL)
+                       return false;
+               if (FAILED(hr))
+                       return false;
                if (path.empty())
                {
                        // We are saving scratchpad (unnamed file)
-                       m_nBufferType[nBuffer] = BUFFER_UNNAMED_SAVED;
+                       m_nBufferType[nBuffer] = BUFFERTYPE::UNNAMED_SAVED;
                        m_strDesc[nBuffer].erase();
                }
 
                m_filePaths.SetPath(nBuffer, strPath);
                UpdateDiffItem(m_pDirDoc);
                UpdateHeaderPath(nBuffer);
+               return true;
        }
+       return false;
 }
 
 /**
@@ -481,16 +461,16 @@ HRESULT CHexMergeDoc::LoadOneFile(int index, LPCTSTR filename, bool readOnly, co
                        return E_FAIL;
                m_pView[index]->SetReadOnly(readOnly);
                m_filePaths.SetPath(index, filename);
-               ASSERT(m_nBufferType[index] == BUFFER_NORMAL); // should have been initialized to BUFFER_NORMAL in constructor
+               ASSERT(m_nBufferType[index] == BUFFERTYPE::NORMAL); // should have been initialized to BUFFERTYPE::NORMAL in constructor
                if (!strDesc.empty())
                {
                        m_strDesc[index] = strDesc;
-                       m_nBufferType[index] = BUFFER_NORMAL_NAMED;
+                       m_nBufferType[index] = BUFFERTYPE::NORMAL_NAMED;
                }
        }
        else
        {
-               m_nBufferType[index] = BUFFER_UNNAMED;
+               m_nBufferType[index] = BUFFERTYPE::UNNAMED;
                m_strDesc[index] = strDesc;
        }
        UpdateHeaderPath(index);
@@ -501,11 +481,12 @@ HRESULT CHexMergeDoc::LoadOneFile(int index, LPCTSTR filename, bool readOnly, co
 /**
  * @brief Load files and initialize frame's compare result icon
  */
-bool CHexMergeDoc::OpenDocs(int nFiles, const FileLocation fileloc[], const bool bRO[], const String strDesc[], int nPane)
+bool CHexMergeDoc::OpenDocs(int nFiles, const FileLocation fileloc[], const bool bRO[], const String strDesc[])
 {
        CHexMergeFrame *pf = GetParentFrame();
        ASSERT(pf != nullptr);
        bool bSucceeded = true;
+       int nNormalBuffer = 0;
        int nBuffer;
        for (nBuffer = 0; nBuffer < nFiles; nBuffer++)
        {
@@ -514,6 +495,8 @@ bool CHexMergeDoc::OpenDocs(int nFiles, const FileLocation fileloc[], const bool
                        bSucceeded = false;
                        break;
                }
+               if (m_nBufferType[nBuffer] == BUFFERTYPE::NORMAL || m_nBufferType[nBuffer] == BUFFERTYPE::NORMAL_NAMED)
+                       ++nNormalBuffer;
        }
        if (nBuffer == nFiles)
        {
@@ -521,10 +504,10 @@ bool CHexMergeDoc::OpenDocs(int nFiles, const FileLocation fileloc[], const bool
                // also triggers initial diff coloring by invalidating the client area.
                m_pView[0]->ResizeWindow();
 
-               OnRefresh();
-
-               if (GetOptionsMgr()->GetBool(OPT_SCROLL_TO_FIRST))
-                       m_pView[0]->SendMessage(WM_COMMAND, ID_FIRSTDIFF);
+               if (nNormalBuffer > 0)
+                       OnRefresh();
+               else
+                       UpdateDiffItem(m_pDirDoc);
        }
        else
        {
@@ -534,11 +517,26 @@ bool CHexMergeDoc::OpenDocs(int nFiles, const FileLocation fileloc[], const bool
        return bSucceeded;
 }
 
+void CHexMergeDoc::MoveOnLoad(int nPane, int)
+{
+       if (nPane < 0)
+       {
+               nPane = GetOptionsMgr()->GetInt(OPT_ACTIVE_PANE);
+               if (nPane < 0 || nPane >= m_nBuffers)
+                       nPane = 0;
+       }
+
+       GetParentFrame()->SetActivePane(nPane);
+
+       if (GetOptionsMgr()->GetBool(OPT_SCROLL_TO_FIRST))
+               m_pView[0]->SendMessage(WM_COMMAND, ID_FIRSTDIFF);
+}
+
 void CHexMergeDoc::CheckFileChanged(void)
 {
        for (int pane = 0; pane < m_nBuffers; ++pane)
        {
-               if (m_pView[pane]->IsFileChangedOnDisk(m_filePaths[pane].c_str()))
+               if (m_pView[pane]->IsFileChangedOnDisk(m_filePaths[pane].c_str()) == FileChange::Changed)
                {
                        String msg = strutils::format_string1(_("Another application has updated file\n%1\nsince WinMerge scanned it last time.\n\nDo you want to reload the file?"), m_filePaths[pane]);
                        if (AfxMessageBox(msg.c_str(), MB_YESNO | MB_ICONWARNING) == IDYES)
@@ -560,8 +558,8 @@ void CHexMergeDoc::UpdateHeaderPath(int pane)
        ASSERT(pf != nullptr);
        String sText;
 
-       if (m_nBufferType[pane] == BUFFER_UNNAMED ||
-               m_nBufferType[pane] == BUFFER_NORMAL_NAMED)
+       if (m_nBufferType[pane] == BUFFERTYPE::UNNAMED ||
+               m_nBufferType[pane] == BUFFERTYPE::NORMAL_NAMED)
        {
                sText = m_strDesc[pane];
        }
@@ -639,20 +637,7 @@ void CHexMergeDoc::RefreshOptions()
  */
 void CHexMergeDoc::SetTitle(LPCTSTR lpszTitle)
 {
-       String sTitle;
-       String sFileName[3];
-
-       if (lpszTitle != nullptr)
-               sTitle = lpszTitle;
-       else
-       {
-               for (int nBuffer = 0; nBuffer < m_filePaths.GetSize(); nBuffer++)
-                       sFileName[nBuffer] = !m_strDesc[nBuffer].empty() ? m_strDesc[nBuffer] : paths::FindFileName(m_filePaths[nBuffer]);
-               if (std::count(&sFileName[0], &sFileName[0] + m_nBuffers, sFileName[0]) == m_nBuffers)
-                       sTitle = sFileName[0] + strutils::format(_T(" x %d"), m_nBuffers);
-               else
-                       sTitle = strutils::join(&sFileName[0], &sFileName[0] + m_nBuffers, _T(" - "));
-       }
+       String sTitle = (lpszTitle != nullptr) ? lpszTitle : CMergeFrameCommon::GetTitleString(m_filePaths, m_strDesc);
        CDocument::SetTitle(sTitle.c_str());
 }
 
@@ -720,8 +705,9 @@ void CHexMergeDoc::OnFileReload()
                fileloc[pane].setPath(m_filePaths[pane]);
                bRO[pane] = m_pView[pane]->GetReadOnly();
        }
-       int nActivePane = GetActiveMergeView()->m_nThisPane;
-       OpenDocs(m_nBuffers, fileloc, bRO, m_strDesc, nActivePane);
+       if (!OpenDocs(m_nBuffers, fileloc, bRO, m_strDesc))
+               return;
+       MoveOnLoad(GetActiveMergeView()->m_nThisPane);
 }
 
 /**
@@ -814,7 +800,10 @@ void CHexMergeDoc::OnViewZoomNormal()
 void CHexMergeDoc::OnRefresh()
 {
        if (UpdateDiffItem(m_pDirDoc) == 0)
-               LangMessageBox(IDS_FILESSAME, MB_ICONINFORMATION | MB_DONT_DISPLAY_AGAIN);
+       {
+               CMergeFrameCommon::ShowIdenticalMessage(m_filePaths, true,
+                       [](LPCTSTR msg, UINT flags, UINT id) -> int { return AfxMessageBox(msg, flags, id); });
+       }
 }
 
 void CHexMergeDoc::OnFileRecompareAs(UINT nID)
@@ -832,10 +821,7 @@ void CHexMergeDoc::OnFileRecompareAs(UINT nID)
                strDesc[nBuffer] = m_strDesc[nBuffer];
        }
        CloseNow();
-       if (nID == ID_MERGE_COMPARE_TEXT)
-               GetMainFrame()->ShowMergeDoc(pDirDoc, nBuffers, fileloc, dwFlags, strDesc);
-       else
-               GetMainFrame()->ShowImgMergeDoc(pDirDoc, nBuffers, fileloc, dwFlags, strDesc);
+       GetMainFrame()->ShowMergeDoc(nID, pDirDoc, nBuffers, fileloc, dwFlags, strDesc);
 }
 
 void CHexMergeDoc::OnUpdateFileRecompareAs(CCmdUI* pCmdUI)