1 /////////////////////////////////////////////////////////////////////////////
2 // WinMerge: an interactive diff/merge utility
3 // Copyright (C) 1997-2000 Thingamahoochie Software
5 // SPDX-License-Identifier: GPL-2.0-or-later
6 /////////////////////////////////////////////////////////////////////////////
8 * @file HexMergeDoc.cpp
10 * @brief Implementation file for CHexMergeDoc
15 #include "HexMergeDoc.h"
17 #include "UnicodeString.h"
18 #include "HexMergeFrm.h"
19 #include "HexMergeView.h"
21 #include "FolderCmp.h"
22 #include "DiffContext.h" // FILE_SAME
24 #include "DirActions.h"
25 #include "OptionsDef.h"
26 #include "DiffFileInfo.h"
27 #include "SaveClosingDlg.h"
30 #include "OptionsMgr.h"
31 #include "FileOrFolderSelect.h"
32 #include "DiffWrapper.h"
33 #include "SyntaxColors.h"
35 #include "Constants.h"
42 int CHexMergeDoc::m_nBuffersTemp = 2;
44 static void UpdateDiffItem(int nBuffers, DIFFITEM &di, CDiffContext *pCtxt);
45 static int Try(HRESULT hr, UINT type = MB_OKCANCEL|MB_ICONSTOP);
48 * @brief Update diff item
50 static void UpdateDiffItem(int nBuffers, DIFFITEM &di, CDiffContext *pCtxt)
52 di.diffcode.setSideNone();
53 for (int nBuffer = 0; nBuffer < nBuffers; nBuffer++)
55 di.diffFileInfo[nBuffer].ClearPartial();
56 if (pCtxt->UpdateInfoFromDiskHalf(di, nBuffer))
57 di.diffcode.diffcode |= DIFFCODE::FIRST << nBuffer;
60 di.diffcode.diffcode &= ~(DIFFCODE::TEXTFLAGS | DIFFCODE::COMPAREFLAGS | DIFFCODE::COMPAREFLAGS3WAY);
62 FolderCmp folderCmp(pCtxt);
63 di.diffcode.diffcode |= folderCmp.prepAndCompareFiles(di);
67 * @brief Issue an error popup if passed in HRESULT is nonzero
69 static int Try(HRESULT hr, UINT type)
71 return hr ? CInternetException(hr).ReportError(type) : 0;
74 /////////////////////////////////////////////////////////////////////////////
77 IMPLEMENT_DYNCREATE(CHexMergeDoc, CDocument)
79 BEGIN_MESSAGE_MAP(CHexMergeDoc, CDocument)
80 //{{AFX_MSG_MAP(CHexMergeDoc)
81 ON_COMMAND(ID_FILE_SAVE, OnFileSave)
82 ON_COMMAND(ID_FILE_SAVE_LEFT, OnFileSaveLeft)
83 ON_COMMAND(ID_FILE_SAVE_RIGHT, OnFileSaveRight)
84 ON_COMMAND(ID_FILE_SAVEAS_LEFT, OnFileSaveAsLeft)
85 ON_COMMAND(ID_FILE_SAVEAS_RIGHT, OnFileSaveAsRight)
86 ON_UPDATE_COMMAND_UI(ID_STATUS_DIFFNUM, OnUpdateStatusNum)
87 ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_LEFT, OnUpdateFileSaveLeft)
88 ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_RIGHT, OnUpdateFileSaveRight)
89 ON_UPDATE_COMMAND_UI(ID_FILE_SAVE, OnUpdateFileSave)
90 ON_COMMAND(ID_RESCAN, OnFileReload)
91 ON_COMMAND(ID_L2R, OnL2r)
92 ON_COMMAND(ID_R2L, OnR2l)
93 ON_COMMAND(ID_COPY_FROM_LEFT, OnCopyFromLeft)
94 ON_COMMAND(ID_COPY_FROM_RIGHT, OnCopyFromRight)
95 ON_COMMAND(ID_ALL_LEFT, OnAllLeft)
96 ON_COMMAND(ID_ALL_RIGHT, OnAllRight)
97 ON_COMMAND(ID_VIEW_ZOOMIN, OnViewZoomIn)
98 ON_COMMAND(ID_VIEW_ZOOMOUT, OnViewZoomOut)
99 ON_COMMAND(ID_VIEW_ZOOMNORMAL, OnViewZoomNormal)
100 ON_COMMAND(ID_REFRESH, OnRefresh)
101 ON_COMMAND_RANGE(ID_MERGE_COMPARE_TEXT, ID_MERGE_COMPARE_IMAGE, OnFileRecompareAs)
102 ON_UPDATE_COMMAND_UI_RANGE(ID_MERGE_COMPARE_TEXT, ID_MERGE_COMPARE_IMAGE, OnUpdateFileRecompareAs)
106 /////////////////////////////////////////////////////////////////////////////
107 // CHexMergeDoc construction/destruction
110 * @brief Constructor.
112 CHexMergeDoc::CHexMergeDoc()
114 , m_nBuffers(m_nBuffersTemp)
116 , m_nBufferType{BUFFER_NORMAL, BUFFER_NORMAL, BUFFER_NORMAL}
118 m_filePaths.SetSize(m_nBuffers);
124 * Informs associated dirdoc that mergedoc is closing.
126 CHexMergeDoc::~CHexMergeDoc()
128 if (m_pDirDoc != nullptr)
129 m_pDirDoc->MergeDocClosing(this);
133 * @brief Return active merge edit view (or left one if neither active)
135 CHexMergeView * CHexMergeDoc::GetActiveMergeView() const
137 CView * pActiveView = GetParentFrame()->GetActiveView();
138 CHexMergeView * pHexMergeView = dynamic_cast<CHexMergeView *>(pActiveView);
139 if (pHexMergeView == nullptr)
140 pHexMergeView = m_pView[0]; // default to left view (in case some location or detail view active)
141 return pHexMergeView;
145 * @brief Update associated diff item
147 int CHexMergeDoc::UpdateDiffItem(CDirDoc *pDirDoc)
149 // If directory compare has results
150 if (pDirDoc != nullptr && pDirDoc->HasDiffs())
152 CDiffContext &ctxt = pDirDoc->GetDiffContext();
153 if (DIFFITEM *pos = FindItemFromPaths(ctxt, m_filePaths))
155 DIFFITEM &di = ctxt.GetDiffRefAt(pos);
156 ::UpdateDiffItem(m_nBuffers, di, &ctxt);
160 int lengthFirst = m_pView[0]->GetLength();
161 void *bufferFirst = m_pView[0]->GetBuffer(lengthFirst);
162 for (int nBuffer = 1; nBuffer < m_nBuffers; nBuffer++)
164 int length = m_pView[nBuffer]->GetLength();
165 if (lengthFirst != length)
169 void *buffer = m_pView[nBuffer]->GetBuffer(length);
170 bDiff = (memcmp(bufferFirst, buffer, lengthFirst) != 0);
175 GetParentFrame()->SetLastCompareResult(bDiff);
176 return bDiff ? 1 : 0;
180 * @brief Asks and then saves modified files
182 bool CHexMergeDoc::PromptAndSaveIfNeeded(bool bAllowCancel)
184 bool bLModified = false, bMModified = false, bRModified = false;
188 bLModified = m_pView[0]->GetModified();
189 bMModified = m_pView[1]->GetModified();
190 bRModified = m_pView[2]->GetModified();
194 bLModified = m_pView[0]->GetModified();
195 bRModified = m_pView[1]->GetModified();
197 if (!bLModified && !bMModified && !bRModified)
200 const String &pathLeft = m_filePaths.GetLeft();
201 const String &pathMiddle = m_filePaths.GetMiddle();
202 const String &pathRight = m_filePaths.GetRight();
205 bool bLSaveSuccess = false, bMSaveSuccess = false, bRSaveSuccess = false;
208 dlg.DoAskFor(bLModified, bMModified, bRModified);
210 dlg.m_bDisableCancel = true;
211 if (!pathLeft.empty())
212 dlg.m_sLeftFile = pathLeft;
214 dlg.m_sLeftFile = m_strDesc[0];
217 if (!pathMiddle.empty())
218 dlg.m_sMiddleFile = pathMiddle;
220 dlg.m_sMiddleFile = m_strDesc[1];
222 if (!pathRight.empty())
223 dlg.m_sRightFile = pathRight;
225 dlg.m_sRightFile = m_strDesc[1];
227 if (dlg.DoModal() == IDOK)
231 if (dlg.m_leftSave == SaveClosingDlg::SAVECLOSING_SAVE)
233 switch (Try(m_pView[0]->SaveFile(pathLeft.c_str())))
236 bLSaveSuccess = true;
245 m_pView[0]->SetSavePoint();
250 if (dlg.m_middleSave == SaveClosingDlg::SAVECLOSING_SAVE)
252 switch (Try(m_pView[1]->SaveFile(pathMiddle.c_str())))
255 bMSaveSuccess = true;
264 m_pView[1]->SetSavePoint();
269 if (dlg.m_rightSave == SaveClosingDlg::SAVECLOSING_SAVE)
271 switch (Try(m_pView[m_nBuffers - 1]->SaveFile(pathRight.c_str())))
274 bRSaveSuccess = true;
283 m_pView[m_nBuffers - 1]->SetSavePoint();
292 // If file were modified and saving was successfull,
293 // update status on dir view
294 if (bLSaveSuccess || bMSaveSuccess || bRSaveSuccess)
296 UpdateDiffItem(m_pDirDoc);
303 * @brief Save modified documents
305 BOOL CHexMergeDoc::SaveModified()
307 return PromptAndSaveIfNeeded(true);
311 * @brief Saves both files
313 void CHexMergeDoc::OnFileSave()
315 for (int nBuffer = 0; nBuffer < m_nBuffers; nBuffer++)
319 void CHexMergeDoc::DoFileSave(int nBuffer)
321 if (m_pView[nBuffer]->GetModified())
323 if (m_nBufferType[nBuffer] == BUFFER_UNNAMED)
324 DoFileSaveAs(nBuffer);
327 const String &path = m_filePaths.GetPath(nBuffer);
328 if (Try(m_pView[nBuffer]->SaveFile(path.c_str())) == IDCANCEL)
331 UpdateDiffItem(m_pDirDoc);
335 void CHexMergeDoc::DoFileSaveAs(int nBuffer)
337 const String &path = m_filePaths.GetPath(nBuffer);
341 title = _("Save Left File As");
342 else if (nBuffer == m_nBuffers - 1)
343 title = _("Save Right File As");
345 title = _("Save Middle File As");
346 if (SelectFile(AfxGetMainWnd()->GetSafeHwnd(), strPath, false, path.c_str(), title))
348 if (Try(m_pView[nBuffer]->SaveFile(strPath.c_str())) == IDCANCEL)
352 // We are saving scratchpad (unnamed file)
353 m_nBufferType[nBuffer] = BUFFER_UNNAMED_SAVED;
354 m_strDesc[nBuffer].erase();
357 m_filePaths.SetPath(nBuffer, strPath);
358 UpdateDiffItem(m_pDirDoc);
359 UpdateHeaderPath(nBuffer);
364 * @brief Saves left-side file
366 void CHexMergeDoc::OnFileSaveLeft()
372 * @brief Saves middle-side file
374 void CHexMergeDoc::OnFileSaveMiddle()
380 * @brief Saves right-side file
382 void CHexMergeDoc::OnFileSaveRight()
384 DoFileSave(m_nBuffers - 1);
388 * @brief Saves left-side file with name asked
390 void CHexMergeDoc::OnFileSaveAsLeft()
396 * @brief Saves right-side file with name asked
398 void CHexMergeDoc::OnFileSaveAsMiddle()
404 * @brief Saves right-side file with name asked
406 void CHexMergeDoc::OnFileSaveAsRight()
408 DoFileSaveAs(m_nBuffers - 1);
412 * @brief Update diff-number pane text
414 void CHexMergeDoc::OnUpdateStatusNum(CCmdUI* pCmdUI)
417 pCmdUI->SetText(s.c_str());
421 * @brief DirDoc gives us its identity just after it creates us
423 void CHexMergeDoc::SetDirDoc(CDirDoc * pDirDoc)
425 ASSERT(pDirDoc != nullptr && m_pDirDoc == nullptr);
430 * @brief Return pointer to parent frame
432 CHexMergeFrame * CHexMergeDoc::GetParentFrame() const
434 return static_cast<CHexMergeFrame *>(m_pView[0]->GetParentFrame());
438 * @brief DirDoc is closing
440 void CHexMergeDoc::DirDocClosing(CDirDoc * pDirDoc)
442 ASSERT(m_pDirDoc == pDirDoc);
447 * @brief DirDoc commanding us to close
449 bool CHexMergeDoc::CloseNow()
451 // Allow user to cancel closing
452 if (!PromptAndSaveIfNeeded(true))
455 GetParentFrame()->CloseNow();
460 * @brief Load one file
462 HRESULT CHexMergeDoc::LoadOneFile(int index, LPCTSTR filename, bool readOnly, const String& strDesc)
466 if (Try(m_pView[index]->LoadFile(filename), MB_ICONSTOP) != 0)
468 m_pView[index]->SetReadOnly(readOnly);
469 m_filePaths.SetPath(index, filename);
470 ASSERT(m_nBufferType[index] == BUFFER_NORMAL); // should have been initialized to BUFFER_NORMAL in constructor
471 if (!strDesc.empty())
473 m_strDesc[index] = strDesc;
474 m_nBufferType[index] = BUFFER_NORMAL_NAMED;
479 m_nBufferType[index] = BUFFER_UNNAMED;
480 m_strDesc[index] = strDesc;
482 UpdateHeaderPath(index);
483 m_pView[index]->ResizeWindow();
488 * @brief Load files and initialize frame's compare result icon
490 bool CHexMergeDoc::OpenDocs(int nFiles, const FileLocation fileloc[], const bool bRO[], const String strDesc[])
492 CHexMergeFrame *pf = GetParentFrame();
493 ASSERT(pf != nullptr);
494 bool bSucceeded = true;
496 for (nBuffer = 0; nBuffer < nFiles; nBuffer++)
498 if (FAILED(LoadOneFile(nBuffer, fileloc[nBuffer].filepath.c_str(), bRO[nBuffer], strDesc ? strDesc[nBuffer] : _T(""))))
504 if (nBuffer == nFiles)
506 // An extra ResizeWindow() on the left view aligns scroll ranges, and
507 // also triggers initial diff coloring by invalidating the client area.
508 m_pView[0]->ResizeWindow();
514 // Use verify macro to trap possible error in debug.
515 VERIFY(pf->DestroyWindow());
520 void CHexMergeDoc::MoveOnLoad(int nPane, int)
524 nPane = GetOptionsMgr()->GetInt(OPT_ACTIVE_PANE);
525 if (nPane < 0 || nPane >= m_nBuffers)
529 GetParentFrame()->SetActivePane(nPane);
531 if (GetOptionsMgr()->GetBool(OPT_SCROLL_TO_FIRST))
532 m_pView[0]->SendMessage(WM_COMMAND, ID_FIRSTDIFF);
535 void CHexMergeDoc::CheckFileChanged(void)
537 for (int pane = 0; pane < m_nBuffers; ++pane)
539 if (m_pView[pane]->IsFileChangedOnDisk(m_filePaths[pane].c_str()) == FileChanged)
541 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]);
542 if (AfxMessageBox(msg.c_str(), MB_YESNO | MB_ICONWARNING) == IDYES)
552 * @brief Write path and filename to headerbar
553 * @note SetText() does not repaint unchanged text
555 void CHexMergeDoc::UpdateHeaderPath(int pane)
557 CHexMergeFrame *pf = GetParentFrame();
558 ASSERT(pf != nullptr);
561 if (m_nBufferType[pane] == BUFFER_UNNAMED ||
562 m_nBufferType[pane] == BUFFER_NORMAL_NAMED)
564 sText = m_strDesc[pane];
568 sText = m_filePaths.GetPath(pane);
569 if (m_pDirDoc != nullptr)
570 m_pDirDoc->ApplyDisplayRoot(pane, sText);
572 if (m_pView[pane]->GetModified())
573 sText.insert(0, _T("* "));
574 pf->GetHeaderInterface()->SetText(pane, sText);
581 * @brief Customize a heksedit control's settings
583 static void Customize(IHexEditorWindow::Settings *settings)
585 settings->bSaveIni = false;
586 //settings->iAutomaticBPL = false;
587 //settings->iBytesPerLine = 16;
588 //settings->iFontSize = 8;
592 * @brief Customize a heksedit control's colors
594 static void Customize(IHexEditorWindow::Colors *colors)
596 COptionsMgr *pOptionsMgr = GetOptionsMgr();
597 colors->iSelBkColorValue = RGB(224, 224, 224);
598 colors->iDiffBkColorValue = pOptionsMgr->GetInt(OPT_CLR_DIFF);
599 colors->iSelDiffBkColorValue = pOptionsMgr->GetInt(OPT_CLR_SELECTED_DIFF);
600 colors->iDiffTextColorValue = pOptionsMgr->GetInt(OPT_CLR_DIFF_TEXT);
601 if (colors->iDiffTextColorValue == 0xFFFFFFFF)
602 colors->iDiffTextColorValue = 0;
603 colors->iSelDiffTextColorValue = pOptionsMgr->GetInt(OPT_CLR_SELECTED_DIFF_TEXT);
604 if (colors->iSelDiffTextColorValue == 0xFFFFFFFF)
605 colors->iSelDiffTextColorValue = 0;
606 SyntaxColors *pSyntaxColors = theApp.GetMainSyntaxColors();
607 colors->iTextColorValue = pSyntaxColors->GetColor(COLORINDEX_NORMALTEXT);
608 colors->iBkColorValue = pSyntaxColors->GetColor(COLORINDEX_BKGND);
609 colors->iSelTextColorValue = pSyntaxColors->GetColor(COLORINDEX_SELTEXT);
610 colors->iSelBkColorValue = pSyntaxColors->GetColor(COLORINDEX_SELBKGND);
614 * @brief Customize a heksedit control's settings and colors
616 static void Customize(IHexEditorWindow *pif)
618 Customize(pif->get_settings());
619 Customize(pif->get_colors());
620 //LANGID wLangID = (LANGID)GetThreadLocale();
621 //pif->load_lang(wLangID);
624 void CHexMergeDoc::RefreshOptions()
626 for (int nBuffer = 0; nBuffer < m_nBuffers; nBuffer++)
628 IHexEditorWindow *pif = m_pView[nBuffer]->GetInterface();
629 pif->read_ini_data();
631 pif->resize_window();
636 * @brief Update document filenames to title
638 void CHexMergeDoc::SetTitle(LPCTSTR lpszTitle)
643 if (lpszTitle != nullptr)
647 for (int nBuffer = 0; nBuffer < m_filePaths.GetSize(); nBuffer++)
648 sFileName[nBuffer] = !m_strDesc[nBuffer].empty() ? m_strDesc[nBuffer] : paths::FindFileName(m_filePaths[nBuffer]);
649 if (std::count(&sFileName[0], &sFileName[0] + m_nBuffers, sFileName[0]) == m_nBuffers)
650 sTitle = sFileName[0] + strutils::format(_T(" x %d"), m_nBuffers);
652 sTitle = strutils::join(&sFileName[0], &sFileName[0] + m_nBuffers, _T(" - "));
654 CDocument::SetTitle(sTitle.c_str());
658 * @brief We have two child views (left & right), so we keep pointers directly
659 * at them (the MFC view list doesn't have them both)
661 void CHexMergeDoc::SetMergeViews(CHexMergeView *pView[])
663 for (int nBuffer = 0; nBuffer < m_nBuffers; nBuffer++)
665 ASSERT(pView[nBuffer] != nullptr && m_pView[nBuffer] == nullptr);
666 m_pView[nBuffer] = pView[nBuffer];
667 m_pView[nBuffer]->m_nThisPane = nBuffer;
672 * @brief Called when "Save left" item is updated
674 void CHexMergeDoc::OnUpdateFileSaveLeft(CCmdUI* pCmdUI)
676 pCmdUI->Enable(m_pView[0]->GetModified());
680 * @brief Called when "Save middle" item is updated
682 void CHexMergeDoc::OnUpdateFileSaveMiddle(CCmdUI* pCmdUI)
684 pCmdUI->Enable(m_nBuffers == 3 && m_pView[1]->GetModified());
688 * @brief Called when "Save right" item is updated
690 void CHexMergeDoc::OnUpdateFileSaveRight(CCmdUI* pCmdUI)
692 pCmdUI->Enable(m_pView[m_nBuffers - 1]->GetModified());
696 * @brief Called when "Save" item is updated
698 void CHexMergeDoc::OnUpdateFileSave(CCmdUI* pCmdUI)
700 bool bModified = false;
701 for (int nBuffer = 0; nBuffer < m_nBuffers; nBuffer++)
702 bModified |= m_pView[nBuffer]->GetModified();
703 pCmdUI->Enable(bModified);
707 * @brief Reloads the opened files
709 void CHexMergeDoc::OnFileReload()
711 if (!PromptAndSaveIfNeeded(true))
714 FileLocation fileloc[3];
716 for (int pane = 0; pane < m_nBuffers; pane++)
718 fileloc[pane].setPath(m_filePaths[pane]);
719 bRO[pane] = m_pView[pane]->GetReadOnly();
721 if (!OpenDocs(m_nBuffers, fileloc, bRO, m_strDesc))
723 MoveOnLoad(GetActiveMergeView()->m_nThisPane);
727 * @brief Copy selected bytes from left to right
729 void CHexMergeDoc::OnL2r()
731 int dstPane = (GetActiveMergeView()->m_nThisPane < m_nBuffers - 1) ? GetActiveMergeView()->m_nThisPane + 1 : m_nBuffers - 1;
732 int srcPane = dstPane - 1;
733 CHexMergeView::CopySel(m_pView[srcPane], m_pView[dstPane]);
737 * @brief Copy selected bytes from right to left
739 void CHexMergeDoc::OnR2l()
741 int dstPane = (GetActiveMergeView()->m_nThisPane > 0) ? GetActiveMergeView()->m_nThisPane - 1 : 0;
742 int srcPane = dstPane + 1;
743 CHexMergeView::CopySel(m_pView[srcPane], m_pView[dstPane]);
747 * @brief Copy selected bytes from left to active pane
749 void CHexMergeDoc::OnCopyFromLeft()
751 int dstPane = GetActiveMergeView()->m_nThisPane;
752 int srcPane = (dstPane - 1 < 0) ? 0 : dstPane - 1;
753 CHexMergeView::CopySel(m_pView[srcPane], m_pView[dstPane]);
757 * @brief Copy selected bytes from right to active pane
759 void CHexMergeDoc::OnCopyFromRight()
761 int dstPane = GetActiveMergeView()->m_nThisPane;
762 int srcPane = (dstPane + 1 > m_nBuffers - 1) ? m_nBuffers - 1 : dstPane + 1;
763 CHexMergeView::CopySel(m_pView[srcPane], m_pView[dstPane]);
767 * @brief Copy all bytes from left to right
769 void CHexMergeDoc::OnAllRight()
771 int dstPane = (GetActiveMergeView()->m_nThisPane < m_nBuffers - 1) ? GetActiveMergeView()->m_nThisPane + 1 : m_nBuffers - 1;
772 int srcPane = dstPane - 1;
773 CHexMergeView::CopyAll(m_pView[srcPane], m_pView[dstPane]);
777 * @brief Copy all bytes from right to left
779 void CHexMergeDoc::OnAllLeft()
781 int dstPane = (GetActiveMergeView()->m_nThisPane > 0) ? GetActiveMergeView()->m_nThisPane - 1 : 0;
782 int srcPane = dstPane + 1;
783 CHexMergeView::CopyAll(m_pView[srcPane], m_pView[dstPane]);
787 * @brief Called when user selects View/Zoom In from menu.
789 void CHexMergeDoc::OnViewZoomIn()
791 for (int pane = 0; pane < m_nBuffers; pane++)
792 m_pView[pane]->ZoomText(1);
796 * @brief Called when user selects View/Zoom Out from menu.
798 void CHexMergeDoc::OnViewZoomOut()
800 for (int pane = 0; pane < m_nBuffers; pane++)
801 m_pView[pane]->ZoomText(-1);
805 * @brief Called when user selects View/Zoom Normal from menu.
807 void CHexMergeDoc::OnViewZoomNormal()
809 for (int pane = 0; pane < m_nBuffers; pane++)
810 m_pView[pane]->ZoomText(0);
813 void CHexMergeDoc::OnRefresh()
815 if (UpdateDiffItem(m_pDirDoc) == 0)
816 LangMessageBox(IDS_FILESSAME, MB_ICONINFORMATION | MB_DONT_DISPLAY_AGAIN);
819 void CHexMergeDoc::OnFileRecompareAs(UINT nID)
821 FileLocation fileloc[3];
824 int nBuffers = m_nBuffers;
825 CDirDoc *pDirDoc = m_pDirDoc->GetMainView() ? m_pDirDoc :
826 static_cast<CDirDoc*>(theApp.m_pDirTemplate->CreateNewDocument());
827 for (int nBuffer = 0; nBuffer < nBuffers; ++nBuffer)
829 fileloc[nBuffer].setPath(m_filePaths[nBuffer]);
830 dwFlags[nBuffer] = m_pView[nBuffer]->GetReadOnly() ? FFILEOPEN_READONLY : 0;
831 strDesc[nBuffer] = m_strDesc[nBuffer];
834 if (nID == ID_MERGE_COMPARE_TEXT)
835 GetMainFrame()->ShowMergeDoc(pDirDoc, nBuffers, fileloc, dwFlags, strDesc);
837 GetMainFrame()->ShowImgMergeDoc(pDirDoc, nBuffers, fileloc, dwFlags, strDesc);
840 void CHexMergeDoc::OnUpdateFileRecompareAs(CCmdUI* pCmdUI)
842 pCmdUI->Enable(pCmdUI->m_nID != ID_MERGE_COMPARE_XML);