1 // TortoiseMerge - a Diff/Patch program
3 // Copyright (C) 2004-2009 - TortoiseSVN
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "TortoiseMerge.h"
23 #include "SysProgressDlg.h"
25 #include "MessageBox.h"
27 #include "PathUtils.h"
30 #include "RightView.h"
31 #include "BottomView.h"
32 #include "DiffColors.h"
33 #include ".\mainfrm.h"
41 const UINT
CMainFrame::m_FindDialogMessage
= RegisterWindowMessage(FINDMSGSTRING
);
43 IMPLEMENT_DYNCREATE(CMainFrame
, CFrameWndEx
)
45 BEGIN_MESSAGE_MAP(CMainFrame
, CFrameWndEx
)
47 ON_COMMAND_RANGE(ID_VIEW_APPLOOK_WIN_2000
, ID_VIEW_APPLOOK_OFF_2007_AQUA
, &CMainFrame::OnApplicationLook
)
48 ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_APPLOOK_WIN_2000
, ID_VIEW_APPLOOK_OFF_2007_AQUA
, &CMainFrame::OnUpdateApplicationLook
)
49 // Global help commands
50 ON_COMMAND(ID_HELP_FINDER
, CFrameWndEx::OnHelpFinder
)
51 ON_COMMAND(ID_HELP
, CFrameWndEx::OnHelp
)
52 ON_COMMAND(ID_CONTEXT_HELP
, CFrameWndEx::OnContextHelp
)
53 ON_COMMAND(ID_DEFAULT_HELP
, CFrameWndEx::OnHelpFinder
)
54 ON_COMMAND(ID_FILE_OPEN
, OnFileOpen
)
55 ON_COMMAND(ID_VIEW_WHITESPACES
, OnViewWhitespaces
)
57 ON_COMMAND(ID_FILE_SAVE
, OnFileSave
)
58 ON_COMMAND(ID_FILE_SAVE_AS
, OnFileSaveAs
)
59 ON_UPDATE_COMMAND_UI(ID_FILE_SAVE
, OnUpdateFileSave
)
60 ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_AS
, OnUpdateFileSaveAs
)
61 ON_COMMAND(ID_VIEW_ONEWAYDIFF
, OnViewOnewaydiff
)
62 ON_UPDATE_COMMAND_UI(ID_VIEW_ONEWAYDIFF
, OnUpdateViewOnewaydiff
)
63 ON_UPDATE_COMMAND_UI(ID_VIEW_WHITESPACES
, OnUpdateViewWhitespaces
)
64 ON_COMMAND(ID_VIEW_OPTIONS
, OnViewOptions
)
66 ON_COMMAND(ID_EDIT_FIND
, OnEditFind
)
67 ON_REGISTERED_MESSAGE(m_FindDialogMessage
, OnFindDialogMessage
)
68 ON_COMMAND(ID_EDIT_FINDNEXT
, OnEditFindnext
)
69 ON_COMMAND(ID_EDIT_FINDPREV
, OnEditFindprev
)
70 ON_COMMAND(ID_FILE_RELOAD
, OnFileReload
)
71 ON_COMMAND(ID_VIEW_LINEDOWN
, OnViewLinedown
)
72 ON_COMMAND(ID_VIEW_LINEUP
, OnViewLineup
)
73 ON_UPDATE_COMMAND_UI(ID_EDIT_MARKASRESOLVED
, OnUpdateMergeMarkasresolved
)
74 ON_COMMAND(ID_EDIT_MARKASRESOLVED
, OnMergeMarkasresolved
)
75 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_NEXTCONFLICT
, OnUpdateMergeNextconflict
)
76 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_PREVIOUSCONFLICT
, OnUpdateMergePreviousconflict
)
79 ON_UPDATE_COMMAND_UI(ID_EDIT_COPY
, OnUpdateEditCopy
)
80 ON_COMMAND(ID_VIEW_SWITCHLEFT
, OnViewSwitchleft
)
81 ON_UPDATE_COMMAND_UI(ID_VIEW_SWITCHLEFT
, OnUpdateViewSwitchleft
)
82 ON_COMMAND(ID_VIEW_LINELEFT
, &CMainFrame::OnViewLineleft
)
83 ON_COMMAND(ID_VIEW_LINERIGHT
, &CMainFrame::OnViewLineright
)
84 ON_UPDATE_COMMAND_UI(ID_VIEW_SHOWFILELIST
, &CMainFrame::OnUpdateViewShowfilelist
)
85 ON_COMMAND(ID_VIEW_SHOWFILELIST
, &CMainFrame::OnViewShowfilelist
)
86 ON_COMMAND(ID_EDIT_USETHEIRBLOCK
, &CMainFrame::OnEditUseTheirs
)
87 ON_COMMAND(ID_EDIT_USEMYBLOCK
, &CMainFrame::OnEditUseMine
)
88 ON_COMMAND(ID_EDIT_USETHEIRTHENMYBLOCK
, &CMainFrame::OnEditUseTheirsThenMine
)
89 ON_COMMAND(ID_EDIT_USEMINETHENTHEIRBLOCK
, &CMainFrame::OnEditUseMineThenTheirs
)
90 ON_COMMAND(ID_EDIT_UNDO
, &CMainFrame::OnEditUndo
)
91 ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO
, &CMainFrame::OnUpdateEditUndo
)
92 ON_UPDATE_COMMAND_UI(ID_EDIT_USEMINETHENTHEIRBLOCK
, &CMainFrame::OnUpdateEditUseminethentheirblock
)
93 ON_UPDATE_COMMAND_UI(ID_EDIT_USEMYBLOCK
, &CMainFrame::OnUpdateEditUsemyblock
)
94 ON_UPDATE_COMMAND_UI(ID_EDIT_USETHEIRBLOCK
, &CMainFrame::OnUpdateEditUsetheirblock
)
95 ON_UPDATE_COMMAND_UI(ID_EDIT_USETHEIRTHENMYBLOCK
, &CMainFrame::OnUpdateEditUsetheirthenmyblock
)
96 ON_COMMAND(ID_VIEW_INLINEDIFFWORD
, &CMainFrame::OnViewInlinediffword
)
97 ON_UPDATE_COMMAND_UI(ID_VIEW_INLINEDIFFWORD
, &CMainFrame::OnUpdateViewInlinediffword
)
98 ON_UPDATE_COMMAND_UI(ID_EDIT_CREATEUNIFIEDDIFFFILE
, &CMainFrame::OnUpdateEditCreateunifieddifffile
)
99 ON_COMMAND(ID_EDIT_CREATEUNIFIEDDIFFFILE
, &CMainFrame::OnEditCreateunifieddifffile
)
100 ON_UPDATE_COMMAND_UI(ID_VIEW_LINEDIFFBAR
, &CMainFrame::OnUpdateViewLinediffbar
)
101 ON_COMMAND(ID_VIEW_LINEDIFFBAR
, &CMainFrame::OnViewLinediffbar
)
102 ON_UPDATE_COMMAND_UI(ID_VIEW_LOCATORBAR
, &CMainFrame::OnUpdateViewLocatorbar
)
103 ON_COMMAND(ID_VIEW_LOCATORBAR
, &CMainFrame::OnViewLocatorbar
)
104 ON_COMMAND(ID_EDIT_USELEFTBLOCK
, &CMainFrame::OnEditUseleftblock
)
105 ON_UPDATE_COMMAND_UI(ID_EDIT_USELEFTBLOCK
, &CMainFrame::OnUpdateEditUseleftblock
)
106 ON_COMMAND(ID_EDIT_USELEFTFILE
, &CMainFrame::OnEditUseleftfile
)
107 ON_UPDATE_COMMAND_UI(ID_EDIT_USELEFTFILE
, &CMainFrame::OnUpdateEditUseleftfile
)
108 ON_COMMAND(ID_EDIT_USEBLOCKFROMLEFTBEFORERIGHT
, &CMainFrame::OnEditUseblockfromleftbeforeright
)
109 ON_UPDATE_COMMAND_UI(ID_EDIT_USEBLOCKFROMLEFTBEFORERIGHT
, &CMainFrame::OnUpdateEditUseblockfromleftbeforeright
)
110 ON_COMMAND(ID_EDIT_USEBLOCKFROMRIGHTBEFORELEFT
, &CMainFrame::OnEditUseblockfromrightbeforeleft
)
111 ON_UPDATE_COMMAND_UI(ID_EDIT_USEBLOCKFROMRIGHTBEFORELEFT
, &CMainFrame::OnUpdateEditUseblockfromrightbeforeleft
)
114 static UINT indicators
[] =
116 ID_SEPARATOR
, // status line indicator
117 ID_INDICATOR_LEFTVIEW
,
118 ID_INDICATOR_RIGHTVIEW
,
119 ID_INDICATOR_BOTTOMVIEW
,
126 // CMainFrame construction/destruction
128 CMainFrame::CMainFrame()
130 m_pFindDialog
= NULL
;
132 m_bInitSplitter
= FALSE
;
133 m_bOneWay
= (0 != ((DWORD
)CRegDWORD(_T("Software\\TortoiseMerge\\OnePane"))));
134 m_bReversedPatch
= FALSE
;
135 m_bHasConflicts
= false;
136 m_bInlineWordDiff
= true;
138 m_bLocatorBar
= true;
139 m_nMoveMovesToIgnore
= 0;
140 theApp
.m_nAppLook
= theApp
.GetInt(_T("ApplicationLook"), ID_VIEW_APPLOOK_VS_2005
);
143 CMainFrame::~CMainFrame()
147 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct
)
149 if (CFrameWndEx::OnCreate(lpCreateStruct
) == -1)
152 OnApplicationLook(theApp
.m_nAppLook
);
154 if (!m_wndMenuBar
.Create(this))
156 TRACE0("Failed to create menubar\n");
157 return -1; // fail to create
160 m_wndMenuBar
.SetPaneStyle(m_wndMenuBar
.GetPaneStyle() | CBRS_SIZE_DYNAMIC
| CBRS_TOOLTIPS
| CBRS_FLYBY
);
162 // prevent the menu bar from taking the focus on activation
163 CMFCPopupMenu::SetForceMenuFocus(FALSE
);
165 if (!m_wndToolBar
.CreateEx(this, TBSTYLE_FLAT
, WS_CHILD
| WS_VISIBLE
| CBRS_ALIGN_TOP
| CBRS_GRIPPER
| CBRS_TOOLTIPS
| CBRS_FLYBY
) ||
166 !m_wndToolBar
.LoadToolBar(IDR_MAINFRAME
))
168 TRACE0("Failed to create toolbar\n");
169 return -1; // fail to create
171 m_wndToolBar
.SetWindowText(_T("Main"));
173 if (!m_wndStatusBar
.Create(this) ||
174 !m_wndStatusBar
.SetIndicators(indicators
,
175 sizeof(indicators
)/sizeof(UINT
)))
177 TRACE0("Failed to create status bar\n");
178 return -1; // fail to create
181 if (!m_wndLocatorBar
.Create(this, IDD_DIFFLOCATOR
,
182 CBRS_ALIGN_LEFT
| CBRS_SIZE_FIXED
, ID_VIEW_LOCATORBAR
))
184 TRACE0("Failed to create dialogbar\n");
185 return -1; // fail to create
187 if (!m_wndLineDiffBar
.Create(this, IDD_LINEDIFF
,
188 CBRS_ALIGN_BOTTOM
| CBRS_SIZE_FIXED
, ID_VIEW_LINEDIFFBAR
))
190 TRACE0("Failed to create dialogbar\n");
191 return -1; // fail to create
193 m_wndLocatorBar
.m_pMainFrm
= this;
194 m_wndLineDiffBar
.m_pMainFrm
= this;
196 EnableDocking(CBRS_ALIGN_ANY
);
197 m_wndMenuBar
.EnableDocking(CBRS_ALIGN_TOP
);
198 m_wndToolBar
.EnableDocking(CBRS_ALIGN_TOP
);
199 DockPane(&m_wndMenuBar
);
200 DockPane(&m_wndToolBar
);
201 DockPane(&m_wndLocatorBar
);
202 DockPane(&m_wndLineDiffBar
);
203 ShowPane(&m_wndLocatorBar
, true, false, true);
204 ShowPane(&m_wndLineDiffBar
, true, false, true);
206 m_wndLocatorBar
.EnableGripper(FALSE
);
207 m_wndLineDiffBar
.EnableGripper(FALSE
);
212 BOOL
CMainFrame::PreCreateWindow(CREATESTRUCT
& cs
)
214 if( !CFrameWndEx::PreCreateWindow(cs
) )
219 void CMainFrame::OnApplicationLook(UINT id
)
223 theApp
.m_nAppLook
= id
;
225 switch (theApp
.m_nAppLook
)
227 case ID_VIEW_APPLOOK_WIN_2000
:
228 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManager
));
231 case ID_VIEW_APPLOOK_OFF_XP
:
232 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOfficeXP
));
235 case ID_VIEW_APPLOOK_WIN_XP
:
236 CMFCVisualManagerWindows::m_b3DTabsXPTheme
= TRUE
;
237 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows
));
240 case ID_VIEW_APPLOOK_OFF_2003
:
241 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2003
));
242 CDockingManager::SetDockingMode(DT_SMART
);
245 case ID_VIEW_APPLOOK_VS_2005
:
246 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerVS2005
));
247 CDockingManager::SetDockingMode(DT_SMART
);
251 switch (theApp
.m_nAppLook
)
253 case ID_VIEW_APPLOOK_OFF_2007_BLUE
:
254 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_LunaBlue
);
257 case ID_VIEW_APPLOOK_OFF_2007_BLACK
:
258 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_ObsidianBlack
);
261 case ID_VIEW_APPLOOK_OFF_2007_SILVER
:
262 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_Silver
);
265 case ID_VIEW_APPLOOK_OFF_2007_AQUA
:
266 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_Aqua
);
270 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2007
));
271 CDockingManager::SetDockingMode(DT_SMART
);
274 RedrawWindow(NULL
, NULL
, RDW_ALLCHILDREN
| RDW_INVALIDATE
| RDW_UPDATENOW
| RDW_FRAME
| RDW_ERASE
);
276 theApp
.WriteInt(_T("ApplicationLook"), theApp
.m_nAppLook
);
279 void CMainFrame::OnUpdateApplicationLook(CCmdUI
* pCmdUI
)
281 pCmdUI
->SetRadio(theApp
.m_nAppLook
== pCmdUI
->m_nID
);
285 // CMainFrame diagnostics
288 void CMainFrame::AssertValid() const
290 CFrameWndEx::AssertValid();
293 void CMainFrame::Dump(CDumpContext
& dc
) const
295 CFrameWndEx::Dump(dc
);
301 // CMainFrame message handlers
304 BOOL
CMainFrame::OnCreateClient(LPCREATESTRUCT
/*lpcs*/, CCreateContext
* pContext
)
310 // split into three panes:
319 // create a splitter with 2 rows, 1 column
320 if (!m_wndSplitter
.CreateStatic(this, 2, 1))
322 TRACE0("Failed to CreateStaticSplitter\n");
326 // add the second splitter pane - which is a nested splitter with 2 columns
327 if (!m_wndSplitter2
.CreateStatic(
328 &m_wndSplitter
, // our parent window is the first splitter
329 1, 2, // the new splitter is 1 row, 2 columns
330 WS_CHILD
| WS_VISIBLE
| WS_BORDER
, // style, WS_BORDER is needed
331 m_wndSplitter
.IdFromRowCol(0, 0)
332 // new splitter is in the first row, 1st column of first splitter
335 TRACE0("Failed to create nested splitter\n");
338 // add the first splitter pane - the default view in row 0
339 if (!m_wndSplitter
.CreateView(1, 0,
340 RUNTIME_CLASS(CBottomView
), CSize(cr
.Width(), cr
.Height()), pContext
))
342 TRACE0("Failed to create first pane\n");
345 m_pwndBottomView
= (CBottomView
*)m_wndSplitter
.GetPane(1,0);
346 m_pwndBottomView
->m_pwndLocator
= &m_wndLocatorBar
;
347 m_pwndBottomView
->m_pwndLineDiffBar
= &m_wndLineDiffBar
;
348 m_pwndBottomView
->m_pwndStatusBar
= &m_wndStatusBar
;
349 m_pwndBottomView
->m_pMainFrame
= this;
351 // now create the two views inside the nested splitter
353 if (!m_wndSplitter2
.CreateView(0, 0,
354 RUNTIME_CLASS(CLeftView
), CSize(cr
.Width()/2, cr
.Height()/2), pContext
))
356 TRACE0("Failed to create second pane\n");
359 m_pwndLeftView
= (CLeftView
*)m_wndSplitter2
.GetPane(0,0);
360 m_pwndLeftView
->m_pwndLocator
= &m_wndLocatorBar
;
361 m_pwndLeftView
->m_pwndLineDiffBar
= &m_wndLineDiffBar
;
362 m_pwndLeftView
->m_pwndStatusBar
= &m_wndStatusBar
;
363 m_pwndLeftView
->m_pMainFrame
= this;
365 if (!m_wndSplitter2
.CreateView(0, 1,
366 RUNTIME_CLASS(CRightView
), CSize(cr
.Width()/2, cr
.Height()/2), pContext
))
368 TRACE0("Failed to create third pane\n");
371 m_pwndRightView
= (CRightView
*)m_wndSplitter2
.GetPane(0,1);
372 m_pwndRightView
->m_pwndLocator
= &m_wndLocatorBar
;
373 m_pwndRightView
->m_pwndLineDiffBar
= &m_wndLineDiffBar
;
374 m_pwndRightView
->m_pwndStatusBar
= &m_wndStatusBar
;
375 m_pwndRightView
->m_pMainFrame
= this;
376 m_bInitSplitter
= TRUE
;
378 m_dlgFilePatches
.Create(IDD_FILEPATCHES
, this);
384 BOOL
CMainFrame::PatchFile(CString sFilePath
, CString sVersion
, BOOL bAutoPatch
)
386 //first, do a "dry run" of patching...
387 if (!m_Patch
.PatchFile(sFilePath
))
389 //patching not successful, so retrieve the
390 //base file from version control and try
393 CSysProgressDlg progDlg
;
394 sTemp
.Format(IDS_GETVERSIONOFFILE
, (LPCTSTR
)sVersion
);
395 progDlg
.SetLine(1, sTemp
, true);
396 progDlg
.SetLine(2, sFilePath
, true);
397 sTemp
.LoadString(IDS_GETVERSIONOFFILETITLE
);
398 progDlg
.SetTitle(sTemp
);
399 progDlg
.SetShowProgressBar(false);
400 progDlg
.SetAnimation(IDR_DOWNLOAD
);
401 progDlg
.SetTime(FALSE
);
402 progDlg
.ShowModeless(this);
403 CString sBaseFile
= m_TempFiles
.GetTempFilePath();
404 if (!CAppUtils::GetVersionedFile(sFilePath
, sVersion
, sBaseFile
, &progDlg
, m_hWnd
))
408 sErrMsg
.Format(IDS_ERR_MAINFRAME_FILEVERSIONNOTFOUND
, (LPCTSTR
)sVersion
, (LPCTSTR
)sFilePath
);
409 MessageBox(sErrMsg
, NULL
, MB_ICONERROR
);
413 CString sTempFile
= m_TempFiles
.GetTempFilePath();
414 if (!m_Patch
.PatchFile(sFilePath
, sTempFile
, sBaseFile
))
416 MessageBox(m_Patch
.GetErrorMessage(), NULL
, MB_ICONERROR
);
420 temp
.Format(_T("%s Revision %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sFilePath
), (LPCTSTR
)sVersion
);
421 m_Data
.m_baseFile
.SetFileName(sBaseFile
);
422 m_Data
.m_baseFile
.SetDescriptiveName(temp
);
423 temp
.Format(_T("%s %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sFilePath
), (LPCTSTR
)m_Data
.m_sPatchPatched
);
424 m_Data
.m_theirFile
.SetFileName(sTempFile
);
425 m_Data
.m_theirFile
.SetDescriptiveName(temp
);
426 m_Data
.m_yourFile
.SetFileName(sFilePath
);
427 m_Data
.m_yourFile
.SetDescriptiveName(CPathUtils::GetFileNameFromPath(sFilePath
));
428 m_Data
.m_mergedFile
.SetFileName(sFilePath
);
429 m_Data
.m_mergedFile
.SetDescriptiveName(CPathUtils::GetFileNameFromPath(sFilePath
));
430 TRACE(_T("comparing %s and %s\nagainst the base file %s\n"), (LPCTSTR
)sTempFile
, (LPCTSTR
)sFilePath
, (LPCTSTR
)sBaseFile
);
434 //"dry run" was successful, so save the patched file somewhere...
435 CString sTempFile
= m_TempFiles
.GetTempFilePath();
436 if (!m_Patch
.PatchFile(sFilePath
, sTempFile
))
438 MessageBox(m_Patch
.GetErrorMessage(), NULL
, MB_ICONERROR
);
441 if (m_bReversedPatch
)
443 m_Data
.m_baseFile
.SetFileName(sTempFile
);
445 temp
.Format(_T("%s %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sFilePath
), (LPCTSTR
)m_Data
.m_sPatchPatched
);
446 m_Data
.m_baseFile
.SetDescriptiveName(temp
);
447 m_Data
.m_yourFile
.SetFileName(sFilePath
);
448 temp
.Format(_T("%s %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sFilePath
), (LPCTSTR
)m_Data
.m_sPatchOriginal
);
449 m_Data
.m_yourFile
.SetDescriptiveName(temp
);
450 m_Data
.m_theirFile
.SetOutOfUse();
451 m_Data
.m_mergedFile
.SetOutOfUse();
455 if (!PathFileExists(sFilePath
))
457 m_Data
.m_baseFile
.SetFileName(m_TempFiles
.GetTempFilePath());
458 m_Data
.m_baseFile
.CreateEmptyFile();
462 m_Data
.m_baseFile
.SetFileName(sFilePath
);
464 CString sDescription
;
465 sDescription
.Format(_T("%s %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sFilePath
), (LPCTSTR
)m_Data
.m_sPatchOriginal
);
466 m_Data
.m_baseFile
.SetDescriptiveName(sDescription
);
467 m_Data
.m_yourFile
.SetFileName(sTempFile
);
469 temp
.Format(_T("%s %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sFilePath
), (LPCTSTR
)m_Data
.m_sPatchPatched
);
470 m_Data
.m_yourFile
.SetDescriptiveName(temp
);
471 m_Data
.m_theirFile
.SetOutOfUse();
472 m_Data
.m_mergedFile
.SetFileName(sFilePath
);
474 TRACE(_T("comparing %s\nwith the patched result %s\n"), (LPCTSTR
)sFilePath
, (LPCTSTR
)sTempFile
);
485 BOOL
CMainFrame::DiffFiles(CString sURL1
, CString sRev1
, CString sURL2
, CString sRev2
)
487 CString tempfile1
= m_TempFiles
.GetTempFilePath();
488 CString tempfile2
= m_TempFiles
.GetTempFilePath();
490 ASSERT(tempfile1
.Compare(tempfile2
));
493 CSysProgressDlg progDlg
;
494 sTemp
.Format(IDS_GETVERSIONOFFILE
, (LPCTSTR
)sRev1
);
495 progDlg
.SetLine(1, sTemp
, true);
496 progDlg
.SetLine(2, sURL1
, true);
497 sTemp
.LoadString(IDS_GETVERSIONOFFILETITLE
);
498 progDlg
.SetTitle(sTemp
);
499 progDlg
.SetShowProgressBar(true);
500 progDlg
.SetAnimation(IDR_DOWNLOAD
);
501 progDlg
.SetTime(FALSE
);
502 progDlg
.SetProgress(1,100);
503 progDlg
.ShowModeless(this);
504 if (!CAppUtils::GetVersionedFile(sURL1
, sRev1
, tempfile1
, &progDlg
, m_hWnd
))
508 sErrMsg
.Format(IDS_ERR_MAINFRAME_FILEVERSIONNOTFOUND
, (LPCTSTR
)sRev1
, (LPCTSTR
)sURL1
);
509 MessageBox(sErrMsg
, NULL
, MB_ICONERROR
);
512 sTemp
.Format(IDS_GETVERSIONOFFILE
, (LPCTSTR
)sRev2
);
513 progDlg
.SetLine(1, sTemp
, true);
514 progDlg
.SetLine(2, sURL2
, true);
515 progDlg
.SetProgress(50, 100);
516 if (!CAppUtils::GetVersionedFile(sURL2
, sRev2
, tempfile2
, &progDlg
, m_hWnd
))
520 sErrMsg
.Format(IDS_ERR_MAINFRAME_FILEVERSIONNOTFOUND
, (LPCTSTR
)sRev2
, (LPCTSTR
)sURL2
);
521 MessageBox(sErrMsg
, NULL
, MB_ICONERROR
);
524 progDlg
.SetProgress(100,100);
527 temp
.Format(_T("%s Revision %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sURL1
), (LPCTSTR
)sRev1
);
528 m_Data
.m_baseFile
.SetFileName(tempfile1
);
529 m_Data
.m_baseFile
.SetDescriptiveName(temp
);
530 temp
.Format(_T("%s Revision %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sURL2
), (LPCTSTR
)sRev2
);
531 m_Data
.m_yourFile
.SetFileName(tempfile2
);
532 m_Data
.m_yourFile
.SetDescriptiveName(temp
);
539 void CMainFrame::OnFileOpen()
541 if (CheckForSave()==IDCANCEL
)
544 if (dlg
.DoModal()!=IDOK
)
548 m_dlgFilePatches
.ShowWindow(SW_HIDE
);
549 m_dlgFilePatches
.Init(NULL
, NULL
, CString(), NULL
);
550 TRACE(_T("got the files:\n %s\n %s\n %s\n %s\n %s\n"), (LPCTSTR
)dlg
.m_sBaseFile
, (LPCTSTR
)dlg
.m_sTheirFile
, (LPCTSTR
)dlg
.m_sYourFile
,
551 (LPCTSTR
)dlg
.m_sUnifiedDiffFile
, (LPCTSTR
)dlg
.m_sPatchDirectory
);
552 m_Data
.m_baseFile
.SetFileName(dlg
.m_sBaseFile
);
553 m_Data
.m_theirFile
.SetFileName(dlg
.m_sTheirFile
);
554 m_Data
.m_yourFile
.SetFileName(dlg
.m_sYourFile
);
555 m_Data
.m_sDiffFile
= dlg
.m_sUnifiedDiffFile
;
556 m_Data
.m_sPatchPath
= dlg
.m_sPatchDirectory
;
557 m_Data
.m_mergedFile
.SetOutOfUse();
558 g_crasher
.AddFile((LPCSTR
)(LPCTSTR
)dlg
.m_sBaseFile
, (LPCSTR
)(LPCTSTR
)_T("Basefile"));
559 g_crasher
.AddFile((LPCSTR
)(LPCTSTR
)dlg
.m_sTheirFile
, (LPCSTR
)(LPCTSTR
)_T("Theirfile"));
560 g_crasher
.AddFile((LPCSTR
)(LPCTSTR
)dlg
.m_sYourFile
, (LPCSTR
)(LPCTSTR
)_T("Yourfile"));
561 g_crasher
.AddFile((LPCSTR
)(LPCTSTR
)dlg
.m_sUnifiedDiffFile
, (LPCSTR
)(LPCTSTR
)_T("Difffile"));
563 if (!m_Data
.IsBaseFileInUse() && m_Data
.IsTheirFileInUse() && m_Data
.IsYourFileInUse())
565 // a diff between two files means "Yours" against "Base", not "Theirs" against "Yours"
566 m_Data
.m_baseFile
.TransferDetailsFrom(m_Data
.m_theirFile
);
568 if (m_Data
.IsBaseFileInUse() && m_Data
.IsTheirFileInUse() && !m_Data
.IsYourFileInUse())
570 // a diff between two files means "Yours" against "Base", not "Theirs" against "Base"
571 m_Data
.m_yourFile
.TransferDetailsFrom(m_Data
.m_theirFile
);
577 void CMainFrame::ClearViewNamesAndPaths() {
578 m_pwndLeftView
->m_sWindowName
.Empty();
579 m_pwndLeftView
->m_sFullFilePath
.Empty();
580 m_pwndRightView
->m_sWindowName
.Empty();
581 m_pwndRightView
->m_sFullFilePath
.Empty();
582 m_pwndBottomView
->m_sWindowName
.Empty();
583 m_pwndBottomView
->m_sFullFilePath
.Empty();
586 bool CMainFrame::LoadViews(bool bRetainPosition
)
588 m_Data
.SetBlame(m_bBlame
);
589 m_bHasConflicts
= false;
590 CBaseView
* pwndActiveView
= m_pwndLeftView
;
591 int nOldLine
= m_pwndLeftView
? m_pwndLeftView
->m_nTopLine
: -1;
593 m_pwndLeftView
&& m_pwndLeftView
->m_pViewData
?
594 m_pwndLeftView
->m_pViewData
->GetLineNumber(m_pwndLeftView
->m_nTopLine
) : -1;
597 ::MessageBox(NULL
, m_Data
.GetError(), _T("TortoiseMerge"), MB_ICONERROR
);
598 m_Data
.m_mergedFile
.SetOutOfUse();
602 m_pwndRightView
->UseCaret(false);
603 m_pwndBottomView
->UseCaret(false);
605 if (!m_Data
.IsBaseFileInUse())
607 if (m_Data
.IsYourFileInUse() && m_Data
.IsTheirFileInUse())
609 m_Data
.m_baseFile
.TransferDetailsFrom(m_Data
.m_theirFile
);
611 else if ((!m_Data
.m_sDiffFile
.IsEmpty())&&(!m_Patch
.OpenUnifiedDiffFile(m_Data
.m_sDiffFile
)))
613 ClearViewNamesAndPaths();
614 MessageBox(m_Patch
.GetErrorMessage(), NULL
, MB_ICONERROR
);
617 if (m_Patch
.GetNumberOfFiles() > 0)
619 CString firstpath
= m_Patch
.GetFilename(0);
620 CString path
=firstpath
;
621 path
.Replace('/','\\');
622 if ( !PathIsRelative(path
) && !PathFileExists(path
) )
624 // The absolute path mentioned in the patch does not exist. Lets
625 // try to find the correct relative path by stripping prefixes.
626 BOOL bFound
= m_Patch
.StripPrefixes(m_Data
.m_sPatchPath
);
627 CString strippedpath
= m_Patch
.GetFilename(0);
631 msg
.Format(IDS_WARNABSOLUTEPATHFOUND
, (LPCTSTR
)firstpath
, (LPCTSTR
)strippedpath
);
632 if (CMessageBox::Show(m_hWnd
, msg
, _T("TortoiseMerge"), MB_ICONQUESTION
| MB_YESNO
)==IDNO
)
638 msg
.Format(IDS_WARNABSOLUTEPATHNOTFOUND
, (LPCTSTR
)firstpath
);
639 CMessageBox::Show(m_hWnd
, msg
, _T("TortoiseMerge"), MB_ICONEXCLAMATION
);
643 CString betterpatchpath
= m_Patch
.CheckPatchPath(m_Data
.m_sPatchPath
);
644 if (betterpatchpath
.CompareNoCase(m_Data
.m_sPatchPath
)!=0)
647 msg
.Format(IDS_WARNBETTERPATCHPATHFOUND
, (LPCTSTR
)m_Data
.m_sPatchPath
, (LPCTSTR
)betterpatchpath
);
648 if (CMessageBox::Show(m_hWnd
, msg
, _T("TortoiseMerge"), MB_ICONQUESTION
| MB_YESNO
)==IDYES
)
649 m_Data
.m_sPatchPath
= betterpatchpath
;
651 m_dlgFilePatches
.Init(&m_Patch
, this, m_Data
.m_sPatchPath
, this);
652 m_dlgFilePatches
.ShowWindow(SW_SHOW
);
653 ClearViewNamesAndPaths();
654 if (!m_wndSplitter
.IsRowHidden(1))
655 m_wndSplitter
.HideRow(1);
656 m_pwndLeftView
->SetHidden(FALSE
);
657 m_pwndRightView
->SetHidden(FALSE
);
658 m_pwndBottomView
->SetHidden(TRUE
);
661 if (m_Data
.IsBaseFileInUse() && !m_Data
.IsYourFileInUse() && m_Data
.IsTheirFileInUse())
663 m_Data
.m_yourFile
.TransferDetailsFrom(m_Data
.m_theirFile
);
665 if (m_Data
.IsBaseFileInUse() && m_Data
.IsYourFileInUse() && !m_Data
.IsTheirFileInUse())
667 //diff between YOUR and BASE
668 m_pwndRightView
->UseCaret();
671 if (!m_wndSplitter2
.IsColumnHidden(1))
672 m_wndSplitter2
.HideColumn(1);
674 m_pwndLeftView
->m_pViewData
= &m_Data
.m_YourBaseBoth
;
675 m_pwndLeftView
->texttype
= m_Data
.m_arYourFile
.GetUnicodeType();
676 m_pwndLeftView
->lineendings
= m_Data
.m_arYourFile
.GetLineEndings();
677 m_pwndLeftView
->m_sWindowName
= m_Data
.m_baseFile
.GetWindowName() + _T(" - ") + m_Data
.m_yourFile
.GetWindowName();
678 m_pwndLeftView
->m_sFullFilePath
= m_Data
.m_baseFile
.GetFilename() + _T(" - ") + m_Data
.m_yourFile
.GetFilename();
680 m_pwndRightView
->m_pViewData
= NULL
;
681 m_pwndBottomView
->m_pViewData
= NULL
;
683 if (!m_wndSplitter
.IsRowHidden(1))
684 m_wndSplitter
.HideRow(1);
685 m_pwndLeftView
->SetHidden(FALSE
);
686 m_pwndRightView
->SetHidden(TRUE
);
687 m_pwndBottomView
->SetHidden(TRUE
);
688 ::SetWindowPos(m_pwndLeftView
->m_hWnd
, NULL
, 0, 0, 0, 0, SWP_FRAMECHANGED
| SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOSIZE
);
692 pwndActiveView
= m_pwndRightView
;
693 if (m_wndSplitter2
.IsColumnHidden(1))
694 m_wndSplitter2
.ShowColumn();
696 m_pwndLeftView
->m_pViewData
= &m_Data
.m_YourBaseLeft
;
697 m_pwndLeftView
->texttype
= m_Data
.m_arBaseFile
.GetUnicodeType();
698 m_pwndLeftView
->lineendings
= m_Data
.m_arBaseFile
.GetLineEndings();
699 m_pwndLeftView
->m_sWindowName
= m_Data
.m_baseFile
.GetWindowName();
700 m_pwndLeftView
->m_sFullFilePath
= m_Data
.m_baseFile
.GetFilename();
702 m_pwndRightView
->m_pViewData
= &m_Data
.m_YourBaseRight
;
703 m_pwndRightView
->texttype
= m_Data
.m_arYourFile
.GetUnicodeType();
704 m_pwndRightView
->lineendings
= m_Data
.m_arYourFile
.GetLineEndings();
705 m_pwndRightView
->m_sWindowName
= m_Data
.m_yourFile
.GetWindowName();
706 m_pwndRightView
->m_sFullFilePath
= m_Data
.m_yourFile
.GetFilename();
708 m_pwndBottomView
->m_pViewData
= NULL
;
710 if (!m_wndSplitter
.IsRowHidden(1))
711 m_wndSplitter
.HideRow(1);
712 m_pwndLeftView
->SetHidden(FALSE
);
713 m_pwndRightView
->SetHidden(FALSE
);
714 m_pwndBottomView
->SetHidden(TRUE
);
717 else if (m_Data
.IsBaseFileInUse() && m_Data
.IsYourFileInUse() && m_Data
.IsTheirFileInUse())
719 //diff between THEIR, YOUR and BASE
720 m_pwndBottomView
->UseCaret();
721 pwndActiveView
= m_pwndBottomView
;
723 m_pwndLeftView
->m_pViewData
= &m_Data
.m_TheirBaseBoth
;
724 m_pwndLeftView
->texttype
= m_Data
.m_arTheirFile
.GetUnicodeType();
725 m_pwndLeftView
->lineendings
= m_Data
.m_arTheirFile
.GetLineEndings();
726 m_pwndLeftView
->m_sWindowName
.LoadString(IDS_VIEWTITLE_THEIRS
);
727 m_pwndLeftView
->m_sWindowName
+= _T(" - ") + m_Data
.m_theirFile
.GetWindowName();
728 m_pwndLeftView
->m_sFullFilePath
= m_Data
.m_theirFile
.GetFilename();
730 m_pwndRightView
->m_pViewData
= &m_Data
.m_YourBaseBoth
;
731 m_pwndRightView
->texttype
= m_Data
.m_arYourFile
.GetUnicodeType();
732 m_pwndRightView
->lineendings
= m_Data
.m_arYourFile
.GetLineEndings();
733 m_pwndRightView
->m_sWindowName
.LoadString(IDS_VIEWTITLE_MINE
);
734 m_pwndRightView
->m_sWindowName
+= _T(" - ") + m_Data
.m_yourFile
.GetWindowName();
735 m_pwndRightView
->m_sFullFilePath
= m_Data
.m_yourFile
.GetFilename();
737 m_pwndBottomView
->m_pViewData
= &m_Data
.m_Diff3
;
738 m_pwndBottomView
->texttype
= m_Data
.m_arTheirFile
.GetUnicodeType();
739 m_pwndBottomView
->lineendings
= m_Data
.m_arTheirFile
.GetLineEndings();
740 m_pwndBottomView
->m_sWindowName
.LoadString(IDS_VIEWTITLE_MERGED
);
741 m_pwndBottomView
->m_sWindowName
+= _T(" - ") + m_Data
.m_mergedFile
.GetWindowName();
742 m_pwndBottomView
->m_sFullFilePath
= m_Data
.m_mergedFile
.GetFilename();
744 if (m_wndSplitter2
.IsColumnHidden(1))
745 m_wndSplitter2
.ShowColumn();
746 if (m_wndSplitter
.IsRowHidden(1))
747 m_wndSplitter
.ShowRow();
748 m_pwndLeftView
->SetHidden(FALSE
);
749 m_pwndRightView
->SetHidden(FALSE
);
750 m_pwndBottomView
->SetHidden(FALSE
);
751 // in three pane view, hide the line diff bar
752 m_wndLineDiffBar
.ShowPane(false, false, true);
753 m_wndLineDiffBar
.DocumentUpdated();
755 if (!m_Data
.m_mergedFile
.InUse())
757 m_Data
.m_mergedFile
.SetFileName(m_Data
.m_yourFile
.GetFilename());
759 m_pwndLeftView
->DocumentUpdated();
760 m_pwndRightView
->DocumentUpdated();
761 m_pwndBottomView
->DocumentUpdated();
762 m_wndLocatorBar
.DocumentUpdated();
763 m_wndLineDiffBar
.DocumentUpdated();
765 SetActiveView(pwndActiveView
);
767 if (bRetainPosition
&& m_pwndLeftView
->m_pViewData
)
769 int n
= nOldLineNumber
;
771 n
= m_pwndLeftView
->m_pViewData
->FindLineNumber(n
);
775 m_pwndLeftView
->ScrollAllToLine(n
);
779 m_pwndLeftView
->SetCaretPosition(p
);
783 bool bGoFirstDiff
= (0 != (DWORD
)CRegDWORD(_T("Software\\TortoiseMerge\\FirstDiffOnLoad"), TRUE
));
785 pwndActiveView
->GoToFirstDifference();
786 // Ignore the first few Mouse Move messages, so that the line diff stays on
787 // the first diff line until the user actually moves the mouse
788 m_nMoveMovesToIgnore
= 3;
792 // Avoid incorrect rendering of active pane.
793 m_pwndBottomView
->ScrollToChar(0);
794 m_pwndLeftView
->ScrollToChar(0);
795 m_pwndRightView
->ScrollToChar(0);
797 CUndo::GetInstance().Clear();
801 void CMainFrame::UpdateLayout()
807 int width
= cr
.Width();
808 if (::IsWindow(m_wndLocatorBar
) && m_wndLocatorBar
.IsWindowVisible())
810 m_wndLocatorBar
.GetWindowRect(&rclocbar
);
811 width
-= rclocbar
.Width();
813 m_wndSplitter
.SetRowInfo(0, cr
.Height()/2, 0);
814 m_wndSplitter
.SetRowInfo(1, cr
.Height()/2, 0);
815 m_wndSplitter
.SetColumnInfo(0, width
/ 2, 50);
816 m_wndSplitter2
.SetRowInfo(0, cr
.Height()/2, 0);
817 m_wndSplitter2
.SetColumnInfo(0, width
/ 2, 50);
818 m_wndSplitter2
.SetColumnInfo(1, width
/ 2, 50);
820 m_wndSplitter
.RecalcLayout();
824 void CMainFrame::OnSize(UINT nType
, int cx
, int cy
)
826 if (m_bInitSplitter
&& nType
!= SIZE_MINIMIZED
)
830 CFrameWndEx::OnSize(nType
, cx
, cy
);
833 void CMainFrame::OnViewWhitespaces()
835 CRegDWORD regViewWhitespaces
= CRegDWORD(_T("Software\\TortoiseMerge\\ViewWhitespaces"), 1);
836 BOOL bViewWhitespaces
= regViewWhitespaces
;
838 bViewWhitespaces
= m_pwndLeftView
->m_bViewWhitespace
;
840 bViewWhitespaces
= !bViewWhitespaces
;
841 regViewWhitespaces
= bViewWhitespaces
;
844 m_pwndLeftView
->m_bViewWhitespace
= bViewWhitespaces
;
845 m_pwndLeftView
->Invalidate();
849 m_pwndRightView
->m_bViewWhitespace
= bViewWhitespaces
;
850 m_pwndRightView
->Invalidate();
852 if (m_pwndBottomView
)
854 m_pwndBottomView
->m_bViewWhitespace
= bViewWhitespaces
;
855 m_pwndBottomView
->Invalidate();
859 void CMainFrame::OnUpdateViewWhitespaces(CCmdUI
*pCmdUI
)
862 pCmdUI
->SetCheck(m_pwndLeftView
->m_bViewWhitespace
);
865 void CMainFrame::OnViewOnewaydiff()
867 if (CheckForSave()==IDCANCEL
)
869 m_bOneWay
= !m_bOneWay
;
872 // in one way view, hide the line diff bar
873 m_wndLineDiffBar
.ShowPane(false, false, true);
874 m_wndLineDiffBar
.DocumentUpdated();
878 // restore the line diff bar
879 m_wndLineDiffBar
.ShowPane(m_bLineDiff
, false, true);
880 m_wndLineDiffBar
.DocumentUpdated();
881 m_wndLocatorBar
.ShowPane(m_bLocatorBar
, false, true);
882 m_wndLocatorBar
.DocumentUpdated();
887 void CMainFrame::ShowDiffBar(bool bShow
)
891 // restore the line diff bar
892 m_wndLineDiffBar
.ShowPane(m_bLineDiff
, false, true);
893 m_wndLineDiffBar
.DocumentUpdated();
894 m_wndLocatorBar
.ShowPane(m_bLocatorBar
, false, true);
895 m_wndLocatorBar
.DocumentUpdated();
899 // in one way view, hide the line diff bar
900 m_wndLineDiffBar
.ShowPane(false, false, true);
901 m_wndLineDiffBar
.DocumentUpdated();
905 int CMainFrame::CheckResolved()
907 //only in three way diffs can be conflicts!
908 m_bHasConflicts
= true;
909 if (m_pwndBottomView
->IsWindowVisible())
911 if (m_pwndBottomView
->m_pViewData
)
913 for (int i
=0; i
<m_pwndBottomView
->m_pViewData
->GetCount(); i
++)
915 if ((DIFFSTATE_CONFLICTED
== m_pwndBottomView
->m_pViewData
->GetState(i
))||
916 (DIFFSTATE_CONFLICTED_IGNORED
== m_pwndBottomView
->m_pViewData
->GetState(i
)))
921 m_bHasConflicts
= false;
925 int CMainFrame::SaveFile(const CString
& sFilePath
)
927 CViewData
* pViewData
= NULL
;
928 CFileTextLines
* pOriginFile
= &m_Data
.m_arBaseFile
;
929 if ((m_pwndBottomView
)&&(m_pwndBottomView
->IsWindowVisible()))
931 pViewData
= m_pwndBottomView
->m_pViewData
;
934 else if ((m_pwndRightView
)&&(m_pwndRightView
->IsWindowVisible()))
936 pViewData
= m_pwndRightView
->m_pViewData
;
937 if (m_Data
.IsYourFileInUse())
938 pOriginFile
= &m_Data
.m_arYourFile
;
939 else if (m_Data
.IsTheirFileInUse())
940 pOriginFile
= &m_Data
.m_arTheirFile
;
948 if ((pViewData
)&&(pOriginFile
))
951 pOriginFile
->CopySettings(&file
);
952 for (int i
=0; i
<pViewData
->GetCount(); i
++)
954 //only copy non-removed lines
955 DiffStates state
= pViewData
->GetState(i
);
958 case DIFFSTATE_CONFLICTED
:
959 case DIFFSTATE_CONFLICTED_IGNORED
:
966 } while((last
<pViewData
->GetCount()) && ((pViewData
->GetState(last
)==DIFFSTATE_CONFLICTED
)||(pViewData
->GetState(last
)==DIFFSTATE_CONFLICTED_IGNORED
)));
967 file
.Add(_T("<<<<<<< .mine"), EOL_NOENDING
);
968 for (int j
=first
; j
<last
; j
++)
970 file
.Add(m_pwndRightView
->m_pViewData
->GetLine(j
), m_pwndRightView
->m_pViewData
->GetLineEnding(j
));
972 file
.Add(_T("======="), EOL_NOENDING
);
973 for (int j
=first
; j
<last
; j
++)
975 file
.Add(m_pwndLeftView
->m_pViewData
->GetLine(j
), m_pwndLeftView
->m_pViewData
->GetLineEnding(j
));
977 file
.Add(_T(">>>>>>> .theirs"), EOL_NOENDING
);
981 case DIFFSTATE_EMPTY
:
982 case DIFFSTATE_CONFLICTEMPTY
:
983 case DIFFSTATE_IDENTICALREMOVED
:
984 case DIFFSTATE_REMOVED
:
985 case DIFFSTATE_THEIRSREMOVED
:
986 case DIFFSTATE_YOURSREMOVED
:
987 case DIFFSTATE_CONFLICTRESOLVEDEMPTY
:
988 // do not save removed lines
991 file
.Add(pViewData
->GetLine(i
), pViewData
->GetLineEnding(i
));
995 if (!file
.Save(sFilePath
, false))
997 CMessageBox::Show(m_hWnd
, file
.GetErrorString(), _T("TortoiseMerge"), MB_ICONERROR
);
1000 m_dlgFilePatches
.SetFileStatusAsPatched(sFilePath
);
1001 if (m_pwndBottomView
)
1002 m_pwndBottomView
->SetModified(FALSE
);
1003 if (m_pwndRightView
)
1004 m_pwndRightView
->SetModified(FALSE
);
1005 CUndo::GetInstance().MarkAsOriginalState();
1006 return file
.GetCount();
1011 void CMainFrame::OnFileSave()
1016 bool CMainFrame::FileSave(bool bCheckResolved
/*=true*/)
1018 if (!m_Data
.m_mergedFile
.InUse())
1019 return FileSaveAs(bCheckResolved
);
1020 // check if the file has the readonly attribute set
1021 bool bDoesNotExist
= false;
1022 DWORD fAttribs
= GetFileAttributes(m_Data
.m_mergedFile
.GetFilename());
1023 if ((fAttribs
!= INVALID_FILE_ATTRIBUTES
)&&(fAttribs
& FILE_ATTRIBUTE_READONLY
))
1024 return FileSaveAs(bCheckResolved
);
1025 if (fAttribs
== INVALID_FILE_ATTRIBUTES
)
1027 bDoesNotExist
= (GetLastError() == ERROR_FILE_NOT_FOUND
);
1031 int nConflictLine
= CheckResolved();
1032 if (nConflictLine
>= 0)
1035 sTemp
.Format(IDS_ERR_MAINFRAME_FILEHASCONFLICTS
, m_pwndBottomView
->m_pViewData
->GetLineNumber(nConflictLine
)+1);
1036 if (MessageBox(sTemp
, 0, MB_ICONERROR
| MB_YESNO
)!=IDYES
)
1038 if (m_pwndBottomView
)
1039 m_pwndBottomView
->GoToLine(nConflictLine
);
1044 if (((DWORD
)CRegDWORD(_T("Software\\TortoiseMerge\\Backup"))) != 0)
1046 MoveFileEx(m_Data
.m_mergedFile
.GetFilename(), m_Data
.m_mergedFile
.GetFilename() + _T(".bak"), MOVEFILE_COPY_ALLOWED
| MOVEFILE_REPLACE_EXISTING
| MOVEFILE_WRITE_THROUGH
);
1048 if (SaveFile(m_Data
.m_mergedFile
.GetFilename())==0)
1050 // file was saved with 0 lines!
1051 // ask the user if the file should be deleted
1053 sTemp
.Format(IDS_DELETEWHENEMPTY
, (LPCTSTR
)m_Data
.m_mergedFile
.GetFilename());
1054 if (CMessageBox::ShowCheck(m_hWnd
, sTemp
, _T("TortoiseMerge"), MB_YESNO
, _T("DeleteFileWhenEmpty")) == IDYES
)
1056 DeleteFile(m_Data
.m_mergedFile
.GetFilename());
1062 // call TortoiseProc to add the new file to version control
1063 CString cmd
= _T("\"") + CPathUtils::GetAppDirectory();
1064 cmd
+= _T("TortoiseProc.exe\" /command:add /noui /path:\"");
1065 cmd
+= m_Data
.m_mergedFile
.GetFilename() + _T("\"");
1066 TCHAR
* buf
= new TCHAR
[cmd
.GetLength()+1];
1067 _tcscpy_s(buf
, cmd
.GetLength()+1, cmd
);
1068 STARTUPINFO startup
;
1069 PROCESS_INFORMATION process
;
1070 memset(&startup
, 0, sizeof(startup
));
1071 startup
.cb
= sizeof(startup
);
1072 memset(&process
, 0, sizeof(process
));
1073 if (CreateProcess(NULL
, buf
, NULL
, NULL
, FALSE
, 0, 0, 0, &startup
, &process
)==0)
1077 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
|
1078 FORMAT_MESSAGE_FROM_SYSTEM
|
1079 FORMAT_MESSAGE_IGNORE_INSERTS
,
1082 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
), // Default language
1087 MessageBox((LPCTSTR
)lpMsgBuf
, _T("TortoiseMerge"), MB_OK
| MB_ICONINFORMATION
);
1088 LocalFree( lpMsgBuf
);
1092 CloseHandle(process
.hThread
);
1093 CloseHandle(process
.hProcess
);
1098 void CMainFrame::OnFileSaveAs()
1103 bool CMainFrame::FileSaveAs(bool bCheckResolved
/*=true*/)
1107 int nConflictLine
= CheckResolved();
1108 if (nConflictLine
>= 0)
1111 sTemp
.Format(IDS_ERR_MAINFRAME_FILEHASCONFLICTS
, m_pwndBottomView
->m_pViewData
->GetLineNumber(nConflictLine
)+1);
1112 if (MessageBox(sTemp
, 0, MB_ICONERROR
| MB_YESNO
)!=IDYES
)
1114 if (m_pwndBottomView
)
1115 m_pwndBottomView
->GoToLine(nConflictLine
);
1120 OPENFILENAME ofn
= {0}; // common dialog box structure
1121 TCHAR szFile
[MAX_PATH
] = {0}; // buffer for file name
1122 ofn
.lStructSize
= sizeof(OPENFILENAME
);
1123 ofn
.hwndOwner
= m_hWnd
;
1124 ofn
.lpstrFile
= szFile
;
1125 ofn
.nMaxFile
= sizeof(szFile
)/sizeof(TCHAR
);
1127 temp
.LoadString(IDS_SAVEASTITLE
);
1128 if (!temp
.IsEmpty())
1129 ofn
.lpstrTitle
= temp
;
1130 ofn
.Flags
= OFN_OVERWRITEPROMPT
;
1132 sFilter
.LoadString(IDS_COMMONFILEFILTER
);
1133 TCHAR
* pszFilters
= new TCHAR
[sFilter
.GetLength()+4];
1134 _tcscpy_s (pszFilters
, sFilter
.GetLength()+4, sFilter
);
1135 // Replace '|' delimiters with '\0's
1136 TCHAR
*ptr
= pszFilters
+ _tcslen(pszFilters
); //set ptr at the NULL
1137 while (ptr
!= pszFilters
)
1143 ofn
.lpstrFilter
= pszFilters
;
1144 ofn
.nFilterIndex
= 1;
1146 // Display the Open dialog box.
1148 if (GetSaveFileName(&ofn
)==TRUE
)
1150 sFile
= CString(ofn
.lpstrFile
);
1152 delete [] pszFilters
;
1155 delete [] pszFilters
;
1159 void CMainFrame::OnUpdateFileSave(CCmdUI
*pCmdUI
)
1161 BOOL bEnable
= FALSE
;
1162 if (m_Data
.m_mergedFile
.InUse())
1164 if (m_pwndBottomView
)
1166 if ((m_pwndBottomView
->IsWindowVisible())&&(m_pwndBottomView
->m_pViewData
))
1171 if (m_pwndRightView
)
1173 if ((m_pwndRightView
->IsWindowVisible())&&(m_pwndRightView
->m_pViewData
))
1175 if (m_pwndRightView
->IsModified() || (m_Data
.m_yourFile
.GetWindowName().Right(9).Compare(_T(": patched"))==0))
1180 pCmdUI
->Enable(bEnable
);
1183 void CMainFrame::OnUpdateFileSaveAs(CCmdUI
*pCmdUI
)
1185 BOOL bEnable
= FALSE
;
1186 if (m_pwndBottomView
)
1188 if ((m_pwndBottomView
->IsWindowVisible())&&(m_pwndBottomView
->m_pViewData
))
1193 if (m_pwndRightView
)
1195 if ((m_pwndRightView
->IsWindowVisible())&&(m_pwndRightView
->m_pViewData
))
1200 pCmdUI
->Enable(bEnable
);
1204 void CMainFrame::OnUpdateViewOnewaydiff(CCmdUI
*pCmdUI
)
1206 pCmdUI
->SetCheck(!m_bOneWay
);
1207 BOOL bEnable
= TRUE
;
1208 if (m_pwndBottomView
)
1210 if (m_pwndBottomView
->IsWindowVisible())
1213 pCmdUI
->Enable(bEnable
);
1216 void CMainFrame::OnViewOptions()
1219 sTemp
.LoadString(IDS_SETTINGSTITLE
);
1220 CSettings
dlg(sTemp
);
1222 if (dlg
.IsReloadNeeded())
1224 if (CheckForSave()==IDCANCEL
)
1226 CDiffColors::GetInstance().LoadRegistry();
1230 CDiffColors::GetInstance().LoadRegistry();
1231 if (m_pwndBottomView
)
1232 m_pwndBottomView
->Invalidate();
1234 m_pwndLeftView
->Invalidate();
1235 if (m_pwndRightView
)
1236 m_pwndRightView
->Invalidate();
1239 void CMainFrame::OnClose()
1241 if ((m_pFindDialog
)&&(!m_pFindDialog
->IsTerminating()))
1243 m_pFindDialog
->SendMessage(WM_CLOSE
);
1247 if (((m_pwndBottomView
)&&(m_pwndBottomView
->IsModified())) ||
1248 ((m_pwndRightView
)&&(m_pwndRightView
->IsModified())))
1251 sTemp
.LoadString(IDS_ASKFORSAVE
);
1252 ret
= MessageBox(sTemp
, 0, MB_YESNOCANCEL
| MB_ICONQUESTION
);
1259 if ((ret
== IDNO
)||(ret
== IDYES
))
1263 // before it is destroyed, save the position of the window
1264 wp
.length
= sizeof wp
;
1266 if (GetWindowPlacement(&wp
))
1270 // never restore to Iconic state
1271 wp
.showCmd
= SW_SHOW
;
1273 if ((wp
.flags
& WPF_RESTORETOMAXIMIZED
) != 0)
1274 // if maximized and maybe iconic restore maximized state
1275 wp
.showCmd
= SW_SHOWMAXIMIZED
;
1277 // and write it to the .INI file
1278 WriteWindowPlacement(&wp
);
1284 void CMainFrame::OnEditFind()
1292 // start searching from the start again
1293 // if no line is selected, otherwise start from
1294 // the selected line
1295 m_nSearchIndex
= FindSearchStart(0);
1296 m_pFindDialog
= new CFindDlg();
1297 m_pFindDialog
->Create(this);
1301 LRESULT
CMainFrame::OnFindDialogMessage(WPARAM
/*wParam*/, LPARAM
/*lParam*/)
1303 ASSERT(m_pFindDialog
!= NULL
);
1305 if (m_pFindDialog
->IsTerminating())
1307 // invalidate the handle identifying the dialog box.
1308 m_pFindDialog
= NULL
;
1312 if(m_pFindDialog
->FindNext())
1314 //read data from dialog
1315 m_sFindText
= m_pFindDialog
->GetFindString();
1316 m_bMatchCase
= (m_pFindDialog
->MatchCase() == TRUE
);
1317 m_bLimitToDiff
= m_pFindDialog
->LimitToDiffs();
1318 m_bWholeWord
= m_pFindDialog
->WholeWord();
1326 bool CharIsDelimiter(const CString
& ch
)
1328 CString
delimiters(_T(" .,:;=+-*/\\\n\t()[]<>@"));
1329 return delimiters
.Find(ch
) >= 0;
1332 bool CMainFrame::StringFound(const CString
& str
)const
1334 int nSubStringStartIdx
= str
.Find(m_sFindText
);
1335 bool bStringFound
= (nSubStringStartIdx
>= 0);
1336 if (bStringFound
&& m_bWholeWord
)
1338 if (nSubStringStartIdx
)
1339 bStringFound
= CharIsDelimiter(str
.Mid(nSubStringStartIdx
-1,1));
1343 int nEndIndex
= nSubStringStartIdx
+ m_sFindText
.GetLength();
1344 if (str
.GetLength() > nEndIndex
)
1345 bStringFound
= CharIsDelimiter(str
.Mid(nEndIndex
, 1));
1348 return bStringFound
;
1351 void CMainFrame::OnEditFindprev()
1353 Search(SearchPrevious
);
1356 void CMainFrame::OnEditFindnext()
1361 void CMainFrame::Search(SearchDirection srchDir
)
1363 if (m_sFindText
.IsEmpty())
1366 if ((m_pwndLeftView
)&&(m_pwndLeftView
->m_pViewData
))
1368 bool bFound
= FALSE
;
1373 DiffStates leftstate
= DIFFSTATE_NORMAL
;
1374 DiffStates rightstate
= DIFFSTATE_NORMAL
;
1375 DiffStates bottomstate
= DIFFSTATE_NORMAL
;
1378 m_nSearchIndex
= FindSearchStart(m_nSearchIndex
);
1380 if (m_nSearchIndex
>= m_pwndLeftView
->m_pViewData
->GetCount())
1382 if (srchDir
== SearchPrevious
)
1384 // SearchIndex points 1 past where we found the last match,
1385 // so if we are searching backwards we need to adjust accordingly
1386 m_nSearchIndex
-= 2;
1387 // if at the top, start again from the end
1388 if (m_nSearchIndex
< 0)
1389 m_nSearchIndex
+= m_pwndLeftView
->m_pViewData
->GetCount();
1391 const int idxLimits
[2][2][2]={{{m_nSearchIndex
, m_pwndLeftView
->m_pViewData
->GetCount()},
1392 {0, m_nSearchIndex
}},
1393 {{m_nSearchIndex
, -1},
1394 {m_pwndLeftView
->m_pViewData
->GetCount()-1, m_nSearchIndex
}}};
1395 const int offsets
[2]={+1, -1};
1397 for (int j
=0; j
!= 2 && !bFound
; ++j
)
1399 for (i
=idxLimits
[srchDir
][j
][0]; i
!= idxLimits
[srchDir
][j
][1]; i
+= offsets
[srchDir
])
1401 left
= m_pwndLeftView
->m_pViewData
->GetLine(i
);
1402 leftstate
= m_pwndLeftView
->m_pViewData
->GetState(i
);
1403 if ((!m_bOneWay
)&&(m_pwndRightView
->m_pViewData
))
1405 right
= m_pwndRightView
->m_pViewData
->GetLine(i
);
1406 rightstate
= m_pwndRightView
->m_pViewData
->GetState(i
);
1408 if ((m_pwndBottomView
)&&(m_pwndBottomView
->m_pViewData
))
1410 bottom
= m_pwndBottomView
->m_pViewData
->GetLine(i
);
1411 bottomstate
= m_pwndBottomView
->m_pViewData
->GetState(i
);
1416 left
= left
.MakeLower();
1417 right
= right
.MakeLower();
1418 bottom
= bottom
.MakeLower();
1419 m_sFindText
= m_sFindText
.MakeLower();
1421 if (StringFound(left
))
1423 if ((!m_bLimitToDiff
)||(leftstate
!= DIFFSTATE_NORMAL
))
1429 else if (StringFound(right
))
1431 if ((!m_bLimitToDiff
)||(rightstate
!= DIFFSTATE_NORMAL
))
1437 else if (StringFound(bottom
))
1439 if ((!m_bLimitToDiff
)||(bottomstate
!= DIFFSTATE_NORMAL
))
1450 m_pwndLeftView
->GoToLine(m_nSearchIndex
);
1451 if (StringFound(left
))
1453 m_pwndLeftView
->SetFocus();
1454 m_pwndLeftView
->HiglightLines(m_nSearchIndex
);
1456 else if (StringFound(right
))
1458 m_pwndRightView
->SetFocus();
1459 m_pwndRightView
->HiglightLines(m_nSearchIndex
);
1461 else if (StringFound(bottom
))
1463 m_pwndBottomView
->SetFocus();
1464 m_pwndBottomView
->HiglightLines(m_nSearchIndex
);
1474 int CMainFrame::FindSearchStart(int nDefault
)
1476 // TortoiseMerge doesn't have a cursor which we could use to
1477 // anchor the search on.
1478 // Instead we use a line that is selected.
1479 // If however no line is selected, use the default line (which could
1480 // be the top of the document for a new search, or the line where the
1481 // search was successful on)
1482 int nLine
= nDefault
;
1487 if (m_pwndLeftView
->GetSelection(nSelStart
, nSelEnd
))
1489 if (nSelStart
== nSelEnd
)
1493 else if ((nLine
== nDefault
)&&(m_pwndRightView
))
1495 if (m_pwndRightView
->GetSelection(nSelStart
, nSelEnd
))
1497 if (nSelStart
== nSelEnd
)
1501 else if ((nLine
== nDefault
)&&(m_pwndBottomView
))
1503 if (m_pwndBottomView
->GetSelection(nSelStart
, nSelEnd
))
1505 if (nSelStart
== nSelEnd
)
1512 void CMainFrame::OnViewLinedown()
1515 m_pwndLeftView
->ScrollToLine(m_pwndLeftView
->m_nTopLine
+1);
1516 if (m_pwndRightView
)
1517 m_pwndRightView
->ScrollToLine(m_pwndRightView
->m_nTopLine
+1);
1518 if (m_pwndBottomView
)
1519 m_pwndBottomView
->ScrollToLine(m_pwndBottomView
->m_nTopLine
+1);
1520 m_wndLocatorBar
.Invalidate();
1523 void CMainFrame::OnViewLineup()
1526 m_pwndLeftView
->ScrollToLine(m_pwndLeftView
->m_nTopLine
-1);
1527 if (m_pwndRightView
)
1528 m_pwndRightView
->ScrollToLine(m_pwndRightView
->m_nTopLine
-1);
1529 if (m_pwndBottomView
)
1530 m_pwndBottomView
->ScrollToLine(m_pwndBottomView
->m_nTopLine
-1);
1531 m_wndLocatorBar
.Invalidate();
1534 void CMainFrame::OnViewLineleft()
1537 m_pwndLeftView
->ScrollSide(-1);
1538 if (m_pwndRightView
)
1539 m_pwndRightView
->ScrollSide(-1);
1540 if (m_pwndBottomView
)
1541 m_pwndBottomView
->ScrollSide(-1);
1544 void CMainFrame::OnViewLineright()
1547 m_pwndLeftView
->ScrollSide(1);
1548 if (m_pwndRightView
)
1549 m_pwndRightView
->ScrollSide(1);
1550 if (m_pwndBottomView
)
1551 m_pwndBottomView
->ScrollSide(1);
1554 void CMainFrame::OnEditUseTheirs()
1556 if (m_pwndBottomView
)
1557 m_pwndBottomView
->UseTheirTextBlock();
1559 void CMainFrame::OnUpdateEditUsetheirblock(CCmdUI
*pCmdUI
)
1561 int nSelBlockStart
= -1;
1562 int nSelBlockEnd
= -1;
1563 if (m_pwndBottomView
)
1564 m_pwndBottomView
->GetSelection(nSelBlockStart
, nSelBlockEnd
);
1565 pCmdUI
->Enable((nSelBlockStart
>= 0)&&(nSelBlockEnd
>= 0));
1569 void CMainFrame::OnEditUseMine()
1571 if (m_pwndBottomView
)
1572 m_pwndBottomView
->UseMyTextBlock();
1574 void CMainFrame::OnUpdateEditUsemyblock(CCmdUI
*pCmdUI
)
1576 int nSelBlockStart
= -1;
1577 int nSelBlockEnd
= -1;
1578 if (m_pwndBottomView
)
1579 m_pwndBottomView
->GetSelection(nSelBlockStart
, nSelBlockEnd
);
1580 pCmdUI
->Enable((nSelBlockStart
>= 0)&&(nSelBlockEnd
>= 0));
1584 void CMainFrame::OnEditUseTheirsThenMine()
1586 if (m_pwndBottomView
)
1587 m_pwndBottomView
->UseTheirThenMyTextBlock();
1589 void CMainFrame::OnUpdateEditUsetheirthenmyblock(CCmdUI
*pCmdUI
)
1591 int nSelBlockStart
= -1;
1592 int nSelBlockEnd
= -1;
1593 if (m_pwndBottomView
)
1594 m_pwndBottomView
->GetSelection(nSelBlockStart
, nSelBlockEnd
);
1595 pCmdUI
->Enable((nSelBlockStart
>= 0)&&(nSelBlockEnd
>= 0));
1599 void CMainFrame::OnEditUseMineThenTheirs()
1601 if (m_pwndBottomView
)
1602 m_pwndBottomView
->UseMyThenTheirTextBlock();
1604 void CMainFrame::OnUpdateEditUseminethentheirblock(CCmdUI
*pCmdUI
)
1606 int nSelBlockStart
= -1;
1607 int nSelBlockEnd
= -1;
1608 if (m_pwndBottomView
)
1609 m_pwndBottomView
->GetSelection(nSelBlockStart
, nSelBlockEnd
);
1610 pCmdUI
->Enable((nSelBlockStart
>= 0)&&(nSelBlockEnd
>= 0));
1613 void CMainFrame::OnEditUseleftblock()
1615 if (m_pwndRightView
)
1616 m_pwndRightView
->UseBlock();
1619 void CMainFrame::OnUpdateEditUseleftblock(CCmdUI
*pCmdUI
)
1621 pCmdUI
->Enable(m_pwndRightView
&& m_pwndRightView
->IsWindowVisible() && m_pwndRightView
->HasCaret() && m_pwndRightView
->HasSelection());
1624 void CMainFrame::OnEditUseleftfile()
1626 if (m_pwndRightView
)
1627 m_pwndRightView
->UseFile();
1630 void CMainFrame::OnUpdateEditUseleftfile(CCmdUI
*pCmdUI
)
1632 pCmdUI
->Enable(m_pwndRightView
&& m_pwndRightView
->IsWindowVisible() && m_pwndRightView
->HasCaret());
1635 void CMainFrame::OnEditUseblockfromleftbeforeright()
1637 if (m_pwndRightView
)
1638 m_pwndRightView
->UseLeftBeforeRight();
1641 void CMainFrame::OnUpdateEditUseblockfromleftbeforeright(CCmdUI
*pCmdUI
)
1643 pCmdUI
->Enable(m_pwndRightView
&& m_pwndRightView
->IsWindowVisible() && m_pwndRightView
->HasCaret() && m_pwndRightView
->HasSelection());
1646 void CMainFrame::OnEditUseblockfromrightbeforeleft()
1648 if (m_pwndRightView
)
1649 m_pwndRightView
->UseRightBeforeLeft();
1652 void CMainFrame::OnUpdateEditUseblockfromrightbeforeleft(CCmdUI
*pCmdUI
)
1654 pCmdUI
->Enable(m_pwndRightView
&& m_pwndRightView
->IsWindowVisible() && m_pwndRightView
->HasCaret() && m_pwndRightView
->HasSelection());
1658 void CMainFrame::OnFileReload()
1660 if (CheckForSave()==IDCANCEL
)
1662 CDiffColors::GetInstance().LoadRegistry();
1666 void CMainFrame::ActivateFrame(int nCmdShow
)
1668 // nCmdShow is the normal show mode this frame should be in
1669 // translate default nCmdShow (-1)
1672 if (!IsWindowVisible())
1673 nCmdShow
= SW_SHOWNORMAL
;
1674 else if (IsIconic())
1675 nCmdShow
= SW_RESTORE
;
1678 // bring to top before showing
1679 BringToTop(nCmdShow
);
1683 // show the window as specified
1686 if ( !ReadWindowPlacement(&wp
) )
1688 ShowWindow(nCmdShow
);
1692 if ( nCmdShow
!= SW_SHOWNORMAL
)
1693 wp
.showCmd
= nCmdShow
;
1695 SetWindowPlacement(&wp
);
1698 // and finally, bring to top after showing
1699 BringToTop(nCmdShow
);
1704 BOOL
CMainFrame::ReadWindowPlacement(WINDOWPLACEMENT
* pwp
)
1706 CRegString placement
= CRegString(_T("Software\\TortoiseMerge\\WindowPos"));
1707 CString sPlacement
= placement
;
1708 if (sPlacement
.IsEmpty())
1710 int nRead
= _stscanf_s(sPlacement
, _T("%u,%u,%d,%d,%d,%d,%d,%d,%d,%d"),
1711 &pwp
->flags
, &pwp
->showCmd
,
1712 &pwp
->ptMinPosition
.x
, &pwp
->ptMinPosition
.y
,
1713 &pwp
->ptMaxPosition
.x
, &pwp
->ptMaxPosition
.y
,
1714 &pwp
->rcNormalPosition
.left
, &pwp
->rcNormalPosition
.top
,
1715 &pwp
->rcNormalPosition
.right
, &pwp
->rcNormalPosition
.bottom
);
1718 pwp
->length
= sizeof(WINDOWPLACEMENT
);
1723 void CMainFrame::WriteWindowPlacement(WINDOWPLACEMENT
* pwp
)
1725 CRegString placement
= CRegString(_T("Software\\TortoiseMerge\\WindowPos"));
1726 TCHAR szBuffer
[sizeof("-32767")*8 + sizeof("65535")*2];
1729 _stprintf_s(szBuffer
, sizeof("-32767")*8 + sizeof("65535")*2, _T("%u,%u,%d,%d,%d,%d,%d,%d,%d,%d"),
1730 pwp
->flags
, pwp
->showCmd
,
1731 pwp
->ptMinPosition
.x
, pwp
->ptMinPosition
.y
,
1732 pwp
->ptMaxPosition
.x
, pwp
->ptMaxPosition
.y
,
1733 pwp
->rcNormalPosition
.left
, pwp
->rcNormalPosition
.top
,
1734 pwp
->rcNormalPosition
.right
, pwp
->rcNormalPosition
.bottom
);
1735 placement
= szBuffer
;
1738 void CMainFrame::OnUpdateMergeMarkasresolved(CCmdUI
*pCmdUI
)
1742 BOOL bEnable
= FALSE
;
1743 if ((!m_bReadOnly
)&&(m_Data
.m_mergedFile
.InUse()))
1745 if (m_pwndBottomView
)
1747 if ((m_pwndBottomView
->IsWindowVisible())&&(m_pwndBottomView
->m_pViewData
))
1753 pCmdUI
->Enable(bEnable
);
1756 void CMainFrame::OnMergeMarkasresolved()
1758 int nConflictLine
= CheckResolved();
1759 if (nConflictLine
>= 0)
1762 sTemp
.Format(IDS_ERR_MAINFRAME_FILEHASCONFLICTS
, m_pwndBottomView
->m_pViewData
->GetLineNumber(nConflictLine
)+1);
1763 if (MessageBox(sTemp
, 0, MB_ICONERROR
| MB_YESNO
)!=IDYES
)
1765 if (m_pwndBottomView
)
1766 m_pwndBottomView
->GoToLine(nConflictLine
);
1770 // now check if the file has already been saved and if not, save it.
1771 if (m_Data
.m_mergedFile
.InUse())
1773 if (m_pwndBottomView
)
1775 if ((m_pwndBottomView
->IsWindowVisible())&&(m_pwndBottomView
->m_pViewData
))
1784 BOOL
CMainFrame::MarkAsResolved()
1788 if ((m_pwndBottomView
)&&(m_pwndBottomView
->IsWindowVisible()))
1790 TCHAR buf
[MAX_PATH
*3];
1791 GetModuleFileName(NULL
, buf
, MAX_PATH
);
1792 TCHAR
* end
= _tcsrchr(buf
, '\\');
1795 _tcscat_s(buf
, MAX_PATH
*3, _T("TortoiseProc.exe /command:resolve /path:\""));
1796 _tcscat_s(buf
, MAX_PATH
*3, m_Data
.m_mergedFile
.GetFilename());
1797 _tcscat_s(buf
, MAX_PATH
*3, _T("\" /closeonend:1 /noquestion /skipcheck"));
1798 STARTUPINFO startup
;
1799 PROCESS_INFORMATION process
;
1800 memset(&startup
, 0, sizeof(startup
));
1801 startup
.cb
= sizeof(startup
);
1802 memset(&process
, 0, sizeof(process
));
1803 if (CreateProcess(NULL
, buf
, NULL
, NULL
, FALSE
, 0, 0, 0, &startup
, &process
)==0)
1806 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
|
1807 FORMAT_MESSAGE_FROM_SYSTEM
|
1808 FORMAT_MESSAGE_IGNORE_INSERTS
,
1811 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
), // Default language
1816 MessageBox((LPCTSTR
)lpMsgBuf
, _T("TortoiseMerge"), MB_OK
| MB_ICONINFORMATION
);
1817 LocalFree( lpMsgBuf
);
1820 CloseHandle(process
.hThread
);
1821 CloseHandle(process
.hProcess
);
1828 void CMainFrame::OnUpdateMergeNextconflict(CCmdUI
*pCmdUI
)
1830 pCmdUI
->Enable(m_bHasConflicts
);
1833 void CMainFrame::OnUpdateMergePreviousconflict(CCmdUI
*pCmdUI
)
1835 pCmdUI
->Enable(m_bHasConflicts
);
1838 void CMainFrame::OnMoving(UINT fwSide
, LPRECT pRect
)
1840 // if the pathfilelist dialog is attached to the mainframe,
1841 // move it along with the mainframe
1842 if (::IsWindow(m_dlgFilePatches
.m_hWnd
))
1845 m_dlgFilePatches
.GetWindowRect(&patchrect
);
1846 if (::IsWindow(m_hWnd
))
1849 GetWindowRect(&thisrect
);
1850 if (patchrect
.right
== thisrect
.left
)
1852 m_dlgFilePatches
.SetWindowPos(NULL
, patchrect
.left
- (thisrect
.left
- pRect
->left
), patchrect
.top
- (thisrect
.top
- pRect
->top
),
1853 0, 0, SWP_NOACTIVATE
| SWP_NOOWNERZORDER
| SWP_NOSIZE
| SWP_NOZORDER
);
1857 __super::OnMoving(fwSide
, pRect
);
1860 void CMainFrame::OnUpdateEditCopy(CCmdUI
*pCmdUI
)
1863 if ((m_pwndBottomView
)&&(m_pwndBottomView
->HasSelection()))
1865 if ((m_pwndRightView
)&&(m_pwndRightView
->HasSelection()))
1867 if ((m_pwndLeftView
)&&(m_pwndLeftView
->HasSelection()))
1869 pCmdUI
->Enable(bShow
);
1872 void CMainFrame::OnViewSwitchleft()
1875 if (((m_pwndBottomView
)&&(m_pwndBottomView
->IsModified())) ||
1876 ((m_pwndRightView
)&&(m_pwndRightView
->IsModified())))
1879 sTemp
.LoadString(IDS_ASKFORSAVE
);
1880 ret
= MessageBox(sTemp
, 0, MB_YESNOCANCEL
| MB_ICONQUESTION
);
1887 if ((ret
== IDNO
)||(ret
== IDYES
))
1889 CWorkingFile file
= m_Data
.m_baseFile
;
1890 m_Data
.m_baseFile
= m_Data
.m_yourFile
;
1891 m_Data
.m_yourFile
= file
;
1892 if (m_Data
.m_mergedFile
.GetFilename().CompareNoCase(m_Data
.m_yourFile
.GetFilename())==0)
1894 m_Data
.m_mergedFile
= m_Data
.m_baseFile
;
1896 else if (m_Data
.m_mergedFile
.GetFilename().CompareNoCase(m_Data
.m_baseFile
.GetFilename())==0)
1898 m_Data
.m_mergedFile
= m_Data
.m_yourFile
;
1904 void CMainFrame::OnUpdateViewSwitchleft(CCmdUI
*pCmdUI
)
1906 BOOL bEnable
= TRUE
;
1907 if (m_pwndBottomView
)
1909 if (m_pwndBottomView
->IsWindowVisible())
1912 pCmdUI
->Enable(bEnable
);
1916 void CMainFrame::OnUpdateViewShowfilelist(CCmdUI
*pCmdUI
)
1918 if (m_dlgFilePatches
.HasFiles())
1920 pCmdUI
->Enable(true);
1923 pCmdUI
->Enable(false);
1924 pCmdUI
->SetCheck(m_dlgFilePatches
.IsWindowVisible());
1927 void CMainFrame::OnViewShowfilelist()
1929 m_dlgFilePatches
.ShowWindow(m_dlgFilePatches
.IsWindowVisible() ? SW_HIDE
: SW_SHOW
);
1932 void CMainFrame::OnEditUndo()
1934 if (CUndo::GetInstance().CanUndo())
1936 CUndo::GetInstance().Undo(m_pwndLeftView
, m_pwndRightView
, m_pwndBottomView
);
1941 void CMainFrame::OnUpdateEditUndo(CCmdUI
*pCmdUI
)
1943 pCmdUI
->Enable(CUndo::GetInstance().CanUndo());
1946 int CMainFrame::CheckForSave()
1949 if (((m_pwndBottomView
)&&(m_pwndBottomView
->IsModified())) ||
1950 ((m_pwndRightView
)&&(m_pwndRightView
->IsModified())))
1953 sTemp
.LoadString(IDS_WARNMODIFIEDLOOSECHANGES
);
1954 ret
= MessageBox(sTemp
, 0, MB_YESNOCANCEL
| MB_ICONQUESTION
);
1964 void CMainFrame::OnViewInlinediffword()
1966 m_bInlineWordDiff
= !m_bInlineWordDiff
;
1969 m_pwndLeftView
->SetInlineWordDiff(m_bInlineWordDiff
);
1970 m_pwndLeftView
->Invalidate();
1972 if (m_pwndRightView
)
1974 m_pwndRightView
->SetInlineWordDiff(m_bInlineWordDiff
);
1975 m_pwndRightView
->Invalidate();
1977 if (m_pwndBottomView
)
1979 m_pwndBottomView
->SetInlineWordDiff(m_bInlineWordDiff
);
1980 m_pwndBottomView
->Invalidate();
1982 m_wndLineDiffBar
.Invalidate();
1985 void CMainFrame::OnUpdateViewInlinediffword(CCmdUI
*pCmdUI
)
1987 pCmdUI
->Enable(m_pwndLeftView
&& m_pwndLeftView
->IsWindowVisible() &&
1988 m_pwndRightView
&& m_pwndRightView
->IsWindowVisible());
1989 pCmdUI
->SetCheck(m_bInlineWordDiff
);
1992 void CMainFrame::OnUpdateEditCreateunifieddifffile(CCmdUI
*pCmdUI
)
1994 // "create unified diff file" is only available if two files
1995 // are diffed, not three.
1996 bool bEnabled
= true;
1997 if ((m_pwndLeftView
== NULL
)||(!m_pwndLeftView
->IsWindowVisible()))
1999 if ((m_pwndRightView
== NULL
)||(!m_pwndRightView
->IsWindowVisible()))
2001 if ((m_pwndBottomView
)&&(m_pwndBottomView
->IsWindowVisible()))
2003 pCmdUI
->Enable(bEnabled
);
2006 void CMainFrame::OnEditCreateunifieddifffile()
2008 CString origFile
, modifiedFile
, outputFile
;
2009 // the original file is the one on the left
2011 origFile
= m_pwndLeftView
->m_sFullFilePath
;
2012 if (m_pwndRightView
)
2013 modifiedFile
= m_pwndRightView
->m_sFullFilePath
;
2014 if (!origFile
.IsEmpty() && !modifiedFile
.IsEmpty())
2016 // ask for the path to save the unified diff file to
2017 OPENFILENAME ofn
= {0}; // common dialog box structure
2018 TCHAR szFile
[MAX_PATH
] = {0}; // buffer for file name
2019 ofn
.lStructSize
= sizeof(OPENFILENAME
);
2020 ofn
.lpstrFile
= szFile
;
2021 ofn
.nMaxFile
= sizeof(szFile
)/sizeof(TCHAR
);
2023 temp
.LoadString(IDS_SAVEASTITLE
);
2024 if (!temp
.IsEmpty())
2025 ofn
.lpstrTitle
= temp
;
2026 ofn
.Flags
= OFN_OVERWRITEPROMPT
;
2028 sFilter
.LoadString(IDS_COMMONFILEFILTER
);
2029 TCHAR
* pszFilters
= new TCHAR
[sFilter
.GetLength()+4];
2030 _tcscpy_s (pszFilters
, sFilter
.GetLength()+4, sFilter
);
2031 // Replace '|' delimiters with '\0's
2032 TCHAR
*ptr
= pszFilters
+ _tcslen(pszFilters
); //set ptr at the NULL
2033 while (ptr
!= pszFilters
)
2039 ofn
.lpstrFilter
= pszFilters
;
2040 ofn
.nFilterIndex
= 1;
2042 // Display the Save dialog box.
2044 if (GetSaveFileName(&ofn
)==TRUE
)
2046 outputFile
= CString(ofn
.lpstrFile
);
2047 CAppUtils::CreateUnifiedDiff(origFile
, modifiedFile
, outputFile
, true);
2049 delete [] pszFilters
;
2053 void CMainFrame::OnUpdateViewLinediffbar(CCmdUI
*pCmdUI
)
2055 pCmdUI
->SetCheck(m_bLineDiff
);
2059 void CMainFrame::OnViewLinediffbar()
2061 m_bLineDiff
= !m_bLineDiff
;
2062 m_wndLineDiffBar
.ShowPane(m_bLineDiff
, false, true);
2063 m_wndLineDiffBar
.DocumentUpdated();
2064 m_wndLocatorBar
.ShowPane(m_bLocatorBar
, false, true);
2065 m_wndLocatorBar
.DocumentUpdated();
2068 void CMainFrame::OnUpdateViewLocatorbar(CCmdUI
*pCmdUI
)
2070 pCmdUI
->SetCheck(m_bLocatorBar
);
2074 void CMainFrame::OnViewLocatorbar()
2076 m_bLocatorBar
= !m_bLocatorBar
;
2077 m_wndLocatorBar
.ShowPane(m_bLocatorBar
, false, true);
2078 m_wndLocatorBar
.DocumentUpdated();
2079 m_wndLineDiffBar
.ShowPane(m_bLineDiff
, false, true);
2080 m_wndLineDiffBar
.DocumentUpdated();