1 // TortoiseMerge - a Diff/Patch program
3 // Copyright (C) 2008-2012 - TortoiseGit
4 // Copyright (C) 2004-2009 - TortoiseSVN
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include "TortoiseMerge.h"
24 #include "SysProgressDlg.h"
26 #include "MessageBox.h"
28 #include "PathUtils.h"
31 #include "RightView.h"
32 #include "BottomView.h"
33 #include "DiffColors.h"
34 #include ".\mainfrm.h"
35 #include "FormatMessageWrapper.h"
43 const UINT
CMainFrame::m_FindDialogMessage
= RegisterWindowMessage(FINDMSGSTRING
);
45 IMPLEMENT_DYNCREATE(CMainFrame
, CFrameWndEx
)
47 BEGIN_MESSAGE_MAP(CMainFrame
, CFrameWndEx
)
49 ON_COMMAND_RANGE(ID_VIEW_APPLOOK_WIN_2000
, ID_VIEW_APPLOOK_OFF_2007_AQUA
, &CMainFrame::OnApplicationLook
)
50 ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_APPLOOK_WIN_2000
, ID_VIEW_APPLOOK_OFF_2007_AQUA
, &CMainFrame::OnUpdateApplicationLook
)
51 // Global help commands
52 ON_COMMAND(ID_HELP_FINDER
, CFrameWndEx::OnHelpFinder
)
53 ON_COMMAND(ID_HELP
, CFrameWndEx::OnHelp
)
54 ON_COMMAND(ID_CONTEXT_HELP
, CFrameWndEx::OnContextHelp
)
55 ON_COMMAND(ID_DEFAULT_HELP
, CFrameWndEx::OnHelpFinder
)
56 ON_COMMAND(ID_FILE_OPEN
, OnFileOpen
)
57 ON_COMMAND(ID_VIEW_WHITESPACES
, OnViewWhitespaces
)
59 ON_COMMAND(ID_FILE_SAVE
, OnFileSave
)
60 ON_COMMAND(ID_FILE_SAVE_AS
, OnFileSaveAs
)
61 ON_UPDATE_COMMAND_UI(ID_FILE_SAVE
, OnUpdateFileSave
)
62 ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_AS
, OnUpdateFileSaveAs
)
63 ON_COMMAND(ID_VIEW_ONEWAYDIFF
, OnViewOnewaydiff
)
64 ON_UPDATE_COMMAND_UI(ID_VIEW_ONEWAYDIFF
, OnUpdateViewOnewaydiff
)
65 ON_UPDATE_COMMAND_UI(ID_VIEW_WHITESPACES
, OnUpdateViewWhitespaces
)
66 ON_COMMAND(ID_VIEW_OPTIONS
, OnViewOptions
)
68 ON_COMMAND(ID_EDIT_FIND
, OnEditFind
)
69 ON_REGISTERED_MESSAGE(m_FindDialogMessage
, OnFindDialogMessage
)
70 ON_COMMAND(ID_EDIT_FINDNEXT
, OnEditFindnext
)
71 ON_COMMAND(ID_EDIT_FINDPREV
, OnEditFindprev
)
72 ON_COMMAND(ID_FILE_RELOAD
, OnFileReload
)
73 ON_COMMAND(ID_VIEW_LINEDOWN
, OnViewLinedown
)
74 ON_COMMAND(ID_VIEW_LINEUP
, OnViewLineup
)
75 ON_UPDATE_COMMAND_UI(ID_EDIT_MARKASRESOLVED
, OnUpdateMergeMarkasresolved
)
76 ON_COMMAND(ID_EDIT_MARKASRESOLVED
, OnMergeMarkasresolved
)
77 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_NEXTCONFLICT
, OnUpdateMergeNextconflict
)
78 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_PREVIOUSCONFLICT
, OnUpdateMergePreviousconflict
)
81 ON_UPDATE_COMMAND_UI(ID_EDIT_COPY
, OnUpdateEditCopy
)
82 ON_COMMAND(ID_VIEW_SWITCHLEFT
, OnViewSwitchleft
)
83 ON_UPDATE_COMMAND_UI(ID_VIEW_SWITCHLEFT
, OnUpdateViewSwitchleft
)
84 ON_COMMAND(ID_VIEW_LINELEFT
, &CMainFrame::OnViewLineleft
)
85 ON_COMMAND(ID_VIEW_LINERIGHT
, &CMainFrame::OnViewLineright
)
86 ON_UPDATE_COMMAND_UI(ID_VIEW_SHOWFILELIST
, &CMainFrame::OnUpdateViewShowfilelist
)
87 ON_COMMAND(ID_VIEW_SHOWFILELIST
, &CMainFrame::OnViewShowfilelist
)
88 ON_COMMAND(ID_EDIT_USETHEIRBLOCK
, &CMainFrame::OnEditUseTheirs
)
89 ON_COMMAND(ID_EDIT_USEMYBLOCK
, &CMainFrame::OnEditUseMine
)
90 ON_COMMAND(ID_EDIT_USETHEIRTHENMYBLOCK
, &CMainFrame::OnEditUseTheirsThenMine
)
91 ON_COMMAND(ID_EDIT_USEMINETHENTHEIRBLOCK
, &CMainFrame::OnEditUseMineThenTheirs
)
92 ON_COMMAND(ID_EDIT_UNDO
, &CMainFrame::OnEditUndo
)
93 ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO
, &CMainFrame::OnUpdateEditUndo
)
94 ON_UPDATE_COMMAND_UI(ID_EDIT_USEMINETHENTHEIRBLOCK
, &CMainFrame::OnUpdateEditUseminethentheirblock
)
95 ON_UPDATE_COMMAND_UI(ID_EDIT_USEMYBLOCK
, &CMainFrame::OnUpdateEditUsemyblock
)
96 ON_UPDATE_COMMAND_UI(ID_EDIT_USETHEIRBLOCK
, &CMainFrame::OnUpdateEditUsetheirblock
)
97 ON_UPDATE_COMMAND_UI(ID_EDIT_USETHEIRTHENMYBLOCK
, &CMainFrame::OnUpdateEditUsetheirthenmyblock
)
98 ON_COMMAND(ID_VIEW_INLINEDIFFWORD
, &CMainFrame::OnViewInlinediffword
)
99 ON_UPDATE_COMMAND_UI(ID_VIEW_INLINEDIFFWORD
, &CMainFrame::OnUpdateViewInlinediffword
)
100 ON_UPDATE_COMMAND_UI(ID_EDIT_CREATEUNIFIEDDIFFFILE
, &CMainFrame::OnUpdateEditCreateunifieddifffile
)
101 ON_COMMAND(ID_EDIT_CREATEUNIFIEDDIFFFILE
, &CMainFrame::OnEditCreateunifieddifffile
)
102 ON_UPDATE_COMMAND_UI(ID_VIEW_LINEDIFFBAR
, &CMainFrame::OnUpdateViewLinediffbar
)
103 ON_COMMAND(ID_VIEW_LINEDIFFBAR
, &CMainFrame::OnViewLinediffbar
)
104 ON_UPDATE_COMMAND_UI(ID_VIEW_LOCATORBAR
, &CMainFrame::OnUpdateViewLocatorbar
)
105 ON_COMMAND(ID_VIEW_LOCATORBAR
, &CMainFrame::OnViewLocatorbar
)
106 ON_COMMAND(ID_EDIT_USELEFTBLOCK
, &CMainFrame::OnEditUseleftblock
)
107 ON_UPDATE_COMMAND_UI(ID_EDIT_USELEFTBLOCK
, &CMainFrame::OnUpdateEditUseleftblock
)
108 ON_COMMAND(ID_EDIT_USELEFTFILE
, &CMainFrame::OnEditUseleftfile
)
109 ON_UPDATE_COMMAND_UI(ID_EDIT_USELEFTFILE
, &CMainFrame::OnUpdateEditUseleftfile
)
110 ON_COMMAND(ID_EDIT_USEBLOCKFROMLEFTBEFORERIGHT
, &CMainFrame::OnEditUseblockfromleftbeforeright
)
111 ON_UPDATE_COMMAND_UI(ID_EDIT_USEBLOCKFROMLEFTBEFORERIGHT
, &CMainFrame::OnUpdateEditUseblockfromleftbeforeright
)
112 ON_COMMAND(ID_EDIT_USEBLOCKFROMRIGHTBEFORELEFT
, &CMainFrame::OnEditUseblockfromrightbeforeleft
)
113 ON_UPDATE_COMMAND_UI(ID_EDIT_USEBLOCKFROMRIGHTBEFORELEFT
, &CMainFrame::OnUpdateEditUseblockfromrightbeforeleft
)
116 static UINT indicators
[] =
118 ID_SEPARATOR
, // status line indicator
119 ID_INDICATOR_LEFTVIEW
,
120 ID_INDICATOR_RIGHTVIEW
,
121 ID_INDICATOR_BOTTOMVIEW
,
128 // CMainFrame construction/destruction
130 CMainFrame::CMainFrame()
131 : m_pFindDialog(NULL
)
133 , m_bInitSplitter(FALSE
)
134 , m_bReversedPatch(FALSE
)
135 , m_bHasConflicts(false)
136 , m_bInlineWordDiff(true)
138 , m_bLocatorBar(true)
139 , m_nMoveMovesToIgnore(0)
140 , m_bLimitToDiff(false)
141 , m_bWholeWord(false)
142 , m_pwndLeftView(NULL
)
143 , m_pwndRightView(NULL
)
144 , m_pwndBottomView(NULL
)
148 m_bOneWay
= (0 != ((DWORD
)CRegDWORD(_T("Software\\TortoiseMerge\\OnePane"))));
149 theApp
.m_nAppLook
= theApp
.GetInt(_T("ApplicationLook"), ID_VIEW_APPLOOK_VS_2005
);
152 CMainFrame::~CMainFrame()
156 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct
)
158 if (CFrameWndEx::OnCreate(lpCreateStruct
) == -1)
161 OnApplicationLook(theApp
.m_nAppLook
);
163 if (!m_wndMenuBar
.Create(this))
165 TRACE0("Failed to create menubar\n");
166 return -1; // fail to create
169 m_wndMenuBar
.SetPaneStyle(m_wndMenuBar
.GetPaneStyle() | CBRS_SIZE_DYNAMIC
| CBRS_TOOLTIPS
| CBRS_FLYBY
);
171 // prevent the menu bar from taking the focus on activation
172 CMFCPopupMenu::SetForceMenuFocus(FALSE
);
174 if (!m_wndToolBar
.CreateEx(this, TBSTYLE_FLAT
, WS_CHILD
| WS_VISIBLE
| CBRS_ALIGN_TOP
| CBRS_GRIPPER
| CBRS_TOOLTIPS
| CBRS_FLYBY
) ||
175 !m_wndToolBar
.LoadToolBar(IDR_MAINFRAME
))
177 TRACE0("Failed to create toolbar\n");
178 return -1; // fail to create
180 m_wndToolBar
.SetWindowText(_T("Main"));
182 if (!m_wndStatusBar
.Create(this) ||
183 !m_wndStatusBar
.SetIndicators(indicators
,
184 _countof(indicators
)))
186 TRACE0("Failed to create status bar\n");
187 return -1; // fail to create
190 if (!m_wndLocatorBar
.Create(this, IDD_DIFFLOCATOR
,
191 CBRS_ALIGN_LEFT
| CBRS_SIZE_FIXED
, ID_VIEW_LOCATORBAR
))
193 TRACE0("Failed to create dialogbar\n");
194 return -1; // fail to create
196 if (!m_wndLineDiffBar
.Create(this, IDD_LINEDIFF
,
197 CBRS_ALIGN_BOTTOM
| CBRS_SIZE_FIXED
, ID_VIEW_LINEDIFFBAR
))
199 TRACE0("Failed to create dialogbar\n");
200 return -1; // fail to create
202 m_wndLocatorBar
.m_pMainFrm
= this;
203 m_wndLineDiffBar
.m_pMainFrm
= this;
205 EnableDocking(CBRS_ALIGN_ANY
);
206 m_wndMenuBar
.EnableDocking(CBRS_ALIGN_TOP
);
207 m_wndToolBar
.EnableDocking(CBRS_ALIGN_TOP
);
208 DockPane(&m_wndMenuBar
);
209 DockPane(&m_wndToolBar
);
210 DockPane(&m_wndLocatorBar
);
211 DockPane(&m_wndLineDiffBar
);
212 ShowPane(&m_wndLocatorBar
, true, false, true);
213 ShowPane(&m_wndLineDiffBar
, true, false, true);
215 m_wndLocatorBar
.EnableGripper(FALSE
);
216 m_wndLineDiffBar
.EnableGripper(FALSE
);
221 BOOL
CMainFrame::PreCreateWindow(CREATESTRUCT
& cs
)
223 if( !CFrameWndEx::PreCreateWindow(cs
) )
228 void CMainFrame::OnApplicationLook(UINT id
)
232 theApp
.m_nAppLook
= id
;
234 switch (theApp
.m_nAppLook
)
236 case ID_VIEW_APPLOOK_WIN_2000
:
237 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManager
));
240 case ID_VIEW_APPLOOK_OFF_XP
:
241 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOfficeXP
));
244 case ID_VIEW_APPLOOK_WIN_XP
:
245 CMFCVisualManagerWindows::m_b3DTabsXPTheme
= TRUE
;
246 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows
));
249 case ID_VIEW_APPLOOK_OFF_2003
:
250 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2003
));
251 CDockingManager::SetDockingMode(DT_SMART
);
254 case ID_VIEW_APPLOOK_VS_2005
:
255 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerVS2005
));
256 CDockingManager::SetDockingMode(DT_SMART
);
260 switch (theApp
.m_nAppLook
)
262 case ID_VIEW_APPLOOK_OFF_2007_BLUE
:
263 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_LunaBlue
);
266 case ID_VIEW_APPLOOK_OFF_2007_BLACK
:
267 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_ObsidianBlack
);
270 case ID_VIEW_APPLOOK_OFF_2007_SILVER
:
271 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_Silver
);
274 case ID_VIEW_APPLOOK_OFF_2007_AQUA
:
275 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_Aqua
);
279 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2007
));
280 CDockingManager::SetDockingMode(DT_SMART
);
283 RedrawWindow(NULL
, NULL
, RDW_ALLCHILDREN
| RDW_INVALIDATE
| RDW_UPDATENOW
| RDW_FRAME
| RDW_ERASE
);
285 theApp
.WriteInt(_T("ApplicationLook"), theApp
.m_nAppLook
);
288 void CMainFrame::OnUpdateApplicationLook(CCmdUI
* pCmdUI
)
290 pCmdUI
->SetRadio(theApp
.m_nAppLook
== pCmdUI
->m_nID
);
294 // CMainFrame diagnostics
297 void CMainFrame::AssertValid() const
299 CFrameWndEx::AssertValid();
302 void CMainFrame::Dump(CDumpContext
& dc
) const
304 CFrameWndEx::Dump(dc
);
310 // CMainFrame message handlers
313 BOOL
CMainFrame::OnCreateClient(LPCREATESTRUCT
/*lpcs*/, CCreateContext
* pContext
)
319 // split into three panes:
328 // create a splitter with 2 rows, 1 column
329 if (!m_wndSplitter
.CreateStatic(this, 2, 1))
331 TRACE0("Failed to CreateStaticSplitter\n");
335 // add the second splitter pane - which is a nested splitter with 2 columns
336 if (!m_wndSplitter2
.CreateStatic(
337 &m_wndSplitter
, // our parent window is the first splitter
338 1, 2, // the new splitter is 1 row, 2 columns
339 WS_CHILD
| WS_VISIBLE
| WS_BORDER
, // style, WS_BORDER is needed
340 m_wndSplitter
.IdFromRowCol(0, 0)
341 // new splitter is in the first row, 1st column of first splitter
344 TRACE0("Failed to create nested splitter\n");
347 // add the first splitter pane - the default view in row 0
348 if (!m_wndSplitter
.CreateView(1, 0,
349 RUNTIME_CLASS(CBottomView
), CSize(cr
.Width(), cr
.Height()), pContext
))
351 TRACE0("Failed to create first pane\n");
354 m_pwndBottomView
= (CBottomView
*)m_wndSplitter
.GetPane(1,0);
355 m_pwndBottomView
->m_pwndLocator
= &m_wndLocatorBar
;
356 m_pwndBottomView
->m_pwndLineDiffBar
= &m_wndLineDiffBar
;
357 m_pwndBottomView
->m_pwndStatusBar
= &m_wndStatusBar
;
358 m_pwndBottomView
->m_pMainFrame
= this;
360 // now create the two views inside the nested splitter
362 if (!m_wndSplitter2
.CreateView(0, 0,
363 RUNTIME_CLASS(CLeftView
), CSize(cr
.Width()/2, cr
.Height()/2), pContext
))
365 TRACE0("Failed to create second pane\n");
368 m_pwndLeftView
= (CLeftView
*)m_wndSplitter2
.GetPane(0,0);
369 m_pwndLeftView
->m_pwndLocator
= &m_wndLocatorBar
;
370 m_pwndLeftView
->m_pwndLineDiffBar
= &m_wndLineDiffBar
;
371 m_pwndLeftView
->m_pwndStatusBar
= &m_wndStatusBar
;
372 m_pwndLeftView
->m_pMainFrame
= this;
374 if (!m_wndSplitter2
.CreateView(0, 1,
375 RUNTIME_CLASS(CRightView
), CSize(cr
.Width()/2, cr
.Height()/2), pContext
))
377 TRACE0("Failed to create third pane\n");
380 m_pwndRightView
= (CRightView
*)m_wndSplitter2
.GetPane(0,1);
381 m_pwndRightView
->m_pwndLocator
= &m_wndLocatorBar
;
382 m_pwndRightView
->m_pwndLineDiffBar
= &m_wndLineDiffBar
;
383 m_pwndRightView
->m_pwndStatusBar
= &m_wndStatusBar
;
384 m_pwndRightView
->m_pMainFrame
= this;
385 m_bInitSplitter
= TRUE
;
387 m_dlgFilePatches
.Create(IDD_FILEPATCHES
, this);
393 BOOL
CMainFrame::PatchFile(CString sFilePath
, CString sVersion
, BOOL bAutoPatch
,BOOL bIsReview
,CString
*Path2
)
395 //first, do a "dry run" of patching...
396 if (!m_Patch
.PatchFile(sFilePath
))
398 //patching not successful, so retrieve the
399 //base file from version control and try
402 CSysProgressDlg progDlg
;
403 sTemp
.Format(IDS_GETVERSIONOFFILE
, (LPCTSTR
)sVersion
);
404 progDlg
.SetLine(1, sTemp
, true);
405 progDlg
.SetLine(2, sFilePath
, true);
406 sTemp
.LoadString(IDS_GETVERSIONOFFILETITLE
);
407 progDlg
.SetTitle(sTemp
);
408 progDlg
.SetShowProgressBar(false);
409 progDlg
.SetAnimation(IDR_DOWNLOAD
);
410 progDlg
.SetTime(FALSE
);
412 if(!m_Patch
.m_IsGitPatch
)
413 progDlg
.ShowModeless(this);
415 CString sBaseFile
= m_TempFiles
.GetTempFilePath();
416 if (!CAppUtils::GetVersionedFile(sFilePath
, sVersion
, sBaseFile
, &progDlg
, m_hWnd
))
420 sErrMsg
.Format(IDS_ERR_MAINFRAME_FILEVERSIONNOTFOUND
, (LPCTSTR
)sVersion
, (LPCTSTR
)sFilePath
);
421 MessageBox(sErrMsg
, NULL
, MB_ICONERROR
);
425 CString sTempFile
= m_TempFiles
.GetTempFilePath();
426 if (!m_Patch
.PatchFile(sFilePath
, sTempFile
, sBaseFile
))
428 MessageBox(m_Patch
.GetErrorMessage(), NULL
, MB_ICONERROR
);
436 temp
.Format(_T("%s Revision %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sFilePath
), (LPCTSTR
)sVersion
);
437 m_Data
.m_baseFile
.SetFileName(sBaseFile
);
438 m_Data
.m_baseFile
.SetDescriptiveName(temp
);
440 temp
.Format(_T("%s %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(*Path2
), (LPCTSTR
)m_Data
.m_sPatchPatched
);
442 temp
.Format(_T("%s %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sFilePath
), (LPCTSTR
)m_Data
.m_sPatchPatched
);
443 m_Data
.m_yourFile
.SetFileName(sTempFile
);
444 m_Data
.m_yourFile
.SetDescriptiveName(temp
);
445 m_Data
.m_theirFile
.SetOutOfUse();
446 m_Data
.m_mergedFile
.SetOutOfUse();
451 temp
.Format(_T("%s Revision %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sFilePath
), (LPCTSTR
)sVersion
);
452 m_Data
.m_baseFile
.SetFileName(sBaseFile
);
453 m_Data
.m_baseFile
.SetDescriptiveName(temp
);
455 temp
.Format(_T("%s %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(*Path2
), (LPCTSTR
)m_Data
.m_sPatchPatched
);
457 temp
.Format(_T("%s %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sFilePath
), (LPCTSTR
)m_Data
.m_sPatchPatched
);
458 m_Data
.m_theirFile
.SetFileName(sTempFile
);
459 m_Data
.m_theirFile
.SetDescriptiveName(temp
);
460 m_Data
.m_yourFile
.SetFileName(sFilePath
);
461 m_Data
.m_yourFile
.SetDescriptiveName(CPathUtils::GetFileNameFromPath(sFilePath
));
462 m_Data
.m_mergedFile
.SetFileName(sFilePath
);
463 m_Data
.m_mergedFile
.SetDescriptiveName(CPathUtils::GetFileNameFromPath(sFilePath
));
465 TRACE(_T("comparing %s and %s\nagainst the base file %s\n"), (LPCTSTR
)sTempFile
, (LPCTSTR
)sFilePath
, (LPCTSTR
)sBaseFile
);
471 //"dry run" was successful, so save the patched file somewhere...
472 CString sTempFile
= m_TempFiles
.GetTempFilePath();
473 if (!m_Patch
.PatchFile(sFilePath
, sTempFile
))
475 MessageBox(m_Patch
.GetErrorMessage(), NULL
, MB_ICONERROR
);
478 if (m_bReversedPatch
)
480 m_Data
.m_baseFile
.SetFileName(sTempFile
);
482 temp
.Format(_T("%s %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sFilePath
), (LPCTSTR
)m_Data
.m_sPatchPatched
);
483 m_Data
.m_baseFile
.SetDescriptiveName(temp
);
484 m_Data
.m_yourFile
.SetFileName(sFilePath
);
485 temp
.Format(_T("%s %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sFilePath
), (LPCTSTR
)m_Data
.m_sPatchOriginal
);
486 m_Data
.m_yourFile
.SetDescriptiveName(temp
);
487 m_Data
.m_theirFile
.SetOutOfUse();
488 m_Data
.m_mergedFile
.SetOutOfUse();
492 if (!PathFileExists(sFilePath
))
494 m_Data
.m_baseFile
.SetFileName(m_TempFiles
.GetTempFilePath());
495 m_Data
.m_baseFile
.CreateEmptyFile();
499 m_Data
.m_baseFile
.SetFileName(sFilePath
);
501 CString sDescription
;
502 sDescription
.Format(_T("%s %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sFilePath
), (LPCTSTR
)m_Data
.m_sPatchOriginal
);
503 m_Data
.m_baseFile
.SetDescriptiveName(sDescription
);
504 m_Data
.m_yourFile
.SetFileName(sTempFile
);
508 temp
.Format(_T("%s %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(*Path2
), (LPCTSTR
)m_Data
.m_sPatchPatched
);
511 temp
.Format(_T("%s %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sFilePath
), (LPCTSTR
)m_Data
.m_sPatchPatched
);
513 m_Data
.m_yourFile
.SetDescriptiveName(temp
);
514 m_Data
.m_theirFile
.SetOutOfUse();
515 m_Data
.m_mergedFile
.SetFileName(sFilePath
);
517 TRACE(_T("comparing %s\nwith the patched result %s\n"), (LPCTSTR
)sFilePath
, (LPCTSTR
)sTempFile
);
528 BOOL
CMainFrame::DiffFiles(CString sURL1
, CString sRev1
, CString sURL2
, CString sRev2
)
530 CString tempfile1
= m_TempFiles
.GetTempFilePath();
531 CString tempfile2
= m_TempFiles
.GetTempFilePath();
533 ASSERT(tempfile1
.Compare(tempfile2
));
536 CSysProgressDlg progDlg
;
537 sTemp
.Format(IDS_GETVERSIONOFFILE
, (LPCTSTR
)sRev1
);
538 progDlg
.SetLine(1, sTemp
, true);
539 progDlg
.SetLine(2, sURL1
, true);
540 sTemp
.LoadString(IDS_GETVERSIONOFFILETITLE
);
541 progDlg
.SetTitle(sTemp
);
542 progDlg
.SetShowProgressBar(true);
543 progDlg
.SetAnimation(IDR_DOWNLOAD
);
544 progDlg
.SetTime(FALSE
);
545 progDlg
.SetProgress(1,100);
546 progDlg
.ShowModeless(this);
547 if (!CAppUtils::GetVersionedFile(sURL1
, sRev1
, tempfile1
, &progDlg
, m_hWnd
))
551 sErrMsg
.Format(IDS_ERR_MAINFRAME_FILEVERSIONNOTFOUND
, (LPCTSTR
)sRev1
, (LPCTSTR
)sURL1
);
552 MessageBox(sErrMsg
, NULL
, MB_ICONERROR
);
555 sTemp
.Format(IDS_GETVERSIONOFFILE
, (LPCTSTR
)sRev2
);
556 progDlg
.SetLine(1, sTemp
, true);
557 progDlg
.SetLine(2, sURL2
, true);
558 progDlg
.SetProgress(50, 100);
559 if (!CAppUtils::GetVersionedFile(sURL2
, sRev2
, tempfile2
, &progDlg
, m_hWnd
))
563 sErrMsg
.Format(IDS_ERR_MAINFRAME_FILEVERSIONNOTFOUND
, (LPCTSTR
)sRev2
, (LPCTSTR
)sURL2
);
564 MessageBox(sErrMsg
, NULL
, MB_ICONERROR
);
567 progDlg
.SetProgress(100,100);
570 temp
.Format(_T("%s Revision %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sURL1
), (LPCTSTR
)sRev1
);
571 m_Data
.m_baseFile
.SetFileName(tempfile1
);
572 m_Data
.m_baseFile
.SetDescriptiveName(temp
);
573 temp
.Format(_T("%s Revision %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sURL2
), (LPCTSTR
)sRev2
);
574 m_Data
.m_yourFile
.SetFileName(tempfile2
);
575 m_Data
.m_yourFile
.SetDescriptiveName(temp
);
582 void CMainFrame::OnFileOpen()
584 if (CheckForSave()==IDCANCEL
)
587 if (dlg
.DoModal()!=IDOK
)
591 m_dlgFilePatches
.ShowWindow(SW_HIDE
);
592 m_dlgFilePatches
.Init(NULL
, NULL
, CString(), NULL
);
593 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
,
594 (LPCTSTR
)dlg
.m_sUnifiedDiffFile
, (LPCTSTR
)dlg
.m_sPatchDirectory
);
595 m_Data
.m_baseFile
.SetFileName(dlg
.m_sBaseFile
);
596 m_Data
.m_theirFile
.SetFileName(dlg
.m_sTheirFile
);
597 m_Data
.m_yourFile
.SetFileName(dlg
.m_sYourFile
);
598 m_Data
.m_sDiffFile
= dlg
.m_sUnifiedDiffFile
;
599 m_Data
.m_sPatchPath
= dlg
.m_sPatchDirectory
;
600 m_Data
.m_mergedFile
.SetOutOfUse();
601 g_crasher
.AddFile((LPCSTR
)(LPCTSTR
)dlg
.m_sBaseFile
, (LPCSTR
)(LPCTSTR
)_T("Basefile"));
602 g_crasher
.AddFile((LPCSTR
)(LPCTSTR
)dlg
.m_sTheirFile
, (LPCSTR
)(LPCTSTR
)_T("Theirfile"));
603 g_crasher
.AddFile((LPCSTR
)(LPCTSTR
)dlg
.m_sYourFile
, (LPCSTR
)(LPCTSTR
)_T("Yourfile"));
604 g_crasher
.AddFile((LPCSTR
)(LPCTSTR
)dlg
.m_sUnifiedDiffFile
, (LPCSTR
)(LPCTSTR
)_T("Difffile"));
606 if (!m_Data
.IsBaseFileInUse() && m_Data
.IsTheirFileInUse() && m_Data
.IsYourFileInUse())
608 // a diff between two files means "Yours" against "Base", not "Theirs" against "Yours"
609 m_Data
.m_baseFile
.TransferDetailsFrom(m_Data
.m_theirFile
);
611 if (m_Data
.IsBaseFileInUse() && m_Data
.IsTheirFileInUse() && !m_Data
.IsYourFileInUse())
613 // a diff between two files means "Yours" against "Base", not "Theirs" against "Base"
614 m_Data
.m_yourFile
.TransferDetailsFrom(m_Data
.m_theirFile
);
620 void CMainFrame::ClearViewNamesAndPaths() {
621 m_pwndLeftView
->m_sWindowName
.Empty();
622 m_pwndLeftView
->m_sFullFilePath
.Empty();
623 m_pwndRightView
->m_sWindowName
.Empty();
624 m_pwndRightView
->m_sFullFilePath
.Empty();
625 m_pwndBottomView
->m_sWindowName
.Empty();
626 m_pwndBottomView
->m_sFullFilePath
.Empty();
629 bool CMainFrame::LoadViews(bool bRetainPosition
)
631 m_Data
.SetBlame(m_bBlame
);
632 m_bHasConflicts
= false;
633 CBaseView
* pwndActiveView
= m_pwndLeftView
;
634 int nOldLine
= m_pwndLeftView
? m_pwndLeftView
->m_nTopLine
: -1;
636 m_pwndLeftView
&& m_pwndLeftView
->m_pViewData
?
637 m_pwndLeftView
->m_pViewData
->GetLineNumber(m_pwndLeftView
->m_nTopLine
) : -1;
640 ::MessageBox(NULL
, m_Data
.GetError(), _T("TortoiseMerge"), MB_ICONERROR
);
641 m_Data
.m_mergedFile
.SetOutOfUse();
645 m_pwndRightView
->UseCaret(false);
646 m_pwndBottomView
->UseCaret(false);
648 if (!m_Data
.IsBaseFileInUse())
650 if (m_Data
.IsYourFileInUse() && m_Data
.IsTheirFileInUse())
652 m_Data
.m_baseFile
.TransferDetailsFrom(m_Data
.m_theirFile
);
654 else if ((!m_Data
.m_sDiffFile
.IsEmpty())&&(!m_Patch
.OpenUnifiedDiffFile(m_Data
.m_sDiffFile
)))
656 ClearViewNamesAndPaths();
657 MessageBox(m_Patch
.GetErrorMessage(), NULL
, MB_ICONERROR
);
660 if (m_Patch
.GetNumberOfFiles() > 0)
662 CString firstpath
= m_Patch
.GetFilename(0);
663 CString path
=firstpath
;
664 path
.Replace('/','\\');
665 if ( !PathIsRelative(path
) && !PathFileExists(path
) )
667 // The absolute path mentioned in the patch does not exist. Lets
668 // try to find the correct relative path by stripping prefixes.
669 BOOL bFound
= m_Patch
.StripPrefixes(m_Data
.m_sPatchPath
);
670 CString strippedpath
= m_Patch
.GetFilename(0);
674 msg
.Format(IDS_WARNABSOLUTEPATHFOUND
, (LPCTSTR
)firstpath
, (LPCTSTR
)strippedpath
);
675 if (CMessageBox::Show(m_hWnd
, msg
, _T("TortoiseMerge"), MB_ICONQUESTION
| MB_YESNO
)==IDNO
)
681 msg
.Format(IDS_WARNABSOLUTEPATHNOTFOUND
, (LPCTSTR
)firstpath
);
682 CMessageBox::Show(m_hWnd
, msg
, _T("TortoiseMerge"), MB_ICONEXCLAMATION
);
686 CString betterpatchpath
= m_Patch
.CheckPatchPath(m_Data
.m_sPatchPath
);
687 if (betterpatchpath
.CompareNoCase(m_Data
.m_sPatchPath
)!=0)
690 msg
.Format(IDS_WARNBETTERPATCHPATHFOUND
, (LPCTSTR
)m_Data
.m_sPatchPath
, (LPCTSTR
)betterpatchpath
);
691 if (CMessageBox::Show(m_hWnd
, msg
, _T("TortoiseMerge"), MB_ICONQUESTION
| MB_YESNO
)==IDYES
)
692 m_Data
.m_sPatchPath
= betterpatchpath
;
694 m_dlgFilePatches
.Init(&m_Patch
, this, m_Data
.m_sPatchPath
, this);
695 m_dlgFilePatches
.ShowWindow(SW_SHOW
);
696 ClearViewNamesAndPaths();
697 if (!m_wndSplitter
.IsRowHidden(1))
698 m_wndSplitter
.HideRow(1);
699 m_pwndLeftView
->SetHidden(FALSE
);
700 m_pwndRightView
->SetHidden(FALSE
);
701 m_pwndBottomView
->SetHidden(TRUE
);
704 if (m_Data
.IsBaseFileInUse() && !m_Data
.IsYourFileInUse() && m_Data
.IsTheirFileInUse())
706 m_Data
.m_yourFile
.TransferDetailsFrom(m_Data
.m_theirFile
);
708 if (m_Data
.IsBaseFileInUse() && m_Data
.IsYourFileInUse() && !m_Data
.IsTheirFileInUse())
710 //diff between YOUR and BASE
711 m_pwndRightView
->UseCaret();
714 if (!m_wndSplitter2
.IsColumnHidden(1))
715 m_wndSplitter2
.HideColumn(1);
717 m_pwndLeftView
->m_pViewData
= &m_Data
.m_YourBaseBoth
;
718 m_pwndLeftView
->texttype
= m_Data
.m_arYourFile
.GetUnicodeType();
719 m_pwndLeftView
->lineendings
= m_Data
.m_arYourFile
.GetLineEndings();
720 m_pwndLeftView
->m_sWindowName
= m_Data
.m_baseFile
.GetWindowName() + _T(" - ") + m_Data
.m_yourFile
.GetWindowName();
721 m_pwndLeftView
->m_sFullFilePath
= m_Data
.m_baseFile
.GetFilename() + _T(" - ") + m_Data
.m_yourFile
.GetFilename();
723 m_pwndRightView
->m_pViewData
= NULL
;
724 m_pwndBottomView
->m_pViewData
= NULL
;
726 if (!m_wndSplitter
.IsRowHidden(1))
727 m_wndSplitter
.HideRow(1);
728 m_pwndLeftView
->SetHidden(FALSE
);
729 m_pwndRightView
->SetHidden(TRUE
);
730 m_pwndBottomView
->SetHidden(TRUE
);
731 ::SetWindowPos(m_pwndLeftView
->m_hWnd
, NULL
, 0, 0, 0, 0, SWP_FRAMECHANGED
| SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOSIZE
);
735 pwndActiveView
= m_pwndRightView
;
736 if (m_wndSplitter2
.IsColumnHidden(1))
737 m_wndSplitter2
.ShowColumn();
739 m_pwndLeftView
->m_pViewData
= &m_Data
.m_YourBaseLeft
;
740 m_pwndLeftView
->texttype
= m_Data
.m_arBaseFile
.GetUnicodeType();
741 m_pwndLeftView
->lineendings
= m_Data
.m_arBaseFile
.GetLineEndings();
742 m_pwndLeftView
->m_sWindowName
= m_Data
.m_baseFile
.GetWindowName();
743 m_pwndLeftView
->m_sFullFilePath
= m_Data
.m_baseFile
.GetFilename();
745 m_pwndRightView
->m_pViewData
= &m_Data
.m_YourBaseRight
;
746 m_pwndRightView
->texttype
= m_Data
.m_arYourFile
.GetUnicodeType();
747 m_pwndRightView
->lineendings
= m_Data
.m_arYourFile
.GetLineEndings();
748 m_pwndRightView
->m_sWindowName
= m_Data
.m_yourFile
.GetWindowName();
749 m_pwndRightView
->m_sFullFilePath
= m_Data
.m_yourFile
.GetFilename();
751 m_pwndBottomView
->m_pViewData
= NULL
;
753 if (!m_wndSplitter
.IsRowHidden(1))
754 m_wndSplitter
.HideRow(1);
755 m_pwndLeftView
->SetHidden(FALSE
);
756 m_pwndRightView
->SetHidden(FALSE
);
757 m_pwndBottomView
->SetHidden(TRUE
);
760 else if (m_Data
.IsBaseFileInUse() && m_Data
.IsYourFileInUse() && m_Data
.IsTheirFileInUse())
762 //diff between THEIR, YOUR and BASE
763 m_pwndBottomView
->UseCaret();
764 pwndActiveView
= m_pwndBottomView
;
766 m_pwndLeftView
->m_pViewData
= &m_Data
.m_TheirBaseBoth
;
767 m_pwndLeftView
->texttype
= m_Data
.m_arTheirFile
.GetUnicodeType();
768 m_pwndLeftView
->lineendings
= m_Data
.m_arTheirFile
.GetLineEndings();
769 m_pwndLeftView
->m_sWindowName
.LoadString(IDS_VIEWTITLE_THEIRS
);
770 m_pwndLeftView
->m_sWindowName
+= _T(" - ") + m_Data
.m_theirFile
.GetWindowName();
771 m_pwndLeftView
->m_sFullFilePath
= m_Data
.m_theirFile
.GetFilename();
773 m_pwndRightView
->m_pViewData
= &m_Data
.m_YourBaseBoth
;
774 m_pwndRightView
->texttype
= m_Data
.m_arYourFile
.GetUnicodeType();
775 m_pwndRightView
->lineendings
= m_Data
.m_arYourFile
.GetLineEndings();
776 m_pwndRightView
->m_sWindowName
.LoadString(IDS_VIEWTITLE_MINE
);
777 m_pwndRightView
->m_sWindowName
+= _T(" - ") + m_Data
.m_yourFile
.GetWindowName();
778 m_pwndRightView
->m_sFullFilePath
= m_Data
.m_yourFile
.GetFilename();
780 m_pwndBottomView
->m_pViewData
= &m_Data
.m_Diff3
;
781 m_pwndBottomView
->texttype
= m_Data
.m_arTheirFile
.GetUnicodeType();
782 m_pwndBottomView
->lineendings
= m_Data
.m_arTheirFile
.GetLineEndings();
783 m_pwndBottomView
->m_sWindowName
.LoadString(IDS_VIEWTITLE_MERGED
);
784 m_pwndBottomView
->m_sWindowName
+= _T(" - ") + m_Data
.m_mergedFile
.GetWindowName();
785 m_pwndBottomView
->m_sFullFilePath
= m_Data
.m_mergedFile
.GetFilename();
787 if (m_wndSplitter2
.IsColumnHidden(1))
788 m_wndSplitter2
.ShowColumn();
789 if (m_wndSplitter
.IsRowHidden(1))
790 m_wndSplitter
.ShowRow();
791 m_pwndLeftView
->SetHidden(FALSE
);
792 m_pwndRightView
->SetHidden(FALSE
);
793 m_pwndBottomView
->SetHidden(FALSE
);
794 // in three pane view, hide the line diff bar
795 m_wndLineDiffBar
.ShowPane(false, false, true);
796 m_wndLineDiffBar
.DocumentUpdated();
798 if (!m_Data
.m_mergedFile
.InUse())
800 m_Data
.m_mergedFile
.SetFileName(m_Data
.m_yourFile
.GetFilename());
802 m_pwndLeftView
->DocumentUpdated();
803 m_pwndRightView
->DocumentUpdated();
804 m_pwndBottomView
->DocumentUpdated();
805 m_wndLocatorBar
.DocumentUpdated();
806 m_wndLineDiffBar
.DocumentUpdated();
808 SetActiveView(pwndActiveView
);
810 if (bRetainPosition
&& m_pwndLeftView
->m_pViewData
)
812 int n
= nOldLineNumber
;
814 n
= m_pwndLeftView
->m_pViewData
->FindLineNumber(n
);
818 m_pwndLeftView
->ScrollAllToLine(n
);
822 m_pwndLeftView
->SetCaretPosition(p
);
826 bool bGoFirstDiff
= (0 != (DWORD
)CRegDWORD(_T("Software\\TortoiseMerge\\FirstDiffOnLoad"), TRUE
));
828 pwndActiveView
->GoToFirstDifference();
829 // Ignore the first few Mouse Move messages, so that the line diff stays on
830 // the first diff line until the user actually moves the mouse
831 m_nMoveMovesToIgnore
= 3;
835 // Avoid incorrect rendering of active pane.
836 m_pwndBottomView
->ScrollToChar(0);
837 m_pwndLeftView
->ScrollToChar(0);
838 m_pwndRightView
->ScrollToChar(0);
840 CUndo::GetInstance().Clear();
844 void CMainFrame::UpdateLayout()
850 int width
= cr
.Width();
851 if (::IsWindow(m_wndLocatorBar
) && m_wndLocatorBar
.IsWindowVisible())
853 m_wndLocatorBar
.GetWindowRect(&rclocbar
);
854 width
-= rclocbar
.Width();
856 m_wndSplitter
.SetRowInfo(0, cr
.Height()/2, 0);
857 m_wndSplitter
.SetRowInfo(1, cr
.Height()/2, 0);
858 m_wndSplitter
.SetColumnInfo(0, width
/ 2, 50);
859 m_wndSplitter2
.SetRowInfo(0, cr
.Height()/2, 0);
860 m_wndSplitter2
.SetColumnInfo(0, width
/ 2, 50);
861 m_wndSplitter2
.SetColumnInfo(1, width
/ 2, 50);
863 m_wndSplitter
.RecalcLayout();
867 void CMainFrame::OnSize(UINT nType
, int cx
, int cy
)
869 if (m_bInitSplitter
&& nType
!= SIZE_MINIMIZED
)
873 CFrameWndEx::OnSize(nType
, cx
, cy
);
876 void CMainFrame::OnViewWhitespaces()
878 CRegDWORD regViewWhitespaces
= CRegDWORD(_T("Software\\TortoiseMerge\\ViewWhitespaces"), 1);
879 BOOL bViewWhitespaces
= regViewWhitespaces
;
881 bViewWhitespaces
= m_pwndLeftView
->m_bViewWhitespace
;
883 bViewWhitespaces
= !bViewWhitespaces
;
884 regViewWhitespaces
= bViewWhitespaces
;
887 m_pwndLeftView
->m_bViewWhitespace
= bViewWhitespaces
;
888 m_pwndLeftView
->Invalidate();
892 m_pwndRightView
->m_bViewWhitespace
= bViewWhitespaces
;
893 m_pwndRightView
->Invalidate();
895 if (m_pwndBottomView
)
897 m_pwndBottomView
->m_bViewWhitespace
= bViewWhitespaces
;
898 m_pwndBottomView
->Invalidate();
902 void CMainFrame::OnUpdateViewWhitespaces(CCmdUI
*pCmdUI
)
905 pCmdUI
->SetCheck(m_pwndLeftView
->m_bViewWhitespace
);
908 void CMainFrame::OnViewOnewaydiff()
910 if (CheckForSave()==IDCANCEL
)
912 m_bOneWay
= !m_bOneWay
;
915 // in one way view, hide the line diff bar
916 m_wndLineDiffBar
.ShowPane(false, false, true);
917 m_wndLineDiffBar
.DocumentUpdated();
921 // restore the line diff bar
922 m_wndLineDiffBar
.ShowPane(m_bLineDiff
, false, true);
923 m_wndLineDiffBar
.DocumentUpdated();
924 m_wndLocatorBar
.ShowPane(m_bLocatorBar
, false, true);
925 m_wndLocatorBar
.DocumentUpdated();
930 void CMainFrame::ShowDiffBar(bool bShow
)
934 // restore the line diff bar
935 m_wndLineDiffBar
.ShowPane(m_bLineDiff
, false, true);
936 m_wndLineDiffBar
.DocumentUpdated();
937 m_wndLocatorBar
.ShowPane(m_bLocatorBar
, false, true);
938 m_wndLocatorBar
.DocumentUpdated();
942 // in one way view, hide the line diff bar
943 m_wndLineDiffBar
.ShowPane(false, false, true);
944 m_wndLineDiffBar
.DocumentUpdated();
948 int CMainFrame::CheckResolved()
950 //only in three way diffs can be conflicts!
951 m_bHasConflicts
= true;
952 if (m_pwndBottomView
->IsWindowVisible())
954 if (m_pwndBottomView
->m_pViewData
)
956 for (int i
=0; i
<m_pwndBottomView
->m_pViewData
->GetCount(); i
++)
958 if ((DIFFSTATE_CONFLICTED
== m_pwndBottomView
->m_pViewData
->GetState(i
))||
959 (DIFFSTATE_CONFLICTED_IGNORED
== m_pwndBottomView
->m_pViewData
->GetState(i
)))
964 m_bHasConflicts
= false;
968 int CMainFrame::SaveFile(const CString
& sFilePath
)
970 CViewData
* pViewData
= NULL
;
971 CFileTextLines
* pOriginFile
= &m_Data
.m_arBaseFile
;
972 if ((m_pwndBottomView
)&&(m_pwndBottomView
->IsWindowVisible()))
974 pViewData
= m_pwndBottomView
->m_pViewData
;
977 else if ((m_pwndRightView
)&&(m_pwndRightView
->IsWindowVisible()))
979 pViewData
= m_pwndRightView
->m_pViewData
;
980 if (m_Data
.IsYourFileInUse())
981 pOriginFile
= &m_Data
.m_arYourFile
;
982 else if (m_Data
.IsTheirFileInUse())
983 pOriginFile
= &m_Data
.m_arTheirFile
;
991 if ((pViewData
)&&(pOriginFile
))
994 pOriginFile
->CopySettings(&file
);
995 for (int i
=0; i
<pViewData
->GetCount(); i
++)
997 //only copy non-removed lines
998 DiffStates state
= pViewData
->GetState(i
);
1001 case DIFFSTATE_CONFLICTED
:
1002 case DIFFSTATE_CONFLICTED_IGNORED
:
1009 } while((last
<pViewData
->GetCount()) && ((pViewData
->GetState(last
)==DIFFSTATE_CONFLICTED
)||(pViewData
->GetState(last
)==DIFFSTATE_CONFLICTED_IGNORED
)));
1010 file
.Add(_T("<<<<<<< .mine"), EOL_NOENDING
);
1011 for (int j
=first
; j
<last
; j
++)
1013 file
.Add(m_pwndRightView
->m_pViewData
->GetLine(j
), m_pwndRightView
->m_pViewData
->GetLineEnding(j
));
1015 file
.Add(_T("======="), EOL_NOENDING
);
1016 for (int j
=first
; j
<last
; j
++)
1018 file
.Add(m_pwndLeftView
->m_pViewData
->GetLine(j
), m_pwndLeftView
->m_pViewData
->GetLineEnding(j
));
1020 file
.Add(_T(">>>>>>> .theirs"), EOL_NOENDING
);
1024 case DIFFSTATE_EMPTY
:
1025 case DIFFSTATE_CONFLICTEMPTY
:
1026 case DIFFSTATE_IDENTICALREMOVED
:
1027 case DIFFSTATE_REMOVED
:
1028 case DIFFSTATE_THEIRSREMOVED
:
1029 case DIFFSTATE_YOURSREMOVED
:
1030 case DIFFSTATE_CONFLICTRESOLVEDEMPTY
:
1031 // do not save removed lines
1034 file
.Add(pViewData
->GetLine(i
), pViewData
->GetLineEnding(i
));
1038 if (!file
.Save(sFilePath
, false))
1040 CMessageBox::Show(m_hWnd
, file
.GetErrorString(), _T("TortoiseMerge"), MB_ICONERROR
);
1043 m_dlgFilePatches
.SetFileStatusAsPatched(sFilePath
);
1044 if (m_pwndBottomView
)
1045 m_pwndBottomView
->SetModified(FALSE
);
1046 if (m_pwndRightView
)
1047 m_pwndRightView
->SetModified(FALSE
);
1048 CUndo::GetInstance().MarkAsOriginalState();
1049 return file
.GetCount();
1054 void CMainFrame::OnFileSave()
1059 bool CMainFrame::FileSave(bool bCheckResolved
/*=true*/)
1061 if (!m_Data
.m_mergedFile
.InUse())
1062 return FileSaveAs(bCheckResolved
);
1063 // check if the file has the readonly attribute set
1064 bool bDoesNotExist
= false;
1065 DWORD fAttribs
= GetFileAttributes(m_Data
.m_mergedFile
.GetFilename());
1066 if ((fAttribs
!= INVALID_FILE_ATTRIBUTES
)&&(fAttribs
& FILE_ATTRIBUTE_READONLY
))
1067 return FileSaveAs(bCheckResolved
);
1068 if (fAttribs
== INVALID_FILE_ATTRIBUTES
)
1070 bDoesNotExist
= (GetLastError() == ERROR_FILE_NOT_FOUND
);
1074 int nConflictLine
= CheckResolved();
1075 if (nConflictLine
>= 0)
1078 sTemp
.Format(IDS_ERR_MAINFRAME_FILEHASCONFLICTS
, m_pwndBottomView
->m_pViewData
->GetLineNumber(nConflictLine
)+1);
1079 if (MessageBox(sTemp
, 0, MB_ICONERROR
| MB_YESNO
)!=IDYES
)
1081 if (m_pwndBottomView
)
1082 m_pwndBottomView
->GoToLine(nConflictLine
);
1087 if (((DWORD
)CRegDWORD(_T("Software\\TortoiseMerge\\Backup"))) != 0)
1089 MoveFileEx(m_Data
.m_mergedFile
.GetFilename(), m_Data
.m_mergedFile
.GetFilename() + _T(".bak"), MOVEFILE_COPY_ALLOWED
| MOVEFILE_REPLACE_EXISTING
| MOVEFILE_WRITE_THROUGH
);
1091 if (SaveFile(m_Data
.m_mergedFile
.GetFilename())==0)
1093 // file was saved with 0 lines!
1094 // ask the user if the file should be deleted
1096 sTemp
.Format(IDS_DELETEWHENEMPTY
, (LPCTSTR
)m_Data
.m_mergedFile
.GetFilename());
1097 if (CMessageBox::ShowCheck(m_hWnd
, sTemp
, _T("TortoiseMerge"), MB_YESNO
, _T("DeleteFileWhenEmpty")) == IDYES
)
1099 DeleteFile(m_Data
.m_mergedFile
.GetFilename());
1105 // call TortoiseProc to add the new file to version control
1106 CString cmd
= _T("/command:add /noui /path:\"");
1107 cmd
+= m_Data
.m_mergedFile
.GetFilename() + _T("\"");
1108 CAppUtils::RunTortoiseProc(cmd
);
1113 void CMainFrame::OnFileSaveAs()
1118 bool CMainFrame::FileSaveAs(bool bCheckResolved
/*=true*/)
1122 int nConflictLine
= CheckResolved();
1123 if (nConflictLine
>= 0)
1126 sTemp
.Format(IDS_ERR_MAINFRAME_FILEHASCONFLICTS
, m_pwndBottomView
->m_pViewData
->GetLineNumber(nConflictLine
)+1);
1127 if (MessageBox(sTemp
, 0, MB_ICONERROR
| MB_YESNO
)!=IDYES
)
1129 if (m_pwndBottomView
)
1130 m_pwndBottomView
->GoToLine(nConflictLine
);
1135 OPENFILENAME ofn
= {0}; // common dialog box structure
1136 TCHAR szFile
[MAX_PATH
] = {0}; // buffer for file name
1137 ofn
.lStructSize
= sizeof(OPENFILENAME
);
1138 ofn
.hwndOwner
= m_hWnd
;
1139 ofn
.lpstrFile
= szFile
;
1140 ofn
.nMaxFile
= _countof(szFile
);
1142 temp
.LoadString(IDS_SAVEASTITLE
);
1143 if (!temp
.IsEmpty())
1144 ofn
.lpstrTitle
= temp
;
1145 ofn
.Flags
= OFN_OVERWRITEPROMPT
;
1147 sFilter
.LoadString(IDS_COMMONFILEFILTER
);
1148 TCHAR
* pszFilters
= new TCHAR
[sFilter
.GetLength()+4];
1149 _tcscpy_s (pszFilters
, sFilter
.GetLength()+4, sFilter
);
1150 // Replace '|' delimiters with '\0's
1151 TCHAR
*ptr
= pszFilters
+ _tcslen(pszFilters
); //set ptr at the NULL
1152 while (ptr
!= pszFilters
)
1158 ofn
.lpstrFilter
= pszFilters
;
1159 ofn
.nFilterIndex
= 1;
1161 // Display the Open dialog box.
1163 if (GetSaveFileName(&ofn
)==TRUE
)
1165 sFile
= CString(ofn
.lpstrFile
);
1167 delete [] pszFilters
;
1170 delete [] pszFilters
;
1174 void CMainFrame::OnUpdateFileSave(CCmdUI
*pCmdUI
)
1176 BOOL bEnable
= FALSE
;
1177 if (m_Data
.m_mergedFile
.InUse())
1179 if (m_pwndBottomView
)
1181 if ((m_pwndBottomView
->IsWindowVisible())&&(m_pwndBottomView
->m_pViewData
))
1186 if (m_pwndRightView
)
1188 if ((m_pwndRightView
->IsWindowVisible())&&(m_pwndRightView
->m_pViewData
))
1190 if (m_pwndRightView
->IsModified() || (m_Data
.m_yourFile
.GetWindowName().Right(9).Compare(_T(": patched"))==0))
1195 pCmdUI
->Enable(bEnable
);
1198 void CMainFrame::OnUpdateFileSaveAs(CCmdUI
*pCmdUI
)
1200 BOOL bEnable
= FALSE
;
1201 if (m_pwndBottomView
)
1203 if ((m_pwndBottomView
->IsWindowVisible())&&(m_pwndBottomView
->m_pViewData
))
1208 if (m_pwndRightView
)
1210 if ((m_pwndRightView
->IsWindowVisible())&&(m_pwndRightView
->m_pViewData
))
1215 pCmdUI
->Enable(bEnable
);
1219 void CMainFrame::OnUpdateViewOnewaydiff(CCmdUI
*pCmdUI
)
1221 pCmdUI
->SetCheck(!m_bOneWay
);
1222 BOOL bEnable
= TRUE
;
1223 if (m_pwndBottomView
)
1225 if (m_pwndBottomView
->IsWindowVisible())
1228 pCmdUI
->Enable(bEnable
);
1231 void CMainFrame::OnViewOptions()
1234 sTemp
.LoadString(IDS_SETTINGSTITLE
);
1235 CSettings
dlg(sTemp
);
1237 if (dlg
.IsReloadNeeded())
1239 if (CheckForSave()==IDCANCEL
)
1241 CDiffColors::GetInstance().LoadRegistry();
1245 CDiffColors::GetInstance().LoadRegistry();
1246 if (m_pwndBottomView
)
1247 m_pwndBottomView
->Invalidate();
1249 m_pwndLeftView
->Invalidate();
1250 if (m_pwndRightView
)
1251 m_pwndRightView
->Invalidate();
1254 void CMainFrame::OnClose()
1256 if ((m_pFindDialog
)&&(!m_pFindDialog
->IsTerminating()))
1258 m_pFindDialog
->SendMessage(WM_CLOSE
);
1262 if (((m_pwndBottomView
)&&(m_pwndBottomView
->IsModified())) ||
1263 ((m_pwndRightView
)&&(m_pwndRightView
->IsModified())))
1266 sTemp
.LoadString(IDS_ASKFORSAVE
);
1267 ret
= MessageBox(sTemp
, 0, MB_YESNOCANCEL
| MB_ICONQUESTION
);
1274 if ((ret
== IDNO
)||(ret
== IDYES
))
1278 // before it is destroyed, save the position of the window
1279 wp
.length
= sizeof wp
;
1281 if (GetWindowPlacement(&wp
))
1285 // never restore to Iconic state
1286 wp
.showCmd
= SW_SHOW
;
1288 if ((wp
.flags
& WPF_RESTORETOMAXIMIZED
) != 0)
1289 // if maximized and maybe iconic restore maximized state
1290 wp
.showCmd
= SW_SHOWMAXIMIZED
;
1292 // and write it to the .INI file
1293 WriteWindowPlacement(&wp
);
1299 void CMainFrame::OnEditFind()
1307 // start searching from the start again
1308 // if no line is selected, otherwise start from
1309 // the selected line
1310 m_nSearchIndex
= FindSearchStart(0);
1311 m_pFindDialog
= new CFindDlg();
1312 m_pFindDialog
->Create(this);
1316 LRESULT
CMainFrame::OnFindDialogMessage(WPARAM
/*wParam*/, LPARAM
/*lParam*/)
1318 ASSERT(m_pFindDialog
!= NULL
);
1320 if (m_pFindDialog
->IsTerminating())
1322 // invalidate the handle identifying the dialog box.
1323 m_pFindDialog
= NULL
;
1327 if(m_pFindDialog
->FindNext())
1329 //read data from dialog
1330 m_sFindText
= m_pFindDialog
->GetFindString();
1331 m_bMatchCase
= (m_pFindDialog
->MatchCase() == TRUE
);
1332 m_bLimitToDiff
= m_pFindDialog
->LimitToDiffs();
1333 m_bWholeWord
= m_pFindDialog
->WholeWord();
1341 bool CharIsDelimiter(const CString
& ch
)
1343 CString
delimiters(_T(" .,:;=+-*/\\\n\t()[]<>@"));
1344 return delimiters
.Find(ch
) >= 0;
1347 bool CMainFrame::StringFound(const CString
& str
)const
1349 int nSubStringStartIdx
= str
.Find(m_sFindText
);
1350 bool bStringFound
= (nSubStringStartIdx
>= 0);
1351 if (bStringFound
&& m_bWholeWord
)
1353 if (nSubStringStartIdx
)
1354 bStringFound
= CharIsDelimiter(str
.Mid(nSubStringStartIdx
-1,1));
1358 int nEndIndex
= nSubStringStartIdx
+ m_sFindText
.GetLength();
1359 if (str
.GetLength() > nEndIndex
)
1360 bStringFound
= CharIsDelimiter(str
.Mid(nEndIndex
, 1));
1363 return bStringFound
;
1366 void CMainFrame::OnEditFindprev()
1368 Search(SearchPrevious
);
1371 void CMainFrame::OnEditFindnext()
1376 void CMainFrame::Search(SearchDirection srchDir
)
1378 if (m_sFindText
.IsEmpty())
1381 if ((m_pwndLeftView
)&&(m_pwndLeftView
->m_pViewData
))
1383 bool bFound
= FALSE
;
1388 DiffStates leftstate
= DIFFSTATE_NORMAL
;
1389 DiffStates rightstate
= DIFFSTATE_NORMAL
;
1390 DiffStates bottomstate
= DIFFSTATE_NORMAL
;
1393 m_nSearchIndex
= FindSearchStart(m_nSearchIndex
);
1395 if (m_nSearchIndex
>= m_pwndLeftView
->m_pViewData
->GetCount())
1397 if (srchDir
== SearchPrevious
)
1399 // SearchIndex points 1 past where we found the last match,
1400 // so if we are searching backwards we need to adjust accordingly
1401 m_nSearchIndex
-= 2;
1402 // if at the top, start again from the end
1403 if (m_nSearchIndex
< 0)
1404 m_nSearchIndex
+= m_pwndLeftView
->m_pViewData
->GetCount();
1406 const int idxLimits
[2][2][2]={{{m_nSearchIndex
, m_pwndLeftView
->m_pViewData
->GetCount()},
1407 {0, m_nSearchIndex
}},
1408 {{m_nSearchIndex
, -1},
1409 {m_pwndLeftView
->m_pViewData
->GetCount()-1, m_nSearchIndex
}}};
1410 const int offsets
[2]={+1, -1};
1412 for (int j
=0; j
!= 2 && !bFound
; ++j
)
1414 for (i
=idxLimits
[srchDir
][j
][0]; i
!= idxLimits
[srchDir
][j
][1]; i
+= offsets
[srchDir
])
1416 left
= m_pwndLeftView
->m_pViewData
->GetLine(i
);
1417 leftstate
= m_pwndLeftView
->m_pViewData
->GetState(i
);
1418 if ((!m_bOneWay
)&&(m_pwndRightView
->m_pViewData
))
1420 right
= m_pwndRightView
->m_pViewData
->GetLine(i
);
1421 rightstate
= m_pwndRightView
->m_pViewData
->GetState(i
);
1423 if ((m_pwndBottomView
)&&(m_pwndBottomView
->m_pViewData
))
1425 bottom
= m_pwndBottomView
->m_pViewData
->GetLine(i
);
1426 bottomstate
= m_pwndBottomView
->m_pViewData
->GetState(i
);
1431 left
= left
.MakeLower();
1432 right
= right
.MakeLower();
1433 bottom
= bottom
.MakeLower();
1434 m_sFindText
= m_sFindText
.MakeLower();
1436 if (StringFound(left
))
1438 if ((!m_bLimitToDiff
)||(leftstate
!= DIFFSTATE_NORMAL
))
1444 else if (StringFound(right
))
1446 if ((!m_bLimitToDiff
)||(rightstate
!= DIFFSTATE_NORMAL
))
1452 else if (StringFound(bottom
))
1454 if ((!m_bLimitToDiff
)||(bottomstate
!= DIFFSTATE_NORMAL
))
1465 m_pwndLeftView
->GoToLine(m_nSearchIndex
);
1466 if (StringFound(left
))
1468 m_pwndLeftView
->SetFocus();
1469 m_pwndLeftView
->HiglightLines(m_nSearchIndex
);
1471 else if (StringFound(right
))
1473 m_pwndRightView
->SetFocus();
1474 m_pwndRightView
->HiglightLines(m_nSearchIndex
);
1476 else if (StringFound(bottom
))
1478 m_pwndBottomView
->SetFocus();
1479 m_pwndBottomView
->HiglightLines(m_nSearchIndex
);
1489 int CMainFrame::FindSearchStart(int nDefault
)
1491 // TortoiseMerge doesn't have a cursor which we could use to
1492 // anchor the search on.
1493 // Instead we use a line that is selected.
1494 // If however no line is selected, use the default line (which could
1495 // be the top of the document for a new search, or the line where the
1496 // search was successful on)
1497 int nLine
= nDefault
;
1502 if (m_pwndLeftView
->GetSelection(nSelStart
, nSelEnd
))
1504 if (nSelStart
== nSelEnd
)
1508 else if ((nLine
== nDefault
)&&(m_pwndRightView
))
1510 if (m_pwndRightView
->GetSelection(nSelStart
, nSelEnd
))
1512 if (nSelStart
== nSelEnd
)
1516 else if ((nLine
== nDefault
)&&(m_pwndBottomView
))
1518 if (m_pwndBottomView
->GetSelection(nSelStart
, nSelEnd
))
1520 if (nSelStart
== nSelEnd
)
1527 void CMainFrame::OnViewLinedown()
1530 m_pwndLeftView
->ScrollToLine(m_pwndLeftView
->m_nTopLine
+1);
1531 if (m_pwndRightView
)
1532 m_pwndRightView
->ScrollToLine(m_pwndRightView
->m_nTopLine
+1);
1533 if (m_pwndBottomView
)
1534 m_pwndBottomView
->ScrollToLine(m_pwndBottomView
->m_nTopLine
+1);
1535 m_wndLocatorBar
.Invalidate();
1538 void CMainFrame::OnViewLineup()
1541 m_pwndLeftView
->ScrollToLine(m_pwndLeftView
->m_nTopLine
-1);
1542 if (m_pwndRightView
)
1543 m_pwndRightView
->ScrollToLine(m_pwndRightView
->m_nTopLine
-1);
1544 if (m_pwndBottomView
)
1545 m_pwndBottomView
->ScrollToLine(m_pwndBottomView
->m_nTopLine
-1);
1546 m_wndLocatorBar
.Invalidate();
1549 void CMainFrame::OnViewLineleft()
1552 m_pwndLeftView
->ScrollSide(-1);
1553 if (m_pwndRightView
)
1554 m_pwndRightView
->ScrollSide(-1);
1555 if (m_pwndBottomView
)
1556 m_pwndBottomView
->ScrollSide(-1);
1559 void CMainFrame::OnViewLineright()
1562 m_pwndLeftView
->ScrollSide(1);
1563 if (m_pwndRightView
)
1564 m_pwndRightView
->ScrollSide(1);
1565 if (m_pwndBottomView
)
1566 m_pwndBottomView
->ScrollSide(1);
1569 void CMainFrame::OnEditUseTheirs()
1571 if (m_pwndBottomView
)
1572 m_pwndBottomView
->UseTheirTextBlock();
1574 void CMainFrame::OnUpdateEditUsetheirblock(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::OnEditUseMine()
1586 if (m_pwndBottomView
)
1587 m_pwndBottomView
->UseMyTextBlock();
1589 void CMainFrame::OnUpdateEditUsemyblock(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::OnEditUseTheirsThenMine()
1601 if (m_pwndBottomView
)
1602 m_pwndBottomView
->UseTheirThenMyTextBlock();
1604 void CMainFrame::OnUpdateEditUsetheirthenmyblock(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));
1614 void CMainFrame::OnEditUseMineThenTheirs()
1616 if (m_pwndBottomView
)
1617 m_pwndBottomView
->UseMyThenTheirTextBlock();
1619 void CMainFrame::OnUpdateEditUseminethentheirblock(CCmdUI
*pCmdUI
)
1621 int nSelBlockStart
= -1;
1622 int nSelBlockEnd
= -1;
1623 if (m_pwndBottomView
)
1624 m_pwndBottomView
->GetSelection(nSelBlockStart
, nSelBlockEnd
);
1625 pCmdUI
->Enable((nSelBlockStart
>= 0)&&(nSelBlockEnd
>= 0));
1628 void CMainFrame::OnEditUseleftblock()
1630 if (m_pwndRightView
)
1631 m_pwndRightView
->UseBlock();
1634 void CMainFrame::OnUpdateEditUseleftblock(CCmdUI
*pCmdUI
)
1636 pCmdUI
->Enable(m_pwndRightView
&& m_pwndRightView
->IsWindowVisible() && m_pwndRightView
->HasCaret() && m_pwndRightView
->HasSelection());
1639 void CMainFrame::OnEditUseleftfile()
1641 if (m_pwndRightView
)
1642 m_pwndRightView
->UseFile();
1645 void CMainFrame::OnUpdateEditUseleftfile(CCmdUI
*pCmdUI
)
1647 pCmdUI
->Enable(m_pwndRightView
&& m_pwndRightView
->IsWindowVisible() && m_pwndRightView
->HasCaret());
1650 void CMainFrame::OnEditUseblockfromleftbeforeright()
1652 if (m_pwndRightView
)
1653 m_pwndRightView
->UseLeftBeforeRight();
1656 void CMainFrame::OnUpdateEditUseblockfromleftbeforeright(CCmdUI
*pCmdUI
)
1658 pCmdUI
->Enable(m_pwndRightView
&& m_pwndRightView
->IsWindowVisible() && m_pwndRightView
->HasCaret() && m_pwndRightView
->HasSelection());
1661 void CMainFrame::OnEditUseblockfromrightbeforeleft()
1663 if (m_pwndRightView
)
1664 m_pwndRightView
->UseRightBeforeLeft();
1667 void CMainFrame::OnUpdateEditUseblockfromrightbeforeleft(CCmdUI
*pCmdUI
)
1669 pCmdUI
->Enable(m_pwndRightView
&& m_pwndRightView
->IsWindowVisible() && m_pwndRightView
->HasCaret() && m_pwndRightView
->HasSelection());
1673 void CMainFrame::OnFileReload()
1675 if (CheckForSave()==IDCANCEL
)
1677 CDiffColors::GetInstance().LoadRegistry();
1681 void CMainFrame::ActivateFrame(int nCmdShow
)
1683 // nCmdShow is the normal show mode this frame should be in
1684 // translate default nCmdShow (-1)
1687 if (!IsWindowVisible())
1688 nCmdShow
= SW_SHOWNORMAL
;
1689 else if (IsIconic())
1690 nCmdShow
= SW_RESTORE
;
1693 // bring to top before showing
1694 BringToTop(nCmdShow
);
1698 // show the window as specified
1701 if ( !ReadWindowPlacement(&wp
) )
1703 ShowWindow(nCmdShow
);
1707 if ( nCmdShow
!= SW_SHOWNORMAL
)
1708 wp
.showCmd
= nCmdShow
;
1710 SetWindowPlacement(&wp
);
1713 // and finally, bring to top after showing
1714 BringToTop(nCmdShow
);
1719 BOOL
CMainFrame::ReadWindowPlacement(WINDOWPLACEMENT
* pwp
)
1721 CRegString placement
= CRegString(_T("Software\\TortoiseMerge\\WindowPos"));
1722 CString sPlacement
= placement
;
1723 if (sPlacement
.IsEmpty())
1725 int nRead
= _stscanf_s(sPlacement
, _T("%u,%u,%d,%d,%d,%d,%d,%d,%d,%d"),
1726 &pwp
->flags
, &pwp
->showCmd
,
1727 &pwp
->ptMinPosition
.x
, &pwp
->ptMinPosition
.y
,
1728 &pwp
->ptMaxPosition
.x
, &pwp
->ptMaxPosition
.y
,
1729 &pwp
->rcNormalPosition
.left
, &pwp
->rcNormalPosition
.top
,
1730 &pwp
->rcNormalPosition
.right
, &pwp
->rcNormalPosition
.bottom
);
1733 pwp
->length
= sizeof(WINDOWPLACEMENT
);
1738 void CMainFrame::WriteWindowPlacement(WINDOWPLACEMENT
* pwp
)
1740 CRegString placement
= CRegString(_T("Software\\TortoiseMerge\\WindowPos"));
1741 TCHAR szBuffer
[_countof("-32767")*8 + sizeof("65535")*2];
1744 _stprintf_s(szBuffer
, _countof("-32767")*8 + sizeof("65535")*2, _T("%u,%u,%d,%d,%d,%d,%d,%d,%d,%d"),
1745 pwp
->flags
, pwp
->showCmd
,
1746 pwp
->ptMinPosition
.x
, pwp
->ptMinPosition
.y
,
1747 pwp
->ptMaxPosition
.x
, pwp
->ptMaxPosition
.y
,
1748 pwp
->rcNormalPosition
.left
, pwp
->rcNormalPosition
.top
,
1749 pwp
->rcNormalPosition
.right
, pwp
->rcNormalPosition
.bottom
);
1750 placement
= szBuffer
;
1753 void CMainFrame::OnUpdateMergeMarkasresolved(CCmdUI
*pCmdUI
)
1757 BOOL bEnable
= FALSE
;
1758 if ((!m_bReadOnly
)&&(m_Data
.m_mergedFile
.InUse()))
1760 if (m_pwndBottomView
)
1762 if ((m_pwndBottomView
->IsWindowVisible())&&(m_pwndBottomView
->m_pViewData
))
1768 pCmdUI
->Enable(bEnable
);
1771 void CMainFrame::OnMergeMarkasresolved()
1773 int nConflictLine
= CheckResolved();
1774 if (nConflictLine
>= 0)
1777 sTemp
.Format(IDS_ERR_MAINFRAME_FILEHASCONFLICTS
, m_pwndBottomView
->m_pViewData
->GetLineNumber(nConflictLine
)+1);
1778 if (MessageBox(sTemp
, 0, MB_ICONERROR
| MB_YESNO
)!=IDYES
)
1780 if (m_pwndBottomView
)
1781 m_pwndBottomView
->GoToLine(nConflictLine
);
1785 // now check if the file has already been saved and if not, save it.
1786 if (m_Data
.m_mergedFile
.InUse())
1788 if (m_pwndBottomView
)
1790 if ((m_pwndBottomView
->IsWindowVisible())&&(m_pwndBottomView
->m_pViewData
))
1799 BOOL
CMainFrame::MarkAsResolved()
1803 if (!((m_pwndBottomView
) && (m_pwndBottomView
->IsWindowVisible())))
1806 CString cmd
= _T("/command:resolve /path:\"");
1807 cmd
+= m_Data
.m_mergedFile
.GetFilename();
1808 cmd
+= _T("\" /closeonend:1 /noquestion /skipcheck");
1809 if (!CAppUtils::RunTortoiseProc(cmd
))
1815 void CMainFrame::OnUpdateMergeNextconflict(CCmdUI
*pCmdUI
)
1817 pCmdUI
->Enable(m_bHasConflicts
);
1820 void CMainFrame::OnUpdateMergePreviousconflict(CCmdUI
*pCmdUI
)
1822 pCmdUI
->Enable(m_bHasConflicts
);
1825 void CMainFrame::OnMoving(UINT fwSide
, LPRECT pRect
)
1827 // if the pathfilelist dialog is attached to the mainframe,
1828 // move it along with the mainframe
1829 if (::IsWindow(m_dlgFilePatches
.m_hWnd
))
1832 m_dlgFilePatches
.GetWindowRect(&patchrect
);
1833 if (::IsWindow(m_hWnd
))
1836 GetWindowRect(&thisrect
);
1837 if (patchrect
.right
== thisrect
.left
)
1839 m_dlgFilePatches
.SetWindowPos(NULL
, patchrect
.left
- (thisrect
.left
- pRect
->left
), patchrect
.top
- (thisrect
.top
- pRect
->top
),
1840 0, 0, SWP_NOACTIVATE
| SWP_NOOWNERZORDER
| SWP_NOSIZE
| SWP_NOZORDER
);
1844 __super::OnMoving(fwSide
, pRect
);
1847 void CMainFrame::OnUpdateEditCopy(CCmdUI
*pCmdUI
)
1850 if ((m_pwndBottomView
)&&(m_pwndBottomView
->HasSelection()))
1852 if ((m_pwndRightView
)&&(m_pwndRightView
->HasSelection()))
1854 if ((m_pwndLeftView
)&&(m_pwndLeftView
->HasSelection()))
1856 pCmdUI
->Enable(bShow
);
1859 void CMainFrame::OnViewSwitchleft()
1862 if (((m_pwndBottomView
)&&(m_pwndBottomView
->IsModified())) ||
1863 ((m_pwndRightView
)&&(m_pwndRightView
->IsModified())))
1866 sTemp
.LoadString(IDS_ASKFORSAVE
);
1867 ret
= MessageBox(sTemp
, 0, MB_YESNOCANCEL
| MB_ICONQUESTION
);
1874 if ((ret
== IDNO
)||(ret
== IDYES
))
1876 CWorkingFile file
= m_Data
.m_baseFile
;
1877 m_Data
.m_baseFile
= m_Data
.m_yourFile
;
1878 m_Data
.m_yourFile
= file
;
1879 if (m_Data
.m_mergedFile
.GetFilename().CompareNoCase(m_Data
.m_yourFile
.GetFilename())==0)
1881 m_Data
.m_mergedFile
= m_Data
.m_baseFile
;
1883 else if (m_Data
.m_mergedFile
.GetFilename().CompareNoCase(m_Data
.m_baseFile
.GetFilename())==0)
1885 m_Data
.m_mergedFile
= m_Data
.m_yourFile
;
1891 void CMainFrame::OnUpdateViewSwitchleft(CCmdUI
*pCmdUI
)
1893 BOOL bEnable
= TRUE
;
1894 if (m_pwndBottomView
)
1896 if (m_pwndBottomView
->IsWindowVisible())
1899 pCmdUI
->Enable(bEnable
);
1903 void CMainFrame::OnUpdateViewShowfilelist(CCmdUI
*pCmdUI
)
1905 if (m_dlgFilePatches
.HasFiles())
1907 pCmdUI
->Enable(true);
1910 pCmdUI
->Enable(false);
1911 pCmdUI
->SetCheck(m_dlgFilePatches
.IsWindowVisible());
1914 void CMainFrame::OnViewShowfilelist()
1916 m_dlgFilePatches
.ShowWindow(m_dlgFilePatches
.IsWindowVisible() ? SW_HIDE
: SW_SHOW
);
1919 void CMainFrame::OnEditUndo()
1921 if (CUndo::GetInstance().CanUndo())
1923 CUndo::GetInstance().Undo(m_pwndLeftView
, m_pwndRightView
, m_pwndBottomView
);
1928 void CMainFrame::OnUpdateEditUndo(CCmdUI
*pCmdUI
)
1930 pCmdUI
->Enable(CUndo::GetInstance().CanUndo());
1933 int CMainFrame::CheckForSave()
1936 if (((m_pwndBottomView
)&&(m_pwndBottomView
->IsModified())) ||
1937 ((m_pwndRightView
)&&(m_pwndRightView
->IsModified())))
1940 sTemp
.LoadString(IDS_WARNMODIFIEDLOOSECHANGES
);
1941 ret
= MessageBox(sTemp
, 0, MB_YESNOCANCEL
| MB_ICONQUESTION
);
1951 void CMainFrame::OnViewInlinediffword()
1953 m_bInlineWordDiff
= !m_bInlineWordDiff
;
1956 m_pwndLeftView
->SetInlineWordDiff(m_bInlineWordDiff
);
1957 m_pwndLeftView
->Invalidate();
1959 if (m_pwndRightView
)
1961 m_pwndRightView
->SetInlineWordDiff(m_bInlineWordDiff
);
1962 m_pwndRightView
->Invalidate();
1964 if (m_pwndBottomView
)
1966 m_pwndBottomView
->SetInlineWordDiff(m_bInlineWordDiff
);
1967 m_pwndBottomView
->Invalidate();
1969 m_wndLineDiffBar
.Invalidate();
1972 void CMainFrame::OnUpdateViewInlinediffword(CCmdUI
*pCmdUI
)
1974 pCmdUI
->Enable(m_pwndLeftView
&& m_pwndLeftView
->IsWindowVisible() &&
1975 m_pwndRightView
&& m_pwndRightView
->IsWindowVisible());
1976 pCmdUI
->SetCheck(m_bInlineWordDiff
);
1979 void CMainFrame::OnUpdateEditCreateunifieddifffile(CCmdUI
*pCmdUI
)
1981 // "create unified diff file" is only available if two files
1982 // are diffed, not three.
1983 bool bEnabled
= true;
1984 if ((m_pwndLeftView
== NULL
)||(!m_pwndLeftView
->IsWindowVisible()))
1986 if ((m_pwndRightView
== NULL
)||(!m_pwndRightView
->IsWindowVisible()))
1988 if ((m_pwndBottomView
)&&(m_pwndBottomView
->IsWindowVisible()))
1990 pCmdUI
->Enable(bEnabled
);
1993 void CMainFrame::OnEditCreateunifieddifffile()
1995 CString origFile
, modifiedFile
, outputFile
;
1996 // the original file is the one on the left
1998 origFile
= m_pwndLeftView
->m_sFullFilePath
;
1999 if (m_pwndRightView
)
2000 modifiedFile
= m_pwndRightView
->m_sFullFilePath
;
2001 if (!origFile
.IsEmpty() && !modifiedFile
.IsEmpty())
2003 // ask for the path to save the unified diff file to
2004 OPENFILENAME ofn
= {0}; // common dialog box structure
2005 TCHAR szFile
[MAX_PATH
] = {0}; // buffer for file name
2006 ofn
.lStructSize
= sizeof(OPENFILENAME
);
2007 ofn
.lpstrFile
= szFile
;
2008 ofn
.nMaxFile
= _countof(szFile
);
2010 temp
.LoadString(IDS_SAVEASTITLE
);
2011 if (!temp
.IsEmpty())
2012 ofn
.lpstrTitle
= temp
;
2013 ofn
.Flags
= OFN_OVERWRITEPROMPT
;
2015 sFilter
.LoadString(IDS_COMMONFILEFILTER
);
2016 TCHAR
* pszFilters
= new TCHAR
[sFilter
.GetLength()+4];
2017 _tcscpy_s (pszFilters
, sFilter
.GetLength()+4, sFilter
);
2018 // Replace '|' delimiters with '\0's
2019 TCHAR
*ptr
= pszFilters
+ _tcslen(pszFilters
); //set ptr at the NULL
2020 while (ptr
!= pszFilters
)
2026 ofn
.lpstrFilter
= pszFilters
;
2027 ofn
.nFilterIndex
= 1;
2029 // Display the Save dialog box.
2031 if (GetSaveFileName(&ofn
)==TRUE
)
2033 outputFile
= CString(ofn
.lpstrFile
);
2034 CAppUtils::CreateUnifiedDiff(origFile
, modifiedFile
, outputFile
, true);
2036 delete [] pszFilters
;
2040 void CMainFrame::OnUpdateViewLinediffbar(CCmdUI
*pCmdUI
)
2042 pCmdUI
->SetCheck(m_bLineDiff
);
2046 void CMainFrame::OnViewLinediffbar()
2048 m_bLineDiff
= !m_bLineDiff
;
2049 m_wndLineDiffBar
.ShowPane(m_bLineDiff
, false, true);
2050 m_wndLineDiffBar
.DocumentUpdated();
2051 m_wndLocatorBar
.ShowPane(m_bLocatorBar
, false, true);
2052 m_wndLocatorBar
.DocumentUpdated();
2055 void CMainFrame::OnUpdateViewLocatorbar(CCmdUI
*pCmdUI
)
2057 pCmdUI
->SetCheck(m_bLocatorBar
);
2061 void CMainFrame::OnViewLocatorbar()
2063 m_bLocatorBar
= !m_bLocatorBar
;
2064 m_wndLocatorBar
.ShowPane(m_bLocatorBar
, false, true);
2065 m_wndLocatorBar
.DocumentUpdated();
2066 m_wndLineDiffBar
.ShowPane(m_bLineDiff
, false, true);
2067 m_wndLineDiffBar
.DocumentUpdated();