1 // TortoiseGitMerge - a Diff/Patch program
3 // Copyright (C) 2008-2013 - TortoiseGit
4 // Copyright (C) 2004-2012 - TortoiseSVN
5 // Copyright (C) 2012-2013 - Sven Strickroth <email@cs-ware.de>
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 2
10 // of the License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software Foundation,
19 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #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"
35 #include "SelectFileFilter.h"
36 #include "FormatMessageWrapper.h"
37 #include "TaskbarUUID.h"
45 const UINT TaskBarButtonCreated
= RegisterWindowMessage(L
"TaskbarButtonCreated");
47 IMPLEMENT_DYNCREATE(CMainFrame
, CFrameWndEx
)
49 BEGIN_MESSAGE_MAP(CMainFrame
, CFrameWndEx
)
51 ON_COMMAND_RANGE(ID_VIEW_APPLOOK_WIN7
, ID_VIEW_APPLOOK_OFF_2007_AQUA
, &CMainFrame::OnApplicationLook
)
52 ON_UPDATE_COMMAND_UI_RANGE(IDC_STYLEBUTTON
, ID_VIEW_APPLOOK_OFF_2007_AQUA
, &CMainFrame::OnUpdateApplicationLook
)
53 // Global help commands
54 ON_COMMAND(ID_HELP_FINDER
, CFrameWndEx::OnHelpFinder
)
55 ON_COMMAND(ID_HELP
, CFrameWndEx::OnHelp
)
56 ON_COMMAND(ID_CONTEXT_HELP
, CFrameWndEx::OnContextHelp
)
57 ON_COMMAND(ID_DEFAULT_HELP
, CFrameWndEx::OnHelpFinder
)
58 ON_COMMAND(ID_FILE_OPEN
, OnFileOpen
)
59 ON_COMMAND(ID_VIEW_WHITESPACES
, OnViewWhitespaces
)
61 ON_COMMAND(ID_FILE_SAVE
, OnFileSave
)
62 ON_COMMAND(ID_FILE_SAVE_AS
, OnFileSaveAs
)
63 ON_UPDATE_COMMAND_UI(ID_FILE_SAVE
, OnUpdateFileSave
)
64 ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_AS
, OnUpdateFileSaveAs
)
65 ON_COMMAND(ID_VIEW_ONEWAYDIFF
, OnViewOnewaydiff
)
66 ON_UPDATE_COMMAND_UI(ID_VIEW_ONEWAYDIFF
, OnUpdateViewOnewaydiff
)
67 ON_UPDATE_COMMAND_UI(ID_VIEW_WHITESPACES
, OnUpdateViewWhitespaces
)
68 ON_COMMAND(ID_VIEW_OPTIONS
, OnViewOptions
)
71 ON_COMMAND(ID_FILE_RELOAD
, OnFileReload
)
72 ON_COMMAND(ID_VIEW_LINEDOWN
, OnViewLinedown
)
73 ON_COMMAND(ID_VIEW_LINEUP
, OnViewLineup
)
74 ON_COMMAND(ID_VIEW_MOVEDBLOCKS
, OnViewMovedBlocks
)
75 ON_UPDATE_COMMAND_UI(ID_VIEW_MOVEDBLOCKS
, OnUpdateViewMovedBlocks
)
76 ON_UPDATE_COMMAND_UI(ID_EDIT_MARKASRESOLVED
, OnUpdateMergeMarkasresolved
)
77 ON_COMMAND(ID_EDIT_MARKASRESOLVED
, OnMergeMarkasresolved
)
78 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_NEXTCONFLICT
, OnUpdateMergeNextconflict
)
79 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_PREVIOUSCONFLICT
, OnUpdateMergePreviousconflict
)
82 ON_UPDATE_COMMAND_UI(ID_EDIT_COPY
, OnUpdateEditCopy
)
83 ON_COMMAND(ID_VIEW_SWITCHLEFT
, OnViewSwitchleft
)
84 ON_UPDATE_COMMAND_UI(ID_VIEW_SWITCHLEFT
, OnUpdateViewSwitchleft
)
85 ON_COMMAND(ID_VIEW_LINELEFT
, &CMainFrame::OnViewLineleft
)
86 ON_COMMAND(ID_VIEW_LINERIGHT
, &CMainFrame::OnViewLineright
)
87 ON_UPDATE_COMMAND_UI(ID_VIEW_SHOWFILELIST
, &CMainFrame::OnUpdateViewShowfilelist
)
88 ON_COMMAND(ID_VIEW_SHOWFILELIST
, &CMainFrame::OnViewShowfilelist
)
89 ON_COMMAND(ID_EDIT_USETHEIRBLOCK
, &CMainFrame::OnEditUseTheirs
)
90 ON_COMMAND(ID_EDIT_USEMYBLOCK
, &CMainFrame::OnEditUseMine
)
91 ON_COMMAND(ID_EDIT_USETHEIRTHENMYBLOCK
, &CMainFrame::OnEditUseTheirsThenMine
)
92 ON_COMMAND(ID_EDIT_USEMINETHENTHEIRBLOCK
, &CMainFrame::OnEditUseMineThenTheirs
)
93 ON_COMMAND(ID_EDIT_UNDO
, &CMainFrame::OnEditUndo
)
94 ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO
, &CMainFrame::OnUpdateEditUndo
)
95 ON_UPDATE_COMMAND_UI(ID_EDIT_USEMINETHENTHEIRBLOCK
, &CMainFrame::OnUpdateEditUseminethentheirblock
)
96 ON_UPDATE_COMMAND_UI(ID_EDIT_USEMYBLOCK
, &CMainFrame::OnUpdateEditUsemyblock
)
97 ON_UPDATE_COMMAND_UI(ID_EDIT_USETHEIRBLOCK
, &CMainFrame::OnUpdateEditUsetheirblock
)
98 ON_UPDATE_COMMAND_UI(ID_EDIT_USETHEIRTHENMYBLOCK
, &CMainFrame::OnUpdateEditUsetheirthenmyblock
)
99 ON_COMMAND(ID_VIEW_INLINEDIFFWORD
, &CMainFrame::OnViewInlinediffword
)
100 ON_UPDATE_COMMAND_UI(ID_VIEW_INLINEDIFFWORD
, &CMainFrame::OnUpdateViewInlinediffword
)
101 ON_COMMAND(ID_VIEW_INLINEDIFF
, &CMainFrame::OnViewInlinediff
)
102 ON_UPDATE_COMMAND_UI(ID_VIEW_INLINEDIFF
, &CMainFrame::OnUpdateViewInlinediff
)
103 ON_UPDATE_COMMAND_UI(ID_EDIT_CREATEUNIFIEDDIFFFILE
, &CMainFrame::OnUpdateEditCreateunifieddifffile
)
104 ON_COMMAND(ID_EDIT_CREATEUNIFIEDDIFFFILE
, &CMainFrame::OnEditCreateunifieddifffile
)
105 ON_UPDATE_COMMAND_UI(ID_VIEW_LINEDIFFBAR
, &CMainFrame::OnUpdateViewLinediffbar
)
106 ON_COMMAND(ID_VIEW_LINEDIFFBAR
, &CMainFrame::OnViewLinediffbar
)
107 ON_UPDATE_COMMAND_UI(ID_VIEW_LOCATORBAR
, &CMainFrame::OnUpdateViewLocatorbar
)
108 ON_COMMAND(ID_VIEW_LOCATORBAR
, &CMainFrame::OnViewLocatorbar
)
109 ON_COMMAND(ID_EDIT_USELEFTBLOCK
, &CMainFrame::OnEditUseleftblock
)
110 ON_UPDATE_COMMAND_UI(ID_USEBLOCKS
, &CMainFrame::OnUpdateUseBlock
)
111 ON_UPDATE_COMMAND_UI(ID_EDIT_USELEFTBLOCK
, &CMainFrame::OnUpdateEditUseleftblock
)
112 ON_COMMAND(ID_EDIT_USELEFTFILE
, &CMainFrame::OnEditUseleftfile
)
113 ON_UPDATE_COMMAND_UI(ID_EDIT_USELEFTFILE
, &CMainFrame::OnUpdateEditUseleftfile
)
114 ON_COMMAND(ID_EDIT_USEBLOCKFROMLEFTBEFORERIGHT
, &CMainFrame::OnEditUseblockfromleftbeforeright
)
115 ON_UPDATE_COMMAND_UI(ID_EDIT_USEBLOCKFROMLEFTBEFORERIGHT
, &CMainFrame::OnUpdateEditUseblockfromleftbeforeright
)
116 ON_COMMAND(ID_EDIT_USEBLOCKFROMRIGHTBEFORELEFT
, &CMainFrame::OnEditUseblockfromrightbeforeleft
)
117 ON_UPDATE_COMMAND_UI(ID_EDIT_USEBLOCKFROMRIGHTBEFORELEFT
, &CMainFrame::OnUpdateEditUseblockfromrightbeforeleft
)
118 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_NEXTDIFFERENCE
, &CMainFrame::OnUpdateNavigateNextdifference
)
119 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_PREVIOUSDIFFERENCE
, &CMainFrame::OnUpdateNavigatePreviousdifference
)
120 ON_COMMAND(ID_VIEW_COLLAPSED
, &CMainFrame::OnViewCollapsed
)
121 ON_UPDATE_COMMAND_UI(ID_VIEW_COLLAPSED
, &CMainFrame::OnUpdateViewCollapsed
)
122 ON_COMMAND(ID_VIEW_COMPAREWHITESPACES
, &CMainFrame::OnViewComparewhitespaces
)
123 ON_UPDATE_COMMAND_UI(ID_VIEW_COMPAREWHITESPACES
, &CMainFrame::OnUpdateViewComparewhitespaces
)
124 ON_COMMAND(ID_VIEW_IGNOREWHITESPACECHANGES
, &CMainFrame::OnViewIgnorewhitespacechanges
)
125 ON_UPDATE_COMMAND_UI(ID_VIEW_IGNOREWHITESPACECHANGES
, &CMainFrame::OnUpdateViewIgnorewhitespacechanges
)
126 ON_COMMAND(ID_VIEW_IGNOREALLWHITESPACECHANGES
, &CMainFrame::OnViewIgnoreallwhitespacechanges
)
127 ON_UPDATE_COMMAND_UI(ID_VIEW_IGNOREALLWHITESPACECHANGES
, &CMainFrame::OnUpdateViewIgnoreallwhitespacechanges
)
128 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_NEXTINLINEDIFF
, &CMainFrame::OnUpdateNavigateNextinlinediff
)
129 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_PREVINLINEDIFF
, &CMainFrame::OnUpdateNavigatePrevinlinediff
)
130 ON_COMMAND(ID_VIEW_WRAPLONGLINES
, &CMainFrame::OnViewWraplonglines
)
131 ON_UPDATE_COMMAND_UI(ID_VIEW_WRAPLONGLINES
, &CMainFrame::OnUpdateViewWraplonglines
)
132 ON_REGISTERED_MESSAGE( TaskBarButtonCreated
, CMainFrame::OnTaskbarButtonCreated
)
133 ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE
, &CMainFrame::OnUpdateEditPaste
)
136 static UINT indicators
[] =
138 ID_SEPARATOR
, // status line indicator
139 ID_INDICATOR_LEFTVIEW
,
140 ID_INDICATOR_RIGHTVIEW
,
141 ID_INDICATOR_BOTTOMVIEW
,
147 // CMainFrame construction/destruction
149 CMainFrame::CMainFrame()
150 : m_bInitSplitter(FALSE
)
151 , m_bReversedPatch(FALSE
)
152 , m_bHasConflicts(false)
153 , m_bInlineWordDiff(true)
155 , m_bLocatorBar(true)
156 , m_nMoveMovesToIgnore(0)
157 , m_pwndLeftView(NULL
)
158 , m_pwndRightView(NULL
)
159 , m_pwndBottomView(NULL
)
162 , m_bCheckReload(false)
163 , m_bSaveRequired(false)
165 , resolveMsgWParam(0)
166 , resolveMsgLParam(0)
167 , m_regWrapLines(L
"Software\\TortoiseGitMerge\\WrapLines", 0)
168 , m_regViewModedBlocks(L
"Software\\TortoiseGitMerge\\ViewMovedBlocks", TRUE
)
169 , m_regOneWay(L
"Software\\TortoiseGitMerge\\OnePane")
170 , m_regCollapsed(L
"Software\\TortoiseGitMerge\\Collapsed", 0)
171 , m_regInlineDiff(L
"Software\\TortoiseGitMerge\\DisplayBinDiff", TRUE
)
172 , m_regUseRibbons(L
"Software\\TortoiseGitMerge\\UseRibbons", TRUE
)
174 m_bOneWay
= (0 != ((DWORD
)m_regOneWay
));
175 theApp
.m_nAppLook
= theApp
.GetInt(_T("ApplicationLook"), ID_VIEW_APPLOOK_VS_2005
);
176 m_bCollapsed
= !!(DWORD
)m_regCollapsed
;
177 m_bViewMovedBlocks
= !!(DWORD
)m_regViewModedBlocks
;
178 m_bWrapLines
= !!(DWORD
)m_regWrapLines
;
179 m_bInlineDiff
= !!m_regInlineDiff
;
180 m_bUseRibbons
= !!m_regUseRibbons
;
181 CMFCVisualManagerWindows::m_b3DTabsXPTheme
= TRUE
;
184 CMainFrame::~CMainFrame()
188 LRESULT
CMainFrame::OnTaskbarButtonCreated(WPARAM
/*wParam*/, LPARAM
/*lParam*/)
190 SetUUIDOverlayIcon(m_hWnd
);
195 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct
)
197 if (CFrameWndEx::OnCreate(lpCreateStruct
) == -1)
200 OnApplicationLook(theApp
.m_nAppLook
);
204 m_wndRibbonBar
.Create(this);
205 m_wndRibbonBar
.LoadFromResource(IDR_RIBBON
);
207 // enable the dialog launch button on the view panel
208 CMFCRibbonCategory
* pMainCat
= m_wndRibbonBar
.GetCategory(1);
211 CMFCRibbonPanel
* pPanel
= pMainCat
->GetPanel(3);
213 pPanel
->EnableLaunchButton(ID_VIEW_OPTIONS
);
218 if (!m_wndMenuBar
.Create(this))
220 TRACE0("Failed to create menubar\n");
221 return -1; // fail to create
223 m_wndMenuBar
.SetPaneStyle(m_wndMenuBar
.GetPaneStyle() | CBRS_SIZE_DYNAMIC
| CBRS_TOOLTIPS
| CBRS_FLYBY
);
225 // prevent the menu bar from taking the focus on activation
226 CMFCPopupMenu::SetForceMenuFocus(FALSE
);
227 if (!m_wndToolBar
.CreateEx(this, TBSTYLE_FLAT
, WS_CHILD
| WS_VISIBLE
| CBRS_ALIGN_TOP
| CBRS_GRIPPER
| CBRS_TOOLTIPS
| CBRS_FLYBY
) || !m_wndToolBar
.LoadToolBar(IDR_MAINFRAME
))
229 TRACE0("Failed to create toolbar\n");
230 return -1; // fail to create
232 m_wndToolBar
.SetWindowText(_T("Main"));
234 if (!m_wndStatusBar
.Create(this) ||
235 !m_wndStatusBar
.SetIndicators(indicators
,
236 _countof(indicators
)))
238 TRACE0("Failed to create status bar\n");
239 return -1; // fail to create
242 if (!m_wndLocatorBar
.Create(this, IDD_DIFFLOCATOR
,
243 CBRS_ALIGN_LEFT
| CBRS_SIZE_FIXED
, ID_VIEW_LOCATORBAR
))
245 TRACE0("Failed to create dialogbar\n");
246 return -1; // fail to create
248 if (!m_wndLineDiffBar
.Create(this, IDD_LINEDIFF
,
249 CBRS_ALIGN_BOTTOM
| CBRS_SIZE_FIXED
, ID_VIEW_LINEDIFFBAR
))
251 TRACE0("Failed to create dialogbar\n");
252 return -1; // fail to create
254 m_wndLocatorBar
.m_pMainFrm
= this;
255 m_wndLineDiffBar
.m_pMainFrm
= this;
257 EnableDocking(CBRS_ALIGN_ANY
);
260 m_wndMenuBar
.EnableDocking(CBRS_ALIGN_TOP
);
261 m_wndToolBar
.EnableDocking(CBRS_ALIGN_TOP
);
262 DockPane(&m_wndMenuBar
);
263 DockPane(&m_wndToolBar
);
265 DockPane(&m_wndLocatorBar
);
266 DockPane(&m_wndLineDiffBar
);
267 ShowPane(&m_wndLocatorBar
, true, false, true);
268 ShowPane(&m_wndLineDiffBar
, true, false, true);
270 m_wndLocatorBar
.EnableGripper(FALSE
);
271 m_wndLineDiffBar
.EnableGripper(FALSE
);
276 BOOL
CMainFrame::PreCreateWindow(CREATESTRUCT
& cs
)
278 if( !CFrameWndEx::PreCreateWindow(cs
) )
283 void CMainFrame::OnApplicationLook(UINT id
)
287 theApp
.m_nAppLook
= id
;
289 switch (theApp
.m_nAppLook
)
291 case ID_VIEW_APPLOOK_WIN_2000
:
292 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManager
));
293 m_wndRibbonBar
.SetWindows7Look(FALSE
);
296 case ID_VIEW_APPLOOK_OFF_XP
:
297 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOfficeXP
));
298 m_wndRibbonBar
.SetWindows7Look(FALSE
);
301 case ID_VIEW_APPLOOK_WIN_XP
:
302 CMFCVisualManagerWindows::m_b3DTabsXPTheme
= TRUE
;
303 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows
));
304 m_wndRibbonBar
.SetWindows7Look(FALSE
);
307 case ID_VIEW_APPLOOK_OFF_2003
:
308 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2003
));
309 CDockingManager::SetDockingMode(DT_SMART
);
310 m_wndRibbonBar
.SetWindows7Look(FALSE
);
313 case ID_VIEW_APPLOOK_VS_2005
:
314 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerVS2005
));
315 CDockingManager::SetDockingMode(DT_SMART
);
316 m_wndRibbonBar
.SetWindows7Look(FALSE
);
319 case ID_VIEW_APPLOOK_VS_2008
:
320 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerVS2008
));
321 CDockingManager::SetDockingMode(DT_SMART
);
322 m_wndRibbonBar
.SetWindows7Look(FALSE
);
325 case ID_VIEW_APPLOOK_WIN7
:
326 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows7
));
327 CDockingManager::SetDockingMode(DT_SMART
);
328 m_wndRibbonBar
.SetWindows7Look(TRUE
);
332 switch (theApp
.m_nAppLook
)
334 case ID_VIEW_APPLOOK_OFF_2007_BLUE
:
335 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_LunaBlue
);
338 case ID_VIEW_APPLOOK_OFF_2007_BLACK
:
339 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_ObsidianBlack
);
342 case ID_VIEW_APPLOOK_OFF_2007_SILVER
:
343 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_Silver
);
346 case ID_VIEW_APPLOOK_OFF_2007_AQUA
:
347 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_Aqua
);
351 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2007
));
352 CDockingManager::SetDockingMode(DT_SMART
);
353 m_wndRibbonBar
.SetWindows7Look(FALSE
);
356 RedrawWindow(NULL
, NULL
, RDW_ALLCHILDREN
| RDW_INVALIDATE
| RDW_UPDATENOW
| RDW_FRAME
| RDW_ERASE
);
358 theApp
.WriteInt(_T("ApplicationLook"), theApp
.m_nAppLook
);
361 void CMainFrame::OnUpdateApplicationLook(CCmdUI
* pCmdUI
)
364 pCmdUI
->SetRadio(theApp
.m_nAppLook
== pCmdUI
->m_nID
);
368 // CMainFrame diagnostics
371 void CMainFrame::AssertValid() const
373 CFrameWndEx::AssertValid();
376 void CMainFrame::Dump(CDumpContext
& dc
) const
378 CFrameWndEx::Dump(dc
);
384 // CMainFrame message handlers
387 BOOL
CMainFrame::OnCreateClient(LPCREATESTRUCT
/*lpcs*/, CCreateContext
* pContext
)
393 // split into three panes:
402 // create a splitter with 2 rows, 1 column
403 if (!m_wndSplitter
.CreateStatic(this, 2, 1))
405 TRACE0("Failed to CreateStaticSplitter\n");
409 // add the second splitter pane - which is a nested splitter with 2 columns
410 if (!m_wndSplitter2
.CreateStatic(
411 &m_wndSplitter
, // our parent window is the first splitter
412 1, 2, // the new splitter is 1 row, 2 columns
413 WS_CHILD
| WS_VISIBLE
| WS_BORDER
, // style, WS_BORDER is needed
414 m_wndSplitter
.IdFromRowCol(0, 0)
415 // new splitter is in the first row, 1st column of first splitter
418 TRACE0("Failed to create nested splitter\n");
421 // add the first splitter pane - the default view in row 0
422 if (!m_wndSplitter
.CreateView(1, 0,
423 RUNTIME_CLASS(CBottomView
), CSize(cr
.Width(), cr
.Height()), pContext
))
425 TRACE0("Failed to create first pane\n");
428 m_pwndBottomView
= (CBottomView
*)m_wndSplitter
.GetPane(1,0);
429 m_pwndBottomView
->m_pwndLocator
= &m_wndLocatorBar
;
430 m_pwndBottomView
->m_pwndLineDiffBar
= &m_wndLineDiffBar
;
431 m_pwndBottomView
->m_pwndStatusBar
= &m_wndStatusBar
;
432 m_pwndBottomView
->m_pMainFrame
= this;
434 // now create the two views inside the nested splitter
436 if (!m_wndSplitter2
.CreateView(0, 0,
437 RUNTIME_CLASS(CLeftView
), CSize(cr
.Width()/2, cr
.Height()/2), pContext
))
439 TRACE0("Failed to create second pane\n");
442 m_pwndLeftView
= (CLeftView
*)m_wndSplitter2
.GetPane(0,0);
443 m_pwndLeftView
->m_pwndLocator
= &m_wndLocatorBar
;
444 m_pwndLeftView
->m_pwndLineDiffBar
= &m_wndLineDiffBar
;
445 m_pwndLeftView
->m_pwndStatusBar
= &m_wndStatusBar
;
446 m_pwndLeftView
->m_pMainFrame
= this;
448 if (!m_wndSplitter2
.CreateView(0, 1,
449 RUNTIME_CLASS(CRightView
), CSize(cr
.Width()/2, cr
.Height()/2), pContext
))
451 TRACE0("Failed to create third pane\n");
454 m_pwndRightView
= (CRightView
*)m_wndSplitter2
.GetPane(0,1);
455 m_pwndRightView
->m_pwndLocator
= &m_wndLocatorBar
;
456 m_pwndRightView
->m_pwndLineDiffBar
= &m_wndLineDiffBar
;
457 m_pwndRightView
->m_pwndStatusBar
= &m_wndStatusBar
;
458 m_pwndRightView
->m_pMainFrame
= this;
459 m_bInitSplitter
= TRUE
;
461 m_dlgFilePatches
.Create(IDD_FILEPATCHES
, this);
467 BOOL
CMainFrame::PatchFile(CString sFilePath
, bool /*bContentMods*/, bool bPropMods
, CString sVersion
, BOOL bAutoPatch
)
470 //"dry run" was successful, so save the patched file somewhere...
471 CString sTempFile
= CTempFiles::Instance().GetTempFilePathString();
472 CString sRejectedFile
;
473 if (m_Patch
.GetPatchResult(sFilePath
, sTempFile
, sRejectedFile
) < 0)
475 MessageBox(m_Patch
.GetErrorMessage(), NULL
, MB_ICONERROR
);
478 sFilePath
= m_Patch
.GetTargetPath() + _T("\\") + sFilePath
;
479 sFilePath
.Replace('/', '\\');
480 if (m_bReversedPatch
)
482 m_Data
.m_baseFile
.SetFileName(sTempFile
);
484 temp
.Format(_T("%s %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sFilePath
), (LPCTSTR
)m_Data
.m_sPatchPatched
);
485 m_Data
.m_baseFile
.SetDescriptiveName(temp
);
486 m_Data
.m_yourFile
.SetFileName(sFilePath
);
487 temp
.Format(_T("%s %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sFilePath
), (LPCTSTR
)m_Data
.m_sPatchOriginal
);
488 m_Data
.m_yourFile
.SetDescriptiveName(temp
);
489 m_Data
.m_theirFile
.SetOutOfUse();
490 m_Data
.m_mergedFile
.SetOutOfUse();
494 if ((!PathFileExists(sFilePath
))||(PathIsDirectory(sFilePath
)))
496 m_Data
.m_baseFile
.SetFileName(CTempFiles::Instance().GetTempFilePathString());
497 m_Data
.m_baseFile
.CreateEmptyFile();
501 m_Data
.m_baseFile
.SetFileName(sFilePath
);
503 CString sDescription
;
504 sDescription
.Format(_T("%s %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sFilePath
), (LPCTSTR
)m_Data
.m_sPatchOriginal
);
505 m_Data
.m_baseFile
.SetDescriptiveName(sDescription
);
506 m_Data
.m_yourFile
.SetFileName(sTempFile
);
508 temp
.Format(_T("%s %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sFilePath
), (LPCTSTR
)m_Data
.m_sPatchPatched
);
509 m_Data
.m_yourFile
.SetDescriptiveName(temp
);
510 m_Data
.m_theirFile
.SetOutOfUse();
511 m_Data
.m_mergedFile
.SetFileName(sFilePath
);
512 m_Data
.m_bPatchRequired
= bPropMods
;
514 TRACE(_T("comparing %s\nwith the patched result %s\n"), (LPCTSTR
)sFilePath
, (LPCTSTR
)sTempFile
);
517 if (!sRejectedFile
.IsEmpty())
520 // start TortoiseUDiff with the rejected hunks
522 sTitle
.Format(IDS_TITLE_REJECTEDHUNKS
, (LPCTSTR
)CPathUtils::GetFileNameFromPath(sFilePath
));
523 CAppUtils::StartUnifiedDiffViewer(sRejectedFile
, sTitle
);
534 BOOL
CMainFrame::DiffFiles(CString sURL1
, CString sRev1
, CString sURL2
, CString sRev2
)
536 CString tempfile1
= CTempFiles::Instance().GetTempFilePathString();
537 CString tempfile2
= CTempFiles::Instance().GetTempFilePathString();
539 ASSERT(tempfile1
.Compare(tempfile2
));
542 CSysProgressDlg progDlg
;
543 sTemp
.Format(IDS_GETVERSIONOFFILE
, (LPCTSTR
)sRev1
);
544 progDlg
.SetLine(1, sTemp
, true);
545 progDlg
.SetLine(2, sURL1
, true);
546 sTemp
.LoadString(IDS_GETVERSIONOFFILETITLE
);
547 progDlg
.SetTitle(sTemp
);
548 progDlg
.SetShowProgressBar(true);
549 progDlg
.SetAnimation(IDR_DOWNLOAD
);
550 progDlg
.SetTime(FALSE
);
551 progDlg
.SetProgress(1,100);
552 progDlg
.ShowModeless(this);
553 if (!CAppUtils::GetVersionedFile(sURL1
, sRev1
, tempfile1
, &progDlg
, m_hWnd
))
557 sErrMsg
.Format(IDS_ERR_MAINFRAME_FILEVERSIONNOTFOUND
, (LPCTSTR
)sRev1
, (LPCTSTR
)sURL1
);
558 MessageBox(sErrMsg
, NULL
, MB_ICONERROR
);
561 sTemp
.Format(IDS_GETVERSIONOFFILE
, (LPCTSTR
)sRev2
);
562 progDlg
.SetLine(1, sTemp
, true);
563 progDlg
.SetLine(2, sURL2
, true);
564 progDlg
.SetProgress(50, 100);
565 if (!CAppUtils::GetVersionedFile(sURL2
, sRev2
, tempfile2
, &progDlg
, m_hWnd
))
569 sErrMsg
.Format(IDS_ERR_MAINFRAME_FILEVERSIONNOTFOUND
, (LPCTSTR
)sRev2
, (LPCTSTR
)sURL2
);
570 MessageBox(sErrMsg
, NULL
, MB_ICONERROR
);
573 progDlg
.SetProgress(100,100);
576 temp
.Format(_T("%s Revision %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sURL1
), (LPCTSTR
)sRev1
);
577 m_Data
.m_baseFile
.SetFileName(tempfile1
);
578 m_Data
.m_baseFile
.SetDescriptiveName(temp
);
579 temp
.Format(_T("%s Revision %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sURL2
), (LPCTSTR
)sRev2
);
580 m_Data
.m_yourFile
.SetFileName(tempfile2
);
581 m_Data
.m_yourFile
.SetDescriptiveName(temp
);
588 void CMainFrame::OnFileOpen()
590 if (CheckForSave()==IDCANCEL
)
593 if (dlg
.DoModal()!=IDOK
)
597 m_dlgFilePatches
.ShowWindow(SW_HIDE
);
598 m_dlgFilePatches
.Init(NULL
, NULL
, CString(), NULL
);
599 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
,
600 (LPCTSTR
)dlg
.m_sUnifiedDiffFile
, (LPCTSTR
)dlg
.m_sPatchDirectory
);
601 m_Data
.m_baseFile
.SetFileName(dlg
.m_sBaseFile
);
602 m_Data
.m_theirFile
.SetFileName(dlg
.m_sTheirFile
);
603 m_Data
.m_yourFile
.SetFileName(dlg
.m_sYourFile
);
604 m_Data
.m_sDiffFile
= dlg
.m_sUnifiedDiffFile
;
605 m_Data
.m_sPatchPath
= dlg
.m_sPatchDirectory
;
606 m_Data
.m_mergedFile
.SetOutOfUse();
607 CCrashReport::Instance().AddFile2(dlg
.m_sBaseFile
, NULL
, _T("Basefile"), CR_AF_MAKE_FILE_COPY
);
608 CCrashReport::Instance().AddFile2(dlg
.m_sTheirFile
, NULL
, _T("Theirfile"), CR_AF_MAKE_FILE_COPY
);
609 CCrashReport::Instance().AddFile2(dlg
.m_sYourFile
, NULL
, _T("Yourfile"), CR_AF_MAKE_FILE_COPY
);
610 CCrashReport::Instance().AddFile2(dlg
.m_sUnifiedDiffFile
, NULL
, _T("Difffile"), CR_AF_MAKE_FILE_COPY
);
612 if (!m_Data
.IsBaseFileInUse() && m_Data
.IsTheirFileInUse() && m_Data
.IsYourFileInUse())
614 // a diff between two files means "Yours" against "Base", not "Theirs" against "Yours"
615 m_Data
.m_baseFile
.TransferDetailsFrom(m_Data
.m_theirFile
);
617 if (m_Data
.IsBaseFileInUse() && m_Data
.IsTheirFileInUse() && !m_Data
.IsYourFileInUse())
619 // a diff between two files means "Yours" against "Base", not "Theirs" against "Base"
620 m_Data
.m_yourFile
.TransferDetailsFrom(m_Data
.m_theirFile
);
622 m_bSaveRequired
= false;
627 void CMainFrame::ClearViewNamesAndPaths()
629 m_pwndLeftView
->m_sWindowName
.Empty();
630 m_pwndLeftView
->m_sFullFilePath
.Empty();
631 m_pwndRightView
->m_sWindowName
.Empty();
632 m_pwndRightView
->m_sFullFilePath
.Empty();
633 m_pwndBottomView
->m_sWindowName
.Empty();
634 m_pwndBottomView
->m_sFullFilePath
.Empty();
637 bool CMainFrame::LoadViews(int line
)
639 m_Data
.SetBlame(m_bBlame
);
640 m_Data
.SetMovedBlocks(m_bViewMovedBlocks
);
641 m_bHasConflicts
= false;
642 CBaseView
* pwndActiveView
= m_pwndLeftView
;
643 int nOldLine
= m_pwndRightView
? m_pwndRightView
->m_nTopLine
: -1;
645 m_pwndRightView
&& m_pwndRightView
->m_pViewData
?
646 m_pwndRightView
->m_pViewData
->GetLineNumber(m_pwndRightView
->m_nTopLine
) : -1;
647 POINT ptOldCaretPos
= {-1, -1};
648 if (m_pwndRightView
&& m_pwndRightView
->IsTarget())
649 ptOldCaretPos
= m_pwndRightView
->GetCaretPosition();
650 if (m_pwndBottomView
&& m_pwndBottomView
->IsTarget())
651 ptOldCaretPos
= m_pwndBottomView
->GetCaretPosition();
654 m_pwndLeftView
->BuildAllScreen2ViewVector();
655 m_pwndLeftView
->DocumentUpdated();
656 m_pwndRightView
->DocumentUpdated();
657 m_pwndBottomView
->DocumentUpdated();
658 m_wndLocatorBar
.DocumentUpdated();
659 m_wndLineDiffBar
.DocumentUpdated();
660 ::MessageBox(m_hWnd
, m_Data
.GetError(), _T("TortoiseGitMerge"), MB_ICONERROR
);
661 m_Data
.m_mergedFile
.SetOutOfUse();
662 m_bSaveRequired
= false;
666 m_pwndLeftView
->BuildAllScreen2ViewVector();
667 m_pwndLeftView
->DocumentUpdated();
668 m_pwndRightView
->DocumentUpdated();
669 m_pwndBottomView
->DocumentUpdated();
670 m_wndLocatorBar
.DocumentUpdated();
671 m_wndLineDiffBar
.DocumentUpdated();
673 m_pwndRightView
->SetWritable(false);
674 m_pwndRightView
->SetTarget(false);
675 m_pwndBottomView
->SetWritable(false);
676 m_pwndBottomView
->SetTarget(false);
678 if (!m_Data
.IsBaseFileInUse())
680 CSysProgressDlg progDlg
;
681 if (m_Data
.IsYourFileInUse() && m_Data
.IsTheirFileInUse())
683 m_Data
.m_baseFile
.TransferDetailsFrom(m_Data
.m_theirFile
);
685 else if ((!m_Data
.m_sDiffFile
.IsEmpty())&&(!m_Patch
.Init(m_Data
.m_sDiffFile
, m_Data
.m_sPatchPath
, &progDlg
)))
688 ClearViewNamesAndPaths();
689 MessageBox(m_Patch
.GetErrorMessage(), NULL
, MB_ICONERROR
);
690 m_bSaveRequired
= false;
694 if (m_Patch
.GetNumberOfFiles() > 0)
696 CString betterpatchpath
= m_Patch
.CheckPatchPath(m_Data
.m_sPatchPath
);
697 if (betterpatchpath
.CompareNoCase(m_Data
.m_sPatchPath
)!=0)
700 msg
.Format(IDS_WARNBETTERPATCHPATHFOUND
, (LPCTSTR
)m_Data
.m_sPatchPath
, (LPCTSTR
)betterpatchpath
);
701 if (CMessageBox::Show(m_hWnd
, msg
, _T("TortoiseGitMerge"), MB_ICONQUESTION
| MB_YESNO
)==IDYES
)
703 m_Data
.m_sPatchPath
= betterpatchpath
;
704 m_Patch
.Init(m_Data
.m_sDiffFile
, m_Data
.m_sPatchPath
, &progDlg
);
707 m_dlgFilePatches
.Init(&m_Patch
, this, m_Data
.m_sPatchPath
, this);
708 m_dlgFilePatches
.ShowWindow(SW_SHOW
);
709 ClearViewNamesAndPaths();
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 if (m_Data
.IsBaseFileInUse() && !m_Data
.IsYourFileInUse() && m_Data
.IsTheirFileInUse())
719 m_Data
.m_yourFile
.TransferDetailsFrom(m_Data
.m_theirFile
);
721 if (m_Data
.IsBaseFileInUse() && m_Data
.IsYourFileInUse() && !m_Data
.IsTheirFileInUse())
723 //diff between YOUR and BASE
724 m_pwndRightView
->SetWritable();
725 m_pwndRightView
->SetTarget();
728 if (!m_wndSplitter2
.IsColumnHidden(1))
729 m_wndSplitter2
.HideColumn(1);
731 m_pwndLeftView
->m_pViewData
= &m_Data
.m_YourBaseBoth
;
732 m_pwndLeftView
->texttype
= m_Data
.m_arYourFile
.GetUnicodeType();
733 m_pwndLeftView
->lineendings
= m_Data
.m_arYourFile
.GetLineEndings();
734 m_pwndLeftView
->m_sWindowName
= m_Data
.m_baseFile
.GetWindowName() + _T(" - ") + m_Data
.m_yourFile
.GetWindowName();
735 m_pwndLeftView
->m_sFullFilePath
= m_Data
.m_baseFile
.GetFilename() + _T(" - ") + m_Data
.m_yourFile
.GetFilename();
737 m_pwndRightView
->m_pViewData
= NULL
;
738 m_pwndBottomView
->m_pViewData
= NULL
;
740 if (!m_wndSplitter
.IsRowHidden(1))
741 m_wndSplitter
.HideRow(1);
742 m_pwndLeftView
->SetHidden(FALSE
);
743 m_pwndRightView
->SetHidden(TRUE
);
744 m_pwndBottomView
->SetHidden(TRUE
);
745 ::SetWindowPos(m_pwndLeftView
->m_hWnd
, NULL
, 0, 0, 0, 0, SWP_FRAMECHANGED
| SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOSIZE
);
749 pwndActiveView
= m_pwndRightView
;
750 if (m_wndSplitter2
.IsColumnHidden(1))
751 m_wndSplitter2
.ShowColumn();
753 m_pwndLeftView
->m_pViewData
= &m_Data
.m_YourBaseLeft
;
754 m_pwndLeftView
->texttype
= m_Data
.m_arBaseFile
.GetUnicodeType();
755 m_pwndLeftView
->lineendings
= m_Data
.m_arBaseFile
.GetLineEndings();
756 m_pwndLeftView
->m_sWindowName
= m_Data
.m_baseFile
.GetWindowName();
757 m_pwndLeftView
->m_sFullFilePath
= m_Data
.m_baseFile
.GetFilename();
758 m_pwndLeftView
->m_sConvertedFilePath
= m_Data
.m_baseFile
.GetConvertedFileName();
760 m_pwndRightView
->m_pViewData
= &m_Data
.m_YourBaseRight
;
761 m_pwndRightView
->texttype
= m_Data
.m_arYourFile
.GetUnicodeType();
762 m_pwndRightView
->lineendings
= m_Data
.m_arYourFile
.GetLineEndings();
763 m_pwndRightView
->m_sWindowName
= m_Data
.m_yourFile
.GetWindowName();
764 m_pwndRightView
->m_sFullFilePath
= m_Data
.m_yourFile
.GetFilename();
765 m_pwndRightView
->m_sConvertedFilePath
= m_Data
.m_yourFile
.GetConvertedFileName();
767 m_pwndBottomView
->m_pViewData
= NULL
;
769 if (!m_wndSplitter
.IsRowHidden(1))
770 m_wndSplitter
.HideRow(1);
771 m_pwndLeftView
->SetHidden(FALSE
);
772 m_pwndRightView
->SetHidden(FALSE
);
773 m_pwndBottomView
->SetHidden(TRUE
);
776 else if (m_Data
.IsBaseFileInUse() && m_Data
.IsYourFileInUse() && m_Data
.IsTheirFileInUse())
778 //diff between THEIR, YOUR and BASE
779 m_pwndBottomView
->SetWritable();
780 m_pwndBottomView
->SetTarget();
781 pwndActiveView
= m_pwndBottomView
;
783 m_pwndLeftView
->m_pViewData
= &m_Data
.m_TheirBaseBoth
;
784 m_pwndLeftView
->texttype
= m_Data
.m_arTheirFile
.GetUnicodeType();
785 m_pwndLeftView
->lineendings
= m_Data
.m_arTheirFile
.GetLineEndings();
786 m_pwndLeftView
->m_sWindowName
.LoadString(IDS_VIEWTITLE_THEIRS
);
787 m_pwndLeftView
->m_sWindowName
+= _T(" - ") + m_Data
.m_theirFile
.GetWindowName();
788 m_pwndLeftView
->m_sFullFilePath
= m_Data
.m_theirFile
.GetFilename();
789 m_pwndLeftView
->m_sConvertedFilePath
= m_Data
.m_theirFile
.GetConvertedFileName();
791 m_pwndRightView
->m_pViewData
= &m_Data
.m_YourBaseBoth
;
792 m_pwndRightView
->texttype
= m_Data
.m_arYourFile
.GetUnicodeType();
793 m_pwndRightView
->lineendings
= m_Data
.m_arYourFile
.GetLineEndings();
794 m_pwndRightView
->m_sWindowName
.LoadString(IDS_VIEWTITLE_MINE
);
795 m_pwndRightView
->m_sWindowName
+= _T(" - ") + m_Data
.m_yourFile
.GetWindowName();
796 m_pwndRightView
->m_sFullFilePath
= m_Data
.m_yourFile
.GetFilename();
797 m_pwndRightView
->m_sConvertedFilePath
= m_Data
.m_yourFile
.GetConvertedFileName();
799 m_pwndBottomView
->m_pViewData
= &m_Data
.m_Diff3
;
800 m_pwndBottomView
->texttype
= m_Data
.m_arTheirFile
.GetUnicodeType();
801 m_pwndBottomView
->lineendings
= m_Data
.m_arTheirFile
.GetLineEndings();
802 m_pwndBottomView
->m_sWindowName
.LoadString(IDS_VIEWTITLE_MERGED
);
803 m_pwndBottomView
->m_sWindowName
+= _T(" - ") + m_Data
.m_mergedFile
.GetWindowName();
804 m_pwndBottomView
->m_sFullFilePath
= m_Data
.m_mergedFile
.GetFilename();
805 m_pwndBottomView
->m_sConvertedFilePath
= m_Data
.m_mergedFile
.GetConvertedFileName();
807 if (m_wndSplitter2
.IsColumnHidden(1))
808 m_wndSplitter2
.ShowColumn();
809 if (m_wndSplitter
.IsRowHidden(1))
810 m_wndSplitter
.ShowRow();
811 m_pwndLeftView
->SetHidden(FALSE
);
812 m_pwndRightView
->SetHidden(FALSE
);
813 m_pwndBottomView
->SetHidden(FALSE
);
814 // in three pane view, hide the line diff bar
815 m_wndLineDiffBar
.ShowPane(false, false, true);
816 m_wndLineDiffBar
.DocumentUpdated();
818 if (!m_Data
.m_mergedFile
.InUse())
820 m_Data
.m_mergedFile
.SetFileName(m_Data
.m_yourFile
.GetFilename());
822 m_pwndLeftView
->BuildAllScreen2ViewVector();
823 m_pwndLeftView
->DocumentUpdated();
824 m_pwndRightView
->DocumentUpdated();
825 m_pwndBottomView
->DocumentUpdated();
826 m_wndLocatorBar
.DocumentUpdated();
827 m_wndLineDiffBar
.DocumentUpdated();
829 SetActiveView(pwndActiveView
);
831 if ((line
>= -1) && m_pwndRightView
->m_pViewData
)
833 int n
= line
== -1 ? min( nOldLineNumber
, nOldLine
) : line
;
835 n
= m_pwndRightView
->m_pViewData
->FindLineNumber(n
);
839 m_pwndRightView
->ScrollAllToLine(n
);
843 if ((ptOldCaretPos
.x
>= 0) || (ptOldCaretPos
.y
>= 0))
845 m_pwndLeftView
->SetCaretPosition(p
);
846 m_pwndRightView
->SetCaretPosition(p
);
847 m_pwndBottomView
->SetCaretPosition(p
);
848 m_pwndBottomView
->ScrollToChar(0);
849 m_pwndLeftView
->ScrollToChar(0);
850 m_pwndRightView
->ScrollToChar(0);
854 CRegDWORD regFirstDiff
= CRegDWORD(_T("Software\\TortoiseGitMerge\\FirstDiffOnLoad"), TRUE
);
855 CRegDWORD regFirstConflict
= CRegDWORD(_T("Software\\TortoiseGitMerge\\FirstConflictOnLoad"), TRUE
);
856 bool bGoFirstDiff
= (0 != (DWORD
)regFirstDiff
);
857 bool bGoFirstConflict
= (0 != (DWORD
)regFirstConflict
);
858 if (bGoFirstConflict
&& (CheckResolved()>=0))
860 pwndActiveView
->GoToFirstConflict();
861 // Ignore the first few Mouse Move messages, so that the line diff stays on
862 // the first diff line until the user actually moves the mouse
863 m_nMoveMovesToIgnore
= MOVESTOIGNORE
;
865 else if (bGoFirstDiff
)
867 pwndActiveView
->GoToFirstDifference();
868 // Ignore the first few Mouse Move messages, so that the line diff stays on
869 // the first diff line until the user actually moves the mouse
870 m_nMoveMovesToIgnore
= MOVESTOIGNORE
;
874 // Avoid incorrect rendering of active pane.
875 m_pwndBottomView
->ScrollToChar(0);
876 m_pwndLeftView
->ScrollToChar(0);
877 m_pwndRightView
->ScrollToChar(0);
882 m_bSaveRequired
= false;
883 CUndo::GetInstance().Clear();
887 void CMainFrame::UpdateLayout()
891 m_wndSplitter
.CenterSplitter();
892 m_wndSplitter2
.CenterSplitter();
896 void CMainFrame::OnSize(UINT nType
, int cx
, int cy
)
898 CFrameWndEx::OnSize(nType
, cx
, cy
);
899 if (m_bInitSplitter
&& nType
!= SIZE_MINIMIZED
)
901 if (m_wndSplitter
.GetSafeHwnd())
903 if (m_wndSplitter
.HasOldRowSize() && (m_wndSplitter
.GetOldRowCount() == 2))
905 int oldTotal
= m_wndSplitter
.GetOldRowSize(0) + m_wndSplitter
.GetOldRowSize(1);
908 int cxCur0
, cxCur1
, cxMin0
, cxMin1
;
909 m_wndSplitter
.GetRowInfo(0, cxCur0
, cxMin0
);
910 m_wndSplitter
.GetRowInfo(1, cxCur1
, cxMin1
);
911 cxCur0
= m_wndSplitter
.GetOldRowSize(0) * (cxCur0
+ cxCur1
) / oldTotal
;
912 cxCur1
= m_wndSplitter
.GetOldRowSize(1) * (cxCur0
+ cxCur1
) / oldTotal
;
913 m_wndSplitter
.SetRowInfo(0, cxCur0
, 0);
914 m_wndSplitter
.SetRowInfo(1, cxCur1
, 0);
915 m_wndSplitter
.RecalcLayout();
919 if (m_wndSplitter2
.HasOldColSize() && (m_wndSplitter2
.GetOldColCount() == 2))
921 int oldTotal
= m_wndSplitter2
.GetOldColSize(0) + m_wndSplitter2
.GetOldColSize(1);
924 int cyCur0
, cyCur1
, cyMin0
, cyMin1
;
925 m_wndSplitter2
.GetColumnInfo(0, cyCur0
, cyMin0
);
926 m_wndSplitter2
.GetColumnInfo(1, cyCur1
, cyMin1
);
927 cyCur0
= m_wndSplitter2
.GetOldColSize(0) * (cyCur0
+ cyCur1
) / oldTotal
;
928 cyCur1
= m_wndSplitter2
.GetOldColSize(1) * (cyCur0
+ cyCur1
) / oldTotal
;
929 m_wndSplitter2
.SetColumnInfo(0, cyCur0
, 0);
930 m_wndSplitter2
.SetColumnInfo(1, cyCur1
, 0);
931 m_wndSplitter2
.RecalcLayout();
936 if ((nType
== SIZE_RESTORED
)&&m_bCheckReload
)
938 m_bCheckReload
= false;
942 // workaround for ribbon interface when taskbar is on the left/top
943 if (nType
== SIZE_MAXIMIZED
)
946 GetWindowPlacement(&wp
);
947 wp
.ptMaxPosition
.x
= wp
.ptMaxPosition
.y
= 0;
948 SetWindowPlacement(&wp
);
952 void CMainFrame::OnViewWhitespaces()
954 CRegDWORD regViewWhitespaces
= CRegDWORD(_T("Software\\TortoiseGitMerge\\ViewWhitespaces"), 1);
955 BOOL bViewWhitespaces
= regViewWhitespaces
;
957 bViewWhitespaces
= m_pwndLeftView
->m_bViewWhitespace
;
959 bViewWhitespaces
= !bViewWhitespaces
;
960 regViewWhitespaces
= bViewWhitespaces
;
963 m_pwndLeftView
->m_bViewWhitespace
= bViewWhitespaces
;
964 m_pwndLeftView
->Invalidate();
968 m_pwndRightView
->m_bViewWhitespace
= bViewWhitespaces
;
969 m_pwndRightView
->Invalidate();
971 if (m_pwndBottomView
)
973 m_pwndBottomView
->m_bViewWhitespace
= bViewWhitespaces
;
974 m_pwndBottomView
->Invalidate();
978 void CMainFrame::OnUpdateViewWhitespaces(CCmdUI
*pCmdUI
)
981 pCmdUI
->SetCheck(m_pwndLeftView
->m_bViewWhitespace
);
984 void CMainFrame::OnViewCollapsed()
986 m_regCollapsed
= !(DWORD
)m_regCollapsed
;
987 m_bCollapsed
= !!(DWORD
)m_regCollapsed
;
989 OnViewTextFoldUnfold();
990 m_wndLocatorBar
.Invalidate();
993 void CMainFrame::OnUpdateViewCollapsed(CCmdUI
*pCmdUI
)
995 pCmdUI
->SetCheck(m_bCollapsed
);
998 void CMainFrame::OnViewWraplonglines()
1000 m_bWrapLines
= !(DWORD
)m_regWrapLines
;
1001 m_regWrapLines
= m_bWrapLines
;
1003 if (m_pwndLeftView
) m_pwndLeftView
->WrapChanged();
1004 if (m_pwndRightView
) m_pwndRightView
->WrapChanged();
1005 if (m_pwndBottomView
) m_pwndBottomView
->WrapChanged();
1006 OnViewTextFoldUnfold();
1007 m_wndLocatorBar
.DocumentUpdated();
1010 void CMainFrame::OnViewTextFoldUnfold()
1012 OnViewTextFoldUnfold(m_pwndLeftView
);
1013 OnViewTextFoldUnfold(m_pwndRightView
);
1014 OnViewTextFoldUnfold(m_pwndBottomView
);
1017 void CMainFrame::OnViewTextFoldUnfold(CBaseView
* view
)
1021 view
->BuildAllScreen2ViewVector();
1022 view
->UpdateCaret();
1024 view
->EnsureCaretVisible();
1027 void CMainFrame::OnUpdateViewWraplonglines(CCmdUI
*pCmdUI
)
1029 pCmdUI
->SetCheck(m_bWrapLines
);
1032 void CMainFrame::OnViewOnewaydiff()
1034 if (CheckForSave()==IDCANCEL
)
1036 m_bOneWay
= !m_bOneWay
;
1037 ShowDiffBar(!m_bOneWay
);
1041 void CMainFrame::ShowDiffBar(bool bShow
)
1045 // restore the line diff bar
1046 m_wndLineDiffBar
.ShowPane(m_bLineDiff
, false, true);
1047 m_wndLineDiffBar
.DocumentUpdated();
1048 m_wndLocatorBar
.ShowPane(m_bLocatorBar
, false, true);
1049 m_wndLocatorBar
.DocumentUpdated();
1053 // in one way view, hide the line diff bar
1054 m_wndLineDiffBar
.ShowPane(false, false, true);
1055 m_wndLineDiffBar
.DocumentUpdated();
1059 int CMainFrame::CheckResolved()
1061 //only in three way diffs can be conflicts!
1062 m_bHasConflicts
= true;
1063 if (m_pwndBottomView
->IsWindowVisible())
1065 CViewData
* viewdata
= m_pwndBottomView
->m_pViewData
;
1068 for (int i
=0; i
<viewdata
->GetCount(); i
++)
1070 const DiffStates state
= viewdata
->GetState(i
);
1071 if ((DIFFSTATE_CONFLICTED
== state
)||(DIFFSTATE_CONFLICTED_IGNORED
== state
))
1076 m_bHasConflicts
= false;
1080 int CMainFrame::SaveFile(const CString
& sFilePath
)
1082 CViewData
* pViewData
= NULL
;
1083 CFileTextLines
* pOriginFile
= &m_Data
.m_arBaseFile
;
1084 if (IsViewGood(m_pwndBottomView
))
1086 pViewData
= m_pwndBottomView
->m_pViewData
;
1089 else if (IsViewGood(m_pwndRightView
))
1091 pViewData
= m_pwndRightView
->m_pViewData
;
1092 if (m_Data
.IsYourFileInUse())
1093 pOriginFile
= &m_Data
.m_arYourFile
;
1094 else if (m_Data
.IsTheirFileInUse())
1095 pOriginFile
= &m_Data
.m_arTheirFile
;
1103 if ((pViewData
)&&(pOriginFile
))
1105 CFileTextLines file
;
1106 pOriginFile
->CopySettings(&file
);
1107 for (int i
=0; i
<pViewData
->GetCount(); i
++)
1109 //only copy non-removed lines
1110 DiffStates state
= pViewData
->GetState(i
);
1113 case DIFFSTATE_CONFLICTED
:
1114 case DIFFSTATE_CONFLICTED_IGNORED
:
1121 } while((last
<pViewData
->GetCount()) && ((pViewData
->GetState(last
)==DIFFSTATE_CONFLICTED
)||(pViewData
->GetState(last
)==DIFFSTATE_CONFLICTED_IGNORED
)));
1122 // TortoiseGitMerge changes here
1123 file
.Add(_T("<<<<<<< .mine"), m_pwndRightView
->lineendings
);
1124 for (int j
=first
; j
<last
; j
++)
1126 EOL lineending
= m_pwndRightView
->m_pViewData
->GetLineEnding(j
);
1127 if (lineending
== EOL_NOENDING
)
1128 lineending
= m_pwndRightView
->lineendings
;
1129 file
.Add(m_pwndRightView
->m_pViewData
->GetLine(j
), lineending
);
1131 file
.Add(_T("======="), m_pwndRightView
->lineendings
);
1132 for (int j
=first
; j
<last
; j
++)
1134 EOL lineending
= m_pwndLeftView
->m_pViewData
->GetLineEnding(j
);
1135 if (lineending
== EOL_NOENDING
)
1136 lineending
= m_pwndLeftView
->lineendings
;
1137 file
.Add(m_pwndLeftView
->m_pViewData
->GetLine(j
), lineending
);
1139 file
.Add(_T(">>>>>>> .theirs"), m_pwndRightView
->lineendings
);
1143 case DIFFSTATE_EMPTY
:
1144 case DIFFSTATE_CONFLICTEMPTY
:
1145 case DIFFSTATE_IDENTICALREMOVED
:
1146 case DIFFSTATE_REMOVED
:
1147 case DIFFSTATE_THEIRSREMOVED
:
1148 case DIFFSTATE_YOURSREMOVED
:
1149 case DIFFSTATE_CONFLICTRESOLVEDEMPTY
:
1150 // do not save removed lines
1153 file
.Add(pViewData
->GetLine(i
), pViewData
->GetLineEnding(i
));
1157 if (!file
.Save(sFilePath
, false, false))
1159 CMessageBox::Show(m_hWnd
, file
.GetErrorString(), _T("TortoiseGitMerge"), MB_ICONERROR
);
1162 if (sFilePath
== m_Data
.m_baseFile
.GetFilename())
1164 m_Data
.m_baseFile
.StoreFileAttributes();
1166 if (sFilePath
== m_Data
.m_theirFile
.GetFilename())
1168 m_Data
.m_theirFile
.StoreFileAttributes();
1170 if (sFilePath
== m_Data
.m_yourFile
.GetFilename())
1172 m_Data
.m_yourFile
.StoreFileAttributes();
1174 /*if (sFilePath == m_Data.m_mergedFile.GetFilename())
1176 m_Data.m_mergedFile.StoreFileAttributes();
1178 m_dlgFilePatches
.SetFileStatusAsPatched(sFilePath
);
1179 if (m_pwndBottomView
)
1180 m_pwndBottomView
->SetModified(FALSE
);
1181 if (m_pwndRightView
)
1182 m_pwndRightView
->SetModified(FALSE
);
1183 CUndo::GetInstance().MarkAsOriginalState();
1184 if (file
.GetCount() == 1 && file
.GetAt(0).IsEmpty() && file
.GetLineEnding(0) == EOL_NOENDING
)
1186 return file
.GetCount();
1191 void CMainFrame::OnFileSave()
1196 void CMainFrame::PatchSave()
1198 bool bDoesNotExist
= !PathFileExists(m_Data
.m_mergedFile
.GetFilename());
1199 if (m_Data
.m_bPatchRequired
)
1201 m_Patch
.PatchPath(m_Data
.m_mergedFile
.GetFilename());
1203 if (!PathIsDirectory(m_Data
.m_mergedFile
.GetFilename()))
1205 int saveret
= SaveFile(m_Data
.m_mergedFile
.GetFilename());
1208 // file was saved with 0 lines, remove it.
1209 m_Patch
.RemoveFile(m_Data
.m_mergedFile
.GetFilename());
1211 DeleteFile(m_Data
.m_mergedFile
.GetFilename());
1213 m_Data
.m_mergedFile
.StoreFileAttributes();
1214 if (m_Data
.m_mergedFile
.GetFilename() == m_Data
.m_yourFile
.GetFilename())
1215 m_Data
.m_yourFile
.StoreFileAttributes();
1216 if ((bDoesNotExist
)&&(DWORD(CRegDWORD(_T("Software\\TortoiseGitMerge\\AutoAdd"), TRUE
))))
1218 // call TortoiseProc to add the new file to version control
1219 CString cmd
= _T("/command:add /noui /path:\"");
1220 cmd
+= m_Data
.m_mergedFile
.GetFilename() + _T("\"");
1221 CAppUtils::RunTortoiseGitProc(cmd
);
1226 bool CMainFrame::FileSave(bool bCheckResolved
/*=true*/)
1228 if (!m_Data
.m_mergedFile
.InUse())
1229 return FileSaveAs(bCheckResolved
);
1230 // check if the file has the readonly attribute set
1231 bool bDoesNotExist
= false;
1232 DWORD fAttribs
= GetFileAttributes(m_Data
.m_mergedFile
.GetFilename());
1233 if ((fAttribs
!= INVALID_FILE_ATTRIBUTES
)&&(fAttribs
& FILE_ATTRIBUTE_READONLY
))
1234 return FileSaveAs(bCheckResolved
);
1235 if (fAttribs
== INVALID_FILE_ATTRIBUTES
)
1237 bDoesNotExist
= (GetLastError() == ERROR_FILE_NOT_FOUND
);
1239 if (bCheckResolved
&& HasConflictsWontKeep())
1242 if (((DWORD
)CRegDWORD(_T("Software\\TortoiseGitMerge\\Backup"))) != 0)
1244 MoveFileEx(m_Data
.m_mergedFile
.GetFilename(), m_Data
.m_mergedFile
.GetFilename() + _T(".bak"), MOVEFILE_COPY_ALLOWED
| MOVEFILE_REPLACE_EXISTING
| MOVEFILE_WRITE_THROUGH
);
1246 if (m_Data
.m_bPatchRequired
)
1248 m_Patch
.PatchPath(m_Data
.m_mergedFile
.GetFilename());
1250 int saveret
= SaveFile(m_Data
.m_mergedFile
.GetFilename());
1253 // file was saved with 0 lines!
1254 // ask the user if the file should be deleted
1256 sTemp
.Format(IDS_DELETEWHENEMPTY
, (LPCTSTR
)m_Data
.m_mergedFile
.GetFilename());
1257 if (CMessageBox::ShowCheck(m_hWnd
, sTemp
, _T("TortoiseGitMerge"), MB_YESNO
, _T("DeleteFileWhenEmpty")) == IDYES
)
1259 m_Patch
.RemoveFile(m_Data
.m_mergedFile
.GetFilename());
1260 DeleteFile(m_Data
.m_mergedFile
.GetFilename());
1263 else if (saveret
< 0)
1265 // error while saving the file
1269 // if we're in conflict resolve mode (three pane view), check if there are no more conflicts
1270 // and if there aren't, ask to mark the file as resolved
1271 if (IsViewGood(m_pwndBottomView
) && !m_bHasConflicts
)
1273 CString projectRoot
;
1274 if (g_GitAdminDir
.HasAdminDir(m_Data
.m_mergedFile
.GetFilename(), false, &projectRoot
))
1276 CString subpath
= m_Data
.m_mergedFile
.GetFilename();
1277 subpath
.Replace(_T('\\'), _T('/'));
1278 if (subpath
.GetLength() >= projectRoot
.GetLength())
1280 if (subpath
[projectRoot
.GetLength()] == _T('/'))
1281 subpath
= subpath
.Right(subpath
.GetLength() - projectRoot
.GetLength() - 1);
1283 subpath
= subpath
.Right(subpath
.GetLength() - projectRoot
.GetLength());
1286 CStringA gitdir
= CUnicodeUtils::GetMulti(projectRoot
, CP_UTF8
);
1287 git_repository
*repository
= NULL
;
1288 git_index
*index
= NULL
;
1289 bool hasConflictInIndex
= false;
1292 if (git_repository_open(&repository
, gitdir
.GetBuffer()))
1294 gitdir
.ReleaseBuffer();
1297 gitdir
.ReleaseBuffer();
1299 if (git_repository_index(&index
, repository
))
1302 CStringA path
= CUnicodeUtils::GetMulti(subpath
, CP_UTF8
);
1303 const git_index_entry
* entry
= git_index_get_bypath(index
, path
.GetBuffer(), 1);
1304 path
.ReleaseBuffer();
1305 hasConflictInIndex
= entry
!= nullptr;
1309 git_index_free(index
);
1312 git_repository_free(repository
);
1314 if (hasConflictInIndex
)
1317 sTemp
.Format(IDS_MARKASRESOLVED
, (LPCTSTR
)CPathUtils::GetFileNameFromPath(m_Data
.m_mergedFile
.GetFilename()));
1318 if (CMessageBox::Show(m_hWnd
, sTemp
, _T("TortoiseGitMerge"), MB_YESNO
| MB_ICONQUESTION
) == IDYES
)
1324 m_bSaveRequired
= false;
1325 m_Data
.m_mergedFile
.StoreFileAttributes();
1327 if ((bDoesNotExist
)&&(DWORD(CRegDWORD(_T("Software\\TortoiseGitMerge\\AutoAdd"), TRUE
))))
1329 // call TortoiseProc to add the new file to version control
1330 CString cmd
= _T("/command:add /noui /path:\"");
1331 cmd
+= m_Data
.m_mergedFile
.GetFilename() + _T("\"");
1332 if(!CAppUtils::RunTortoiseGitProc(cmd
))
1338 void CMainFrame::OnFileSaveAs()
1343 bool CMainFrame::FileSaveAs(bool bCheckResolved
/*=true*/)
1345 if (bCheckResolved
&& HasConflictsWontKeep())
1349 if(!TryGetFileName(fileName
))
1356 void CMainFrame::OnUpdateFileSave(CCmdUI
*pCmdUI
)
1358 BOOL bEnable
= FALSE
;
1359 if (m_Data
.m_mergedFile
.InUse())
1361 if (IsViewGood(m_pwndBottomView
)&&(m_pwndBottomView
->m_pViewData
))
1363 else if ( (IsViewGood(m_pwndRightView
)&&(m_pwndRightView
->m_pViewData
)) &&
1364 (m_pwndRightView
->IsModified() || (m_Data
.m_yourFile
.GetWindowName().Right(9).Compare(_T(": patched"))==0)) )
1367 pCmdUI
->Enable(bEnable
);
1370 void CMainFrame::OnUpdateFileSaveAs(CCmdUI
*pCmdUI
)
1372 BOOL bEnable
= FALSE
;
1373 if (IsViewGood(m_pwndBottomView
)&&(m_pwndBottomView
->m_pViewData
))
1375 else if (IsViewGood(m_pwndRightView
)&&(m_pwndRightView
->m_pViewData
))
1377 pCmdUI
->Enable(bEnable
);
1380 void CMainFrame::OnUpdateViewOnewaydiff(CCmdUI
*pCmdUI
)
1382 pCmdUI
->SetCheck(!m_bOneWay
);
1383 BOOL bEnable
= TRUE
;
1384 if (IsViewGood(m_pwndBottomView
))
1388 pCmdUI
->Enable(bEnable
);
1391 void CMainFrame::OnViewOptions()
1394 sTemp
.LoadString(IDS_SETTINGSTITLE
);
1395 CSettings
dlg(sTemp
);
1397 if (dlg
.IsReloadNeeded())
1399 if (CheckForSave()==IDCANCEL
)
1401 CDiffColors::GetInstance().LoadRegistry();
1405 CDiffColors::GetInstance().LoadRegistry();
1406 if (m_pwndBottomView
)
1407 m_pwndBottomView
->Invalidate();
1409 m_pwndLeftView
->Invalidate();
1410 if (m_pwndRightView
)
1411 m_pwndRightView
->Invalidate();
1414 void CMainFrame::OnClose()
1417 if (HasUnsavedEdits())
1420 sTemp
.LoadString(IDS_ASKFORSAVE
);
1421 ret
= MessageBox(sTemp
, 0, MB_YESNOCANCEL
| MB_ICONQUESTION
);
1429 if ((ret
== IDNO
)||(ret
== IDYES
))
1433 // before it is destroyed, save the position of the window
1434 wp
.length
= sizeof wp
;
1436 if (GetWindowPlacement(&wp
))
1440 // never restore to Iconic state
1441 wp
.showCmd
= SW_SHOW
;
1443 if ((wp
.flags
& WPF_RESTORETOMAXIMIZED
) != 0)
1444 // if maximized and maybe iconic restore maximized state
1445 wp
.showCmd
= SW_SHOWMAXIMIZED
;
1447 // and write it to the .INI file
1448 WriteWindowPlacement(&wp
);
1454 void CMainFrame::OnActivate(UINT nValue
, CWnd
* /*pwnd*/, BOOL
/*bActivated?*/) {
1455 if (nValue
!= 0) // activated
1459 m_bCheckReload
= TRUE
;
1466 void CMainFrame::OnViewLinedown()
1468 OnViewLineUpDown(1);
1471 void CMainFrame::OnViewLineup()
1473 OnViewLineUpDown(-1);
1476 void CMainFrame::OnViewLineUpDown(int direction
)
1479 m_pwndLeftView
->ScrollToLine(m_pwndLeftView
->m_nTopLine
+direction
);
1480 if (m_pwndRightView
)
1481 m_pwndRightView
->ScrollToLine(m_pwndRightView
->m_nTopLine
+direction
);
1482 if (m_pwndBottomView
)
1483 m_pwndBottomView
->ScrollToLine(m_pwndBottomView
->m_nTopLine
+direction
);
1484 m_wndLocatorBar
.Invalidate();
1485 m_nMoveMovesToIgnore
= MOVESTOIGNORE
;
1488 void CMainFrame::OnViewLineleft()
1490 OnViewLineLeftRight(-1);
1493 void CMainFrame::OnViewLineright()
1495 OnViewLineLeftRight(1);
1498 void CMainFrame::OnViewLineLeftRight(int direction
)
1501 m_pwndLeftView
->ScrollSide(direction
);
1502 if (m_pwndRightView
)
1503 m_pwndRightView
->ScrollSide(direction
);
1504 if (m_pwndBottomView
)
1505 m_pwndBottomView
->ScrollSide(direction
);
1508 void CMainFrame::OnEditUseTheirs()
1510 if (m_pwndBottomView
)
1511 m_pwndBottomView
->UseTheirTextBlock();
1513 void CMainFrame::OnUpdateEditUsetheirblock(CCmdUI
*pCmdUI
)
1515 pCmdUI
->Enable(m_pwndBottomView
&& m_pwndBottomView
->HasSelection());
1518 void CMainFrame::OnEditUseMine()
1520 if (m_pwndBottomView
)
1521 m_pwndBottomView
->UseMyTextBlock();
1523 void CMainFrame::OnUpdateEditUsemyblock(CCmdUI
*pCmdUI
)
1525 OnUpdateEditUsetheirblock(pCmdUI
);
1528 void CMainFrame::OnEditUseTheirsThenMine()
1530 if (m_pwndBottomView
)
1531 m_pwndBottomView
->UseTheirAndYourBlock();
1534 void CMainFrame::OnUpdateEditUsetheirthenmyblock(CCmdUI
*pCmdUI
)
1536 OnUpdateEditUsetheirblock(pCmdUI
);
1539 void CMainFrame::OnEditUseMineThenTheirs()
1541 if (m_pwndBottomView
)
1542 m_pwndBottomView
->UseYourAndTheirBlock();
1545 void CMainFrame::OnUpdateEditUseminethentheirblock(CCmdUI
*pCmdUI
)
1547 OnUpdateEditUsetheirblock(pCmdUI
);
1550 void CMainFrame::OnEditUseleftblock()
1552 if (m_pwndBottomView
->IsWindowVisible())
1553 m_pwndBottomView
->UseRightBlock();
1555 m_pwndRightView
->UseLeftBlock();
1558 void CMainFrame::OnUpdateEditUseleftblock(CCmdUI
*pCmdUI
)
1560 pCmdUI
->Enable(IsViewGood(m_pwndRightView
) && m_pwndRightView
->IsTarget() && m_pwndRightView
->HasSelection());
1563 void CMainFrame::OnUpdateUseBlock(CCmdUI
*pCmdUI
)
1565 pCmdUI
->Enable(TRUE
);
1568 void CMainFrame::OnEditUseleftfile()
1570 if (m_pwndBottomView
->IsWindowVisible())
1571 m_pwndBottomView
->UseRightFile();
1573 m_pwndRightView
->UseLeftFile();
1576 void CMainFrame::OnUpdateEditUseleftfile(CCmdUI
*pCmdUI
)
1578 pCmdUI
->Enable(IsViewGood(m_pwndRightView
) && m_pwndRightView
->IsTarget());
1581 void CMainFrame::OnEditUseblockfromleftbeforeright()
1583 if (m_pwndRightView
)
1584 m_pwndRightView
->UseBothLeftFirst();
1587 void CMainFrame::OnUpdateEditUseblockfromleftbeforeright(CCmdUI
*pCmdUI
)
1589 OnUpdateEditUseleftblock(pCmdUI
);
1592 void CMainFrame::OnEditUseblockfromrightbeforeleft()
1594 if (m_pwndRightView
)
1595 m_pwndRightView
->UseBothRightFirst();
1598 void CMainFrame::OnUpdateEditUseblockfromrightbeforeleft(CCmdUI
*pCmdUI
)
1600 OnUpdateEditUseleftblock(pCmdUI
);
1603 void CMainFrame::OnFileReload()
1605 if (CheckForSave()==IDCANCEL
)
1607 CDiffColors::GetInstance().LoadRegistry();
1611 void CMainFrame::ActivateFrame(int nCmdShow
)
1613 // nCmdShow is the normal show mode this frame should be in
1614 // translate default nCmdShow (-1)
1617 if (!IsWindowVisible())
1618 nCmdShow
= SW_SHOWNORMAL
;
1619 else if (IsIconic())
1620 nCmdShow
= SW_RESTORE
;
1623 // bring to top before showing
1624 BringToTop(nCmdShow
);
1628 // show the window as specified
1631 if ( !ReadWindowPlacement(&wp
) )
1633 ShowWindow(nCmdShow
);
1637 if ( nCmdShow
!= SW_SHOWNORMAL
)
1638 wp
.showCmd
= nCmdShow
;
1640 SetWindowPlacement(&wp
);
1643 // and finally, bring to top after showing
1644 BringToTop(nCmdShow
);
1648 BOOL
CMainFrame::ReadWindowPlacement(WINDOWPLACEMENT
* pwp
)
1650 CRegString placement
= CRegString(_T("Software\\TortoiseGitMerge\\WindowPos"));
1651 CString sPlacement
= placement
;
1652 if (sPlacement
.IsEmpty())
1654 int nRead
= _stscanf_s(sPlacement
, _T("%u,%u,%d,%d,%d,%d,%d,%d,%d,%d"),
1655 &pwp
->flags
, &pwp
->showCmd
,
1656 &pwp
->ptMinPosition
.x
, &pwp
->ptMinPosition
.y
,
1657 &pwp
->ptMaxPosition
.x
, &pwp
->ptMaxPosition
.y
,
1658 &pwp
->rcNormalPosition
.left
, &pwp
->rcNormalPosition
.top
,
1659 &pwp
->rcNormalPosition
.right
, &pwp
->rcNormalPosition
.bottom
);
1662 pwp
->length
= sizeof(WINDOWPLACEMENT
);
1667 void CMainFrame::WriteWindowPlacement(WINDOWPLACEMENT
* pwp
)
1669 CRegString placement
= CRegString(_T("Software\\TortoiseGitMerge\\WindowPos"));
1670 TCHAR szBuffer
[_countof("-32767")*8 + sizeof("65535")*2];
1672 _stprintf_s(szBuffer
, _T("%u,%u,%d,%d,%d,%d,%d,%d,%d,%d"),
1673 pwp
->flags
, pwp
->showCmd
,
1674 pwp
->ptMinPosition
.x
, pwp
->ptMinPosition
.y
,
1675 pwp
->ptMaxPosition
.x
, pwp
->ptMaxPosition
.y
,
1676 pwp
->rcNormalPosition
.left
, pwp
->rcNormalPosition
.top
,
1677 pwp
->rcNormalPosition
.right
, pwp
->rcNormalPosition
.bottom
);
1678 placement
= szBuffer
;
1681 void CMainFrame::OnUpdateMergeMarkasresolved(CCmdUI
*pCmdUI
)
1685 BOOL bEnable
= FALSE
;
1686 if ((!m_bReadOnly
)&&(m_Data
.m_mergedFile
.InUse()))
1688 if (IsViewGood(m_pwndBottomView
)&&(m_pwndBottomView
->m_pViewData
))
1693 pCmdUI
->Enable(bEnable
);
1696 void CMainFrame::OnMergeMarkasresolved()
1698 if(HasConflictsWontKeep())
1701 // now check if the file has already been saved and if not, save it.
1702 if (m_Data
.m_mergedFile
.InUse())
1704 if (IsViewGood(m_pwndBottomView
)&&(m_pwndBottomView
->m_pViewData
))
1707 m_bSaveRequired
= false;
1713 BOOL
CMainFrame::MarkAsResolved()
1717 if (!IsViewGood(m_pwndBottomView
))
1720 CString cmd
= _T("/command:resolve /path:\"");
1721 cmd
+= m_Data
.m_mergedFile
.GetFilename();
1722 cmd
+= _T("\" /closeonend:1 /noquestion /skipcheck /silent");
1726 s
.Format(L
" /resolvemsghwnd:%I64d /resolvemsgwparam:%I64d /resolvemsglparam:%I64d", (__int64
)resolveMsgWnd
, (__int64
)resolveMsgWParam
, (__int64
)resolveMsgLParam
);
1729 if(!CAppUtils::RunTortoiseGitProc(cmd
))
1731 m_bSaveRequired
= false;
1735 void CMainFrame::OnUpdateMergeNextconflict(CCmdUI
*pCmdUI
)
1738 if (HasNextConflict(m_pwndBottomView
))
1740 else if (HasNextConflict(m_pwndRightView
))
1742 else if (HasNextConflict(m_pwndLeftView
))
1744 pCmdUI
->Enable(bShow
);
1747 bool CMainFrame::HasNextConflict(CBaseView
* view
)
1751 if (!view
->IsTarget())
1753 return view
->HasNextConflict();
1756 void CMainFrame::OnUpdateMergePreviousconflict(CCmdUI
*pCmdUI
)
1759 if (HasPrevConflict(m_pwndBottomView
))
1761 else if (HasPrevConflict(m_pwndRightView
))
1763 else if (HasPrevConflict(m_pwndLeftView
))
1765 pCmdUI
->Enable(bShow
);
1768 bool CMainFrame::HasPrevConflict(CBaseView
* view
)
1772 if (!view
->IsTarget())
1774 return view
->HasPrevConflict();
1777 void CMainFrame::OnUpdateNavigateNextdifference(CCmdUI
*pCmdUI
)
1779 CBaseView
* baseView
= GetActiveBaseView();
1782 bShow
= baseView
->HasNextDiff();
1783 pCmdUI
->Enable(bShow
);
1786 void CMainFrame::OnUpdateNavigatePreviousdifference(CCmdUI
*pCmdUI
)
1788 CBaseView
* baseView
= GetActiveBaseView();
1791 bShow
= baseView
->HasPrevDiff();
1792 pCmdUI
->Enable(bShow
);
1795 void CMainFrame::OnUpdateNavigateNextinlinediff(CCmdUI
*pCmdUI
)
1798 if (HasNextInlineDiff(m_pwndBottomView
))
1800 else if (HasNextInlineDiff(m_pwndRightView
))
1802 else if (HasNextInlineDiff(m_pwndLeftView
))
1804 pCmdUI
->Enable(bShow
);
1807 bool CMainFrame::HasNextInlineDiff(CBaseView
* view
)
1811 if (!view
->IsTarget())
1813 return view
->HasNextInlineDiff();
1816 void CMainFrame::OnUpdateNavigatePrevinlinediff(CCmdUI
*pCmdUI
)
1819 if (HasPrevInlineDiff(m_pwndBottomView
))
1821 else if (HasPrevInlineDiff(m_pwndRightView
))
1823 else if (HasPrevInlineDiff(m_pwndLeftView
))
1825 pCmdUI
->Enable(bShow
);
1828 bool CMainFrame::HasPrevInlineDiff(CBaseView
* view
)
1832 if (!view
->IsTarget())
1834 return view
->HasPrevInlineDiff();
1837 void CMainFrame::OnMoving(UINT fwSide
, LPRECT pRect
)
1839 // if the pathfilelist dialog is attached to the mainframe,
1840 // move it along with the mainframe
1841 if (::IsWindow(m_dlgFilePatches
.m_hWnd
))
1844 m_dlgFilePatches
.GetWindowRect(&patchrect
);
1845 if (::IsWindow(m_hWnd
))
1848 GetWindowRect(&thisrect
);
1849 if (patchrect
.right
== thisrect
.left
)
1851 m_dlgFilePatches
.SetWindowPos(NULL
, patchrect
.left
- (thisrect
.left
- pRect
->left
), patchrect
.top
- (thisrect
.top
- pRect
->top
),
1852 0, 0, SWP_NOACTIVATE
| SWP_NOOWNERZORDER
| SWP_NOSIZE
| SWP_NOZORDER
);
1856 __super::OnMoving(fwSide
, pRect
);
1859 void CMainFrame::OnUpdateEditCopy(CCmdUI
*pCmdUI
)
1862 if ((m_pwndBottomView
)&&(m_pwndBottomView
->HasSelection()))
1864 else if ((m_pwndRightView
)&&(m_pwndRightView
->HasSelection()))
1866 else if ((m_pwndLeftView
)&&(m_pwndLeftView
->HasSelection()))
1868 pCmdUI
->Enable(bShow
);
1871 void CMainFrame::OnUpdateEditPaste(CCmdUI
*pCmdUI
)
1873 BOOL bWritable
= FALSE
;
1874 if ((m_pwndBottomView
)&&(m_pwndBottomView
->IsWritable()))
1876 else if ((m_pwndRightView
)&&(m_pwndRightView
->IsWritable()))
1878 else if ((m_pwndLeftView
)&&(m_pwndLeftView
->IsWritable()))
1880 pCmdUI
->Enable(bWritable
&& ::IsClipboardFormatAvailable(CF_TEXT
));
1883 void CMainFrame::OnViewSwitchleft()
1886 if (HasUnsavedEdits())
1889 sTemp
.LoadString(IDS_ASKFORSAVE
);
1890 ret
= MessageBox(sTemp
, 0, MB_YESNOCANCEL
| MB_ICONQUESTION
);
1897 if ((ret
== IDNO
)||(ret
== IDYES
))
1899 CWorkingFile file
= m_Data
.m_baseFile
;
1900 m_Data
.m_baseFile
= m_Data
.m_yourFile
;
1901 m_Data
.m_yourFile
= file
;
1902 if (m_Data
.m_mergedFile
.GetFilename().CompareNoCase(m_Data
.m_yourFile
.GetFilename())==0)
1904 m_Data
.m_mergedFile
= m_Data
.m_baseFile
;
1906 else if (m_Data
.m_mergedFile
.GetFilename().CompareNoCase(m_Data
.m_baseFile
.GetFilename())==0)
1908 m_Data
.m_mergedFile
= m_Data
.m_yourFile
;
1914 void CMainFrame::OnUpdateViewSwitchleft(CCmdUI
*pCmdUI
)
1916 BOOL bEnable
= !IsViewGood(m_pwndBottomView
);
1917 pCmdUI
->Enable(bEnable
);
1920 void CMainFrame::OnUpdateViewShowfilelist(CCmdUI
*pCmdUI
)
1922 BOOL bEnable
= m_dlgFilePatches
.HasFiles();
1923 pCmdUI
->Enable(bEnable
);
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
);
1940 void CMainFrame::OnUpdateEditUndo(CCmdUI
*pCmdUI
)
1942 pCmdUI
->Enable(CUndo::GetInstance().CanUndo());
1945 int CMainFrame::CheckForReload()
1947 static bool bLock
= false; //we don't want to check when activated after MessageBox we just created ... this is simple, but we don't need multithread lock
1953 bool bSourceChanged
=
1954 m_Data
.m_baseFile
.HasSourceFileChanged()
1955 || m_Data
.m_yourFile
.HasSourceFileChanged()
1956 || m_Data
.m_theirFile
.HasSourceFileChanged()
1957 /*|| m_Data.m_mergedFile.HasSourceFileChanged()*/;
1958 if (!bSourceChanged
)
1964 int idsMessage
= HasUnsavedEdits() ? IDS_WARNMODIFIEDOUTSIDELOOSECHANGES
: IDS_WARNMODIFIEDOUTSIDE
;
1965 UINT ret
= CMessageBox::Show(m_hWnd
, idsMessage
, IDS_APPNAME
, MB_YESNO
| MB_ICONQUESTION
);
1969 CDiffColors::GetInstance().LoadRegistry();
1974 if (IsViewGood(m_pwndBottomView
)) // three pane view
1976 /*if (m_Data.m_sourceFile.HasSourceFileChanged())
1977 m_pwndBottomView->SetModified();
1978 if (m_Data.m_mergedFile.HasSourceFileChanged())
1979 m_pwndBottomView->SetModified();//*/
1980 if (m_Data
.m_yourFile
.HasSourceFileChanged())
1981 m_pwndRightView
->SetModified();
1982 if (m_Data
.m_theirFile
.HasSourceFileChanged())
1983 m_pwndLeftView
->SetModified();
1985 else if (IsViewGood(m_pwndRightView
)) // two pane view
1987 if (m_Data
.m_baseFile
.HasSourceFileChanged())
1988 m_pwndLeftView
->SetModified();
1989 if (m_Data
.m_yourFile
.HasSourceFileChanged())
1990 m_pwndRightView
->SetModified();
1994 if (m_Data
.m_yourFile
.HasSourceFileChanged())
1995 m_pwndLeftView
->SetModified();
1998 // no reload just store updated file time
1999 m_Data
.m_baseFile
.StoreFileAttributes();
2000 m_Data
.m_theirFile
.StoreFileAttributes();
2001 m_Data
.m_yourFile
.StoreFileAttributes();
2002 //m_Data.m_mergedFile.StoreFileAttributes();
2008 int CMainFrame::CheckForSave()
2011 if (HasUnsavedEdits())
2014 sTemp
.LoadString(IDS_WARNMODIFIEDLOOSECHANGES
);
2015 ret
= MessageBox(sTemp
, 0, MB_YESNOCANCEL
| MB_ICONQUESTION
);
2026 bool CMainFrame::HasUnsavedEdits() const
2028 return HasUnsavedEdits(m_pwndBottomView
) || HasUnsavedEdits(m_pwndRightView
) || m_bSaveRequired
;
2031 bool CMainFrame::HasUnsavedEdits(const CBaseView
* view
)
2035 return view
->IsModified();
2038 bool CMainFrame::IsViewGood(const CBaseView
* view
)
2040 return CBaseView::IsViewGood(view
);
2043 void CMainFrame::OnViewInlinediffword()
2045 m_bInlineWordDiff
= !m_bInlineWordDiff
;
2048 m_pwndLeftView
->SetInlineWordDiff(m_bInlineWordDiff
);
2049 m_pwndLeftView
->BuildAllScreen2ViewVector();
2050 m_pwndLeftView
->DocumentUpdated();
2052 if (m_pwndRightView
)
2054 m_pwndRightView
->SetInlineWordDiff(m_bInlineWordDiff
);
2055 m_pwndRightView
->BuildAllScreen2ViewVector();
2056 m_pwndRightView
->DocumentUpdated();
2058 if (m_pwndBottomView
)
2060 m_pwndBottomView
->SetInlineWordDiff(m_bInlineWordDiff
);
2061 m_pwndBottomView
->BuildAllScreen2ViewVector();
2062 m_pwndBottomView
->DocumentUpdated();
2064 m_wndLineDiffBar
.DocumentUpdated();
2067 void CMainFrame::OnUpdateViewInlinediffword(CCmdUI
*pCmdUI
)
2069 pCmdUI
->Enable(m_bInlineDiff
&& IsViewGood(m_pwndLeftView
) && IsViewGood(m_pwndRightView
));
2070 pCmdUI
->SetCheck(m_bInlineWordDiff
);
2073 void CMainFrame::OnViewInlinediff()
2075 m_bInlineDiff
= !m_bInlineDiff
;
2078 m_pwndLeftView
->SetInlineDiff(m_bInlineDiff
);
2079 m_pwndLeftView
->BuildAllScreen2ViewVector();
2080 m_pwndLeftView
->DocumentUpdated();
2082 if (m_pwndRightView
)
2084 m_pwndRightView
->SetInlineDiff(m_bInlineDiff
);
2085 m_pwndRightView
->BuildAllScreen2ViewVector();
2086 m_pwndRightView
->DocumentUpdated();
2088 if (m_pwndBottomView
)
2090 m_pwndBottomView
->SetInlineDiff(m_bInlineDiff
);
2091 m_pwndBottomView
->BuildAllScreen2ViewVector();
2092 m_pwndBottomView
->DocumentUpdated();
2094 m_wndLineDiffBar
.DocumentUpdated();
2097 void CMainFrame::OnUpdateViewInlinediff(CCmdUI
*pCmdUI
)
2099 pCmdUI
->Enable(IsViewGood(m_pwndLeftView
) && IsViewGood(m_pwndRightView
));
2100 pCmdUI
->SetCheck(m_bInlineDiff
);
2103 void CMainFrame::OnUpdateEditCreateunifieddifffile(CCmdUI
*pCmdUI
)
2105 // "create unified diff file" is only available if two files
2106 // are diffed, not three.
2107 bool bEnabled
= true;
2108 if (!IsViewGood(m_pwndLeftView
))
2110 else if (!IsViewGood(m_pwndRightView
))
2112 else if (IsViewGood(m_pwndBottomView
)) //no negation here
2114 pCmdUI
->Enable(bEnabled
);
2117 void CMainFrame::OnEditCreateunifieddifffile()
2119 CString origFile
, modifiedFile
;
2120 // the original file is the one on the left
2122 origFile
= m_pwndLeftView
->m_sFullFilePath
;
2123 if (m_pwndRightView
)
2124 modifiedFile
= m_pwndRightView
->m_sFullFilePath
;
2125 if (origFile
.IsEmpty() || modifiedFile
.IsEmpty())
2129 if(!TryGetFileName(outputFile
))
2132 CAppUtils::CreateUnifiedDiff(origFile
, modifiedFile
, outputFile
, true);
2135 void CMainFrame::OnUpdateViewLinediffbar(CCmdUI
*pCmdUI
)
2137 pCmdUI
->SetCheck(m_bLineDiff
);
2141 void CMainFrame::OnViewLinediffbar()
2143 m_bLineDiff
= !m_bLineDiff
;
2144 m_wndLineDiffBar
.ShowPane(m_bLineDiff
, false, true);
2145 m_wndLineDiffBar
.DocumentUpdated();
2146 m_wndLocatorBar
.ShowPane(m_bLocatorBar
, false, true);
2147 m_wndLocatorBar
.DocumentUpdated();
2150 void CMainFrame::OnUpdateViewLocatorbar(CCmdUI
*pCmdUI
)
2152 pCmdUI
->SetCheck(m_bLocatorBar
);
2156 void CMainFrame::OnViewLocatorbar()
2158 m_bLocatorBar
= !m_bLocatorBar
;
2159 m_wndLocatorBar
.ShowPane(m_bLocatorBar
, false, true);
2160 m_wndLocatorBar
.DocumentUpdated();
2161 m_wndLineDiffBar
.ShowPane(m_bLineDiff
, false, true);
2162 m_wndLineDiffBar
.DocumentUpdated();
2165 void CMainFrame::OnViewComparewhitespaces()
2167 if (CheckForSave()==IDCANCEL
)
2169 CRegDWORD regIgnoreWS
= CRegDWORD(_T("Software\\TortoiseGitMerge\\IgnoreWS"));
2174 void CMainFrame::OnUpdateViewComparewhitespaces(CCmdUI
*pCmdUI
)
2176 CRegDWORD regIgnoreWS
= CRegDWORD(_T("Software\\TortoiseGitMerge\\IgnoreWS"));
2177 DWORD dwIgnoreWS
= regIgnoreWS
;
2178 pCmdUI
->SetCheck(dwIgnoreWS
== 0);
2181 void CMainFrame::OnViewIgnorewhitespacechanges()
2183 if (CheckForSave()==IDCANCEL
)
2185 CRegDWORD regIgnoreWS
= CRegDWORD(_T("Software\\TortoiseGitMerge\\IgnoreWS"));
2190 void CMainFrame::OnUpdateViewIgnorewhitespacechanges(CCmdUI
*pCmdUI
)
2192 CRegDWORD regIgnoreWS
= CRegDWORD(_T("Software\\TortoiseGitMerge\\IgnoreWS"));
2193 DWORD dwIgnoreWS
= regIgnoreWS
;
2194 pCmdUI
->SetCheck(dwIgnoreWS
== 2);
2197 void CMainFrame::OnViewIgnoreallwhitespacechanges()
2199 if (CheckForSave()==IDCANCEL
)
2201 CRegDWORD regIgnoreWS
= CRegDWORD(_T("Software\\TortoiseGitMerge\\IgnoreWS"));
2206 void CMainFrame::OnUpdateViewIgnoreallwhitespacechanges(CCmdUI
*pCmdUI
)
2208 CRegDWORD regIgnoreWS
= CRegDWORD(_T("Software\\TortoiseGitMerge\\IgnoreWS"));
2209 DWORD dwIgnoreWS
= regIgnoreWS
;
2210 pCmdUI
->SetCheck(dwIgnoreWS
== 1);
2213 void CMainFrame::OnViewMovedBlocks()
2215 m_bViewMovedBlocks
= !(DWORD
)m_regViewModedBlocks
;
2216 m_regViewModedBlocks
= m_bViewMovedBlocks
;
2220 void CMainFrame::OnUpdateViewMovedBlocks(CCmdUI
*pCmdUI
)
2222 pCmdUI
->SetCheck(m_bViewMovedBlocks
);
2223 BOOL bEnable
= TRUE
;
2224 if (IsViewGood(m_pwndBottomView
))
2228 pCmdUI
->Enable(bEnable
);
2231 bool CMainFrame::HasConflictsWontKeep()
2233 const int nConflictLine
= CheckResolved();
2234 if (nConflictLine
< 0)
2238 sTemp
.Format(IDS_ERR_MAINFRAME_FILEHASCONFLICTS
, m_pwndBottomView
->m_pViewData
->GetLineNumber(nConflictLine
)+1);
2239 if (MessageBox(sTemp
, 0, MB_ICONERROR
| MB_YESNO
)==IDYES
)
2242 if (m_pwndBottomView
)
2243 m_pwndBottomView
->GoToLine(nConflictLine
);
2247 bool CMainFrame::TryGetFileName(CString
& result
)
2249 return CCommonAppUtils::FileOpenSave(result
, NULL
, IDS_SAVEASTITLE
, IDS_COMMONFILEFILTER
, false, m_hWnd
);
2252 CBaseView
* CMainFrame::GetActiveBaseView() const
2254 CView
* activeView
= GetActiveView();
2255 CBaseView
* activeBase
= dynamic_cast<CBaseView
*>( activeView
);
2259 void CMainFrame::SetWindowTitle()
2261 // try to find a suitable window title
2262 CString sYour
= m_Data
.m_yourFile
.GetDescriptiveName();
2263 if (sYour
.Find(_T(" - "))>=0)
2264 sYour
= sYour
.Left(sYour
.Find(_T(" - ")));
2265 if (sYour
.Find(_T(" : "))>=0)
2266 sYour
= sYour
.Left(sYour
.Find(_T(" : ")));
2267 CString sTheir
= m_Data
.m_theirFile
.GetDescriptiveName();
2268 if (sTheir
.IsEmpty())
2269 sTheir
= m_Data
.m_baseFile
.GetDescriptiveName();
2270 if (sTheir
.Find(_T(" - "))>=0)
2271 sTheir
= sTheir
.Left(sTheir
.Find(_T(" - ")));
2272 if (sTheir
.Find(_T(" : "))>=0)
2273 sTheir
= sTheir
.Left(sTheir
.Find(_T(" : ")));
2275 if (!sYour
.IsEmpty() && !sTheir
.IsEmpty())
2277 if (sYour
.CompareNoCase(sTheir
)==0)
2278 SetWindowText(sYour
+ _T(" - TortoiseGitMerge"));
2279 else if ((sYour
.GetLength() < 10) &&
2280 (sTheir
.GetLength() < 10))
2281 SetWindowText(sYour
+ _T(" - ") + sTheir
+ _T(" - TortoiseGitMerge"));
2284 // we have two very long descriptive texts here, which
2285 // means we have to find a way to use them as a window
2286 // title in a shorter way.
2287 // for simplicity, we just use the one from "yourfile"
2288 SetWindowText(sYour
+ _T(" - TortoiseGitMerge"));
2291 else if (!sYour
.IsEmpty())
2292 SetWindowText(sYour
+ _T(" - TortoiseGitMerge"));
2293 else if (!sTheir
.IsEmpty())
2294 SetWindowText(sTheir
+ _T(" - TortoiseGitMerge"));
2296 SetWindowText(L
"TortoiseGitMerge");