Add flag indication user can change Read only mode for view
[TortoiseGit.git] / src / TortoiseMerge / MainFrm.cpp
blob7d2be2d7c02e390bba7113d9b3e05f8f66a7d191
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.
21 #include "stdafx.h"
22 #include "TortoiseMerge.h"
23 #include "CustomMFCRibbonButton.h"
24 #include "OpenDlg.h"
25 #include "SysProgressDlg.h"
26 #include "Settings.h"
27 #include "MessageBox.h"
28 #include "AppUtils.h"
29 #include "PathUtils.h"
30 #include "MainFrm.h"
31 #include "LeftView.h"
32 #include "RightView.h"
33 #include "BottomView.h"
34 #include "DiffColors.h"
35 #include "mainfrm.h"
36 #include "SelectFileFilter.h"
37 #include "FormatMessageWrapper.h"
38 #include "TaskbarUUID.h"
39 #include "git2.h"
41 #ifdef _DEBUG
42 #define new DEBUG_NEW
43 #endif
45 CCustomMFCRibbonButton button1;
47 // CMainFrame
48 const UINT TaskBarButtonCreated = RegisterWindowMessage(L"TaskbarButtonCreated");
50 IMPLEMENT_DYNCREATE(CMainFrame, CFrameWndEx)
52 BEGIN_MESSAGE_MAP(CMainFrame, CFrameWndEx)
53 ON_WM_CREATE()
54 ON_COMMAND_RANGE(ID_VIEW_APPLOOK_WIN7, ID_VIEW_APPLOOK_OFF_2007_AQUA, &CMainFrame::OnApplicationLook)
55 ON_UPDATE_COMMAND_UI_RANGE(IDC_STYLEBUTTON, ID_VIEW_APPLOOK_OFF_2007_AQUA, &CMainFrame::OnUpdateApplicationLook)
56 // Global help commands
57 ON_COMMAND(ID_HELP_FINDER, CFrameWndEx::OnHelpFinder)
58 ON_COMMAND(ID_HELP, CFrameWndEx::OnHelp)
59 ON_COMMAND(ID_CONTEXT_HELP, CFrameWndEx::OnContextHelp)
60 ON_COMMAND(ID_DEFAULT_HELP, CFrameWndEx::OnHelpFinder)
61 ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
62 ON_COMMAND(ID_VIEW_WHITESPACES, OnViewWhitespaces)
63 ON_WM_SIZE()
64 ON_COMMAND(ID_FILE_SAVE, OnFileSave)
65 ON_COMMAND(ID_FILE_SAVE_AS, OnFileSaveAs)
66 ON_UPDATE_COMMAND_UI(ID_FILE_SAVE, OnUpdateFileSave)
67 ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_AS, OnUpdateFileSaveAs)
68 ON_COMMAND(ID_VIEW_ONEWAYDIFF, OnViewOnewaydiff)
69 ON_UPDATE_COMMAND_UI(ID_VIEW_ONEWAYDIFF, OnUpdateViewOnewaydiff)
70 ON_UPDATE_COMMAND_UI(ID_VIEW_WHITESPACES, OnUpdateViewWhitespaces)
71 ON_COMMAND(ID_VIEW_OPTIONS, OnViewOptions)
72 ON_WM_CLOSE()
73 ON_WM_ACTIVATE()
74 ON_COMMAND(ID_FILE_RELOAD, OnFileReload)
75 ON_COMMAND(ID_VIEW_LINEDOWN, OnViewLinedown)
76 ON_COMMAND(ID_VIEW_LINEUP, OnViewLineup)
77 ON_COMMAND(ID_VIEW_MOVEDBLOCKS, OnViewMovedBlocks)
78 ON_UPDATE_COMMAND_UI(ID_VIEW_MOVEDBLOCKS, OnUpdateViewMovedBlocks)
79 ON_UPDATE_COMMAND_UI(ID_EDIT_MARKASRESOLVED, OnUpdateMergeMarkasresolved)
80 ON_COMMAND(ID_EDIT_MARKASRESOLVED, OnMergeMarkasresolved)
81 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_NEXTCONFLICT, OnUpdateMergeNextconflict)
82 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_PREVIOUSCONFLICT, OnUpdateMergePreviousconflict)
83 ON_WM_MOVE()
84 ON_WM_MOVING()
85 ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateEditCopy)
86 ON_COMMAND(ID_VIEW_SWITCHLEFT, OnViewSwitchleft)
87 ON_UPDATE_COMMAND_UI(ID_VIEW_SWITCHLEFT, OnUpdateViewSwitchleft)
88 ON_COMMAND(ID_VIEW_LINELEFT, &CMainFrame::OnViewLineleft)
89 ON_COMMAND(ID_VIEW_LINERIGHT, &CMainFrame::OnViewLineright)
90 ON_UPDATE_COMMAND_UI(ID_VIEW_SHOWFILELIST, &CMainFrame::OnUpdateViewShowfilelist)
91 ON_COMMAND(ID_VIEW_SHOWFILELIST, &CMainFrame::OnViewShowfilelist)
92 ON_COMMAND(ID_EDIT_USETHEIRBLOCK, &CMainFrame::OnEditUseTheirs)
93 ON_COMMAND(ID_EDIT_USEMYBLOCK, &CMainFrame::OnEditUseMine)
94 ON_COMMAND(ID_EDIT_USETHEIRTHENMYBLOCK, &CMainFrame::OnEditUseTheirsThenMine)
95 ON_COMMAND(ID_EDIT_USEMINETHENTHEIRBLOCK, &CMainFrame::OnEditUseMineThenTheirs)
96 ON_COMMAND(ID_EDIT_UNDO, &CMainFrame::OnEditUndo)
97 ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, &CMainFrame::OnUpdateEditUndo)
98 ON_UPDATE_COMMAND_UI(ID_EDIT_USEMINETHENTHEIRBLOCK, &CMainFrame::OnUpdateEditUseminethentheirblock)
99 ON_UPDATE_COMMAND_UI(ID_EDIT_USEMYBLOCK, &CMainFrame::OnUpdateEditUsemyblock)
100 ON_UPDATE_COMMAND_UI(ID_EDIT_USETHEIRBLOCK, &CMainFrame::OnUpdateEditUsetheirblock)
101 ON_UPDATE_COMMAND_UI(ID_EDIT_USETHEIRTHENMYBLOCK, &CMainFrame::OnUpdateEditUsetheirthenmyblock)
102 ON_COMMAND(ID_VIEW_INLINEDIFFWORD, &CMainFrame::OnViewInlinediffword)
103 ON_UPDATE_COMMAND_UI(ID_VIEW_INLINEDIFFWORD, &CMainFrame::OnUpdateViewInlinediffword)
104 ON_COMMAND(ID_VIEW_INLINEDIFF, &CMainFrame::OnViewInlinediff)
105 ON_UPDATE_COMMAND_UI(ID_VIEW_INLINEDIFF, &CMainFrame::OnUpdateViewInlinediff)
106 ON_UPDATE_COMMAND_UI(ID_EDIT_CREATEUNIFIEDDIFFFILE, &CMainFrame::OnUpdateEditCreateunifieddifffile)
107 ON_COMMAND(ID_EDIT_CREATEUNIFIEDDIFFFILE, &CMainFrame::OnEditCreateunifieddifffile)
108 ON_UPDATE_COMMAND_UI(ID_VIEW_LINEDIFFBAR, &CMainFrame::OnUpdateViewLinediffbar)
109 ON_COMMAND(ID_VIEW_LINEDIFFBAR, &CMainFrame::OnViewLinediffbar)
110 ON_UPDATE_COMMAND_UI(ID_VIEW_LOCATORBAR, &CMainFrame::OnUpdateViewLocatorbar)
111 ON_COMMAND(ID_VIEW_LOCATORBAR, &CMainFrame::OnViewLocatorbar)
112 ON_COMMAND(ID_EDIT_USELEFTBLOCK, &CMainFrame::OnEditUseleftblock)
113 ON_UPDATE_COMMAND_UI(ID_USEBLOCKS, &CMainFrame::OnUpdateUseBlock)
114 ON_UPDATE_COMMAND_UI(ID_EDIT_USELEFTBLOCK, &CMainFrame::OnUpdateEditUseleftblock)
115 ON_COMMAND(ID_EDIT_USELEFTFILE, &CMainFrame::OnEditUseleftfile)
116 ON_UPDATE_COMMAND_UI(ID_EDIT_USELEFTFILE, &CMainFrame::OnUpdateEditUseleftfile)
117 ON_COMMAND(ID_EDIT_USEBLOCKFROMLEFTBEFORERIGHT, &CMainFrame::OnEditUseblockfromleftbeforeright)
118 ON_UPDATE_COMMAND_UI(ID_EDIT_USEBLOCKFROMLEFTBEFORERIGHT, &CMainFrame::OnUpdateEditUseblockfromleftbeforeright)
119 ON_COMMAND(ID_EDIT_USEBLOCKFROMRIGHTBEFORELEFT, &CMainFrame::OnEditUseblockfromrightbeforeleft)
120 ON_UPDATE_COMMAND_UI(ID_EDIT_USEBLOCKFROMRIGHTBEFORELEFT, &CMainFrame::OnUpdateEditUseblockfromrightbeforeleft)
121 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_NEXTDIFFERENCE, &CMainFrame::OnUpdateNavigateNextdifference)
122 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_PREVIOUSDIFFERENCE, &CMainFrame::OnUpdateNavigatePreviousdifference)
123 ON_COMMAND(ID_VIEW_COLLAPSED, &CMainFrame::OnViewCollapsed)
124 ON_UPDATE_COMMAND_UI(ID_VIEW_COLLAPSED, &CMainFrame::OnUpdateViewCollapsed)
125 ON_COMMAND(ID_VIEW_COMPAREWHITESPACES, &CMainFrame::OnViewComparewhitespaces)
126 ON_UPDATE_COMMAND_UI(ID_VIEW_COMPAREWHITESPACES, &CMainFrame::OnUpdateViewComparewhitespaces)
127 ON_COMMAND(ID_VIEW_IGNOREWHITESPACECHANGES, &CMainFrame::OnViewIgnorewhitespacechanges)
128 ON_UPDATE_COMMAND_UI(ID_VIEW_IGNOREWHITESPACECHANGES, &CMainFrame::OnUpdateViewIgnorewhitespacechanges)
129 ON_COMMAND(ID_VIEW_IGNOREALLWHITESPACECHANGES, &CMainFrame::OnViewIgnoreallwhitespacechanges)
130 ON_UPDATE_COMMAND_UI(ID_VIEW_IGNOREALLWHITESPACECHANGES, &CMainFrame::OnUpdateViewIgnoreallwhitespacechanges)
131 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_NEXTINLINEDIFF, &CMainFrame::OnUpdateNavigateNextinlinediff)
132 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_PREVINLINEDIFF, &CMainFrame::OnUpdateNavigatePrevinlinediff)
133 ON_COMMAND(ID_VIEW_WRAPLONGLINES, &CMainFrame::OnViewWraplonglines)
134 ON_UPDATE_COMMAND_UI(ID_VIEW_WRAPLONGLINES, &CMainFrame::OnUpdateViewWraplonglines)
135 ON_REGISTERED_MESSAGE( TaskBarButtonCreated, CMainFrame::OnTaskbarButtonCreated )
136 ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, &CMainFrame::OnUpdateEditPaste)
137 END_MESSAGE_MAP()
139 static UINT indicators[] =
141 ID_SEPARATOR, // status line indicator
142 ID_INDICATOR_LEFTVIEW,
143 ID_INDICATOR_RIGHTVIEW,
144 ID_INDICATOR_BOTTOMVIEW,
145 ID_INDICATOR_CAPS,
146 ID_INDICATOR_NUM,
150 // CMainFrame construction/destruction
152 CMainFrame::CMainFrame()
153 : m_bInitSplitter(FALSE)
154 , m_bReversedPatch(FALSE)
155 , m_bHasConflicts(false)
156 , m_bInlineWordDiff(true)
157 , m_bLineDiff(true)
158 , m_bLocatorBar(true)
159 , m_nMoveMovesToIgnore(0)
160 , m_pwndLeftView(NULL)
161 , m_pwndRightView(NULL)
162 , m_pwndBottomView(NULL)
163 , m_bReadOnly(false)
164 , m_bBlame(false)
165 , m_bCheckReload(false)
166 , m_bSaveRequired(false)
167 , resolveMsgWnd(0)
168 , resolveMsgWParam(0)
169 , resolveMsgLParam(0)
170 , m_regWrapLines(L"Software\\TortoiseGitMerge\\WrapLines", 0)
171 , m_regViewModedBlocks(L"Software\\TortoiseGitMerge\\ViewMovedBlocks", TRUE)
172 , m_regOneWay(L"Software\\TortoiseGitMerge\\OnePane")
173 , m_regCollapsed(L"Software\\TortoiseGitMerge\\Collapsed", 0)
174 , m_regInlineDiff(L"Software\\TortoiseGitMerge\\DisplayBinDiff", TRUE)
175 , m_regUseRibbons(L"Software\\TortoiseGitMerge\\UseRibbons", TRUE)
177 m_bOneWay = (0 != ((DWORD)m_regOneWay));
178 theApp.m_nAppLook = theApp.GetInt(_T("ApplicationLook"), ID_VIEW_APPLOOK_VS_2005);
179 m_bCollapsed = !!(DWORD)m_regCollapsed;
180 m_bViewMovedBlocks = !!(DWORD)m_regViewModedBlocks;
181 m_bWrapLines = !!(DWORD)m_regWrapLines;
182 m_bInlineDiff = !!m_regInlineDiff;
183 m_bUseRibbons = !!m_regUseRibbons;
184 CMFCVisualManagerWindows::m_b3DTabsXPTheme = TRUE;
187 CMainFrame::~CMainFrame()
191 LRESULT CMainFrame::OnTaskbarButtonCreated(WPARAM /*wParam*/, LPARAM /*lParam*/)
193 SetUUIDOverlayIcon(m_hWnd);
194 return 0;
198 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
200 if (CFrameWndEx::OnCreate(lpCreateStruct) == -1)
201 return -1;
203 OnApplicationLook(theApp.m_nAppLook);
205 if (m_bUseRibbons)
207 m_wndRibbonBar.Create(this);
208 m_wndRibbonBar.LoadFromResource(IDR_RIBBON);
210 // enable the dialog launch button on the view panel
211 CMFCRibbonCategory * pMainCat = m_wndRibbonBar.GetCategory(1);
212 if (pMainCat)
214 CMFCRibbonPanel * pPanel = pMainCat->GetPanel(3);
215 if (pPanel)
216 pPanel->EnableLaunchButton(ID_VIEW_OPTIONS);
218 // now replace all buttons with our custom button class
219 for (int i = 0; i < m_wndRibbonBar.GetCategoryCount(); ++i)
221 CMFCRibbonCategory * pCat = m_wndRibbonBar.GetCategory(i);
222 for (int j = 0; j < pCat->GetPanelCount(); ++j)
224 CMFCRibbonPanel * pPanel = pCat->GetPanel(j);
225 CList<UINT, UINT> lstItems;
226 pPanel->GetItemIDsList(lstItems);
227 while (!lstItems.IsEmpty())
229 UINT id = lstItems.GetHead();
230 lstItems.RemoveHead();
231 CMFCRibbonButton * pButton = dynamic_cast<CMFCRibbonButton*>(pPanel->FindByID(id));
232 if (pButton)
234 CCustomMFCRibbonButton * c = new CCustomMFCRibbonButton(id, pButton->GetText());
235 pPanel->ReplaceByID(id, c);
241 else
243 if (!m_wndMenuBar.Create(this))
245 TRACE0("Failed to create menubar\n");
246 return -1; // fail to create
248 m_wndMenuBar.SetPaneStyle(m_wndMenuBar.GetPaneStyle() | CBRS_SIZE_DYNAMIC | CBRS_TOOLTIPS | CBRS_FLYBY);
250 // prevent the menu bar from taking the focus on activation
251 CMFCPopupMenu::SetForceMenuFocus(FALSE);
252 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))
254 TRACE0("Failed to create toolbar\n");
255 return -1; // fail to create
257 m_wndToolBar.SetWindowText(_T("Main"));
259 if (!m_wndStatusBar.Create(this) ||
260 !m_wndStatusBar.SetIndicators(indicators,
261 _countof(indicators)))
263 TRACE0("Failed to create status bar\n");
264 return -1; // fail to create
267 if (!m_wndLocatorBar.Create(this, IDD_DIFFLOCATOR,
268 CBRS_ALIGN_LEFT | CBRS_SIZE_FIXED, ID_VIEW_LOCATORBAR))
270 TRACE0("Failed to create dialogbar\n");
271 return -1; // fail to create
273 if (!m_wndLineDiffBar.Create(this, IDD_LINEDIFF,
274 CBRS_ALIGN_BOTTOM | CBRS_SIZE_FIXED, ID_VIEW_LINEDIFFBAR))
276 TRACE0("Failed to create dialogbar\n");
277 return -1; // fail to create
279 m_wndLocatorBar.m_pMainFrm = this;
280 m_wndLineDiffBar.m_pMainFrm = this;
282 EnableDocking(CBRS_ALIGN_ANY);
283 if (!m_bUseRibbons)
285 m_wndMenuBar.EnableDocking(CBRS_ALIGN_TOP);
286 m_wndToolBar.EnableDocking(CBRS_ALIGN_TOP);
287 DockPane(&m_wndMenuBar);
288 DockPane(&m_wndToolBar);
290 DockPane(&m_wndLocatorBar);
291 DockPane(&m_wndLineDiffBar);
292 ShowPane(&m_wndLocatorBar, true, false, true);
293 ShowPane(&m_wndLineDiffBar, true, false, true);
295 m_wndLocatorBar.EnableGripper(FALSE);
296 m_wndLineDiffBar.EnableGripper(FALSE);
298 return 0;
301 BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
303 if( !CFrameWndEx::PreCreateWindow(cs) )
304 return FALSE;
305 return TRUE;
308 void CMainFrame::OnApplicationLook(UINT id)
310 CWaitCursor wait;
312 theApp.m_nAppLook = id;
314 switch (theApp.m_nAppLook)
316 case ID_VIEW_APPLOOK_WIN_2000:
317 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManager));
318 m_wndRibbonBar.SetWindows7Look(FALSE);
319 break;
321 case ID_VIEW_APPLOOK_OFF_XP:
322 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOfficeXP));
323 m_wndRibbonBar.SetWindows7Look(FALSE);
324 break;
326 case ID_VIEW_APPLOOK_WIN_XP:
327 CMFCVisualManagerWindows::m_b3DTabsXPTheme = TRUE;
328 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));
329 m_wndRibbonBar.SetWindows7Look(FALSE);
330 break;
332 case ID_VIEW_APPLOOK_OFF_2003:
333 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2003));
334 CDockingManager::SetDockingMode(DT_SMART);
335 m_wndRibbonBar.SetWindows7Look(FALSE);
336 break;
338 case ID_VIEW_APPLOOK_VS_2005:
339 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerVS2005));
340 CDockingManager::SetDockingMode(DT_SMART);
341 m_wndRibbonBar.SetWindows7Look(FALSE);
342 break;
344 case ID_VIEW_APPLOOK_VS_2008:
345 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerVS2008));
346 CDockingManager::SetDockingMode(DT_SMART);
347 m_wndRibbonBar.SetWindows7Look(FALSE);
348 break;
350 case ID_VIEW_APPLOOK_WIN7:
351 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows7));
352 CDockingManager::SetDockingMode(DT_SMART);
353 m_wndRibbonBar.SetWindows7Look(TRUE);
354 break;
356 default:
357 switch (theApp.m_nAppLook)
359 case ID_VIEW_APPLOOK_OFF_2007_BLUE:
360 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_LunaBlue);
361 break;
363 case ID_VIEW_APPLOOK_OFF_2007_BLACK:
364 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_ObsidianBlack);
365 break;
367 case ID_VIEW_APPLOOK_OFF_2007_SILVER:
368 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_Silver);
369 break;
371 case ID_VIEW_APPLOOK_OFF_2007_AQUA:
372 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_Aqua);
373 break;
376 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2007));
377 CDockingManager::SetDockingMode(DT_SMART);
378 m_wndRibbonBar.SetWindows7Look(FALSE);
381 RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_UPDATENOW | RDW_FRAME | RDW_ERASE);
383 theApp.WriteInt(_T("ApplicationLook"), theApp.m_nAppLook);
386 void CMainFrame::OnUpdateApplicationLook(CCmdUI* pCmdUI)
388 pCmdUI->Enable();
389 pCmdUI->SetRadio(theApp.m_nAppLook == pCmdUI->m_nID);
393 // CMainFrame diagnostics
395 #ifdef _DEBUG
396 void CMainFrame::AssertValid() const
398 CFrameWndEx::AssertValid();
401 void CMainFrame::Dump(CDumpContext& dc) const
403 CFrameWndEx::Dump(dc);
406 #endif //_DEBUG
409 // CMainFrame message handlers
412 BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT /*lpcs*/, CCreateContext* pContext)
414 CRect cr;
415 GetClientRect( &cr);
418 // split into three panes:
419 // -------------
420 // | | |
421 // | | |
422 // |------------
423 // | |
424 // | |
425 // |------------
427 // create a splitter with 2 rows, 1 column
428 if (!m_wndSplitter.CreateStatic(this, 2, 1))
430 TRACE0("Failed to CreateStaticSplitter\n");
431 return FALSE;
434 // add the second splitter pane - which is a nested splitter with 2 columns
435 if (!m_wndSplitter2.CreateStatic(
436 &m_wndSplitter, // our parent window is the first splitter
437 1, 2, // the new splitter is 1 row, 2 columns
438 WS_CHILD | WS_VISIBLE | WS_BORDER, // style, WS_BORDER is needed
439 m_wndSplitter.IdFromRowCol(0, 0)
440 // new splitter is in the first row, 1st column of first splitter
443 TRACE0("Failed to create nested splitter\n");
444 return FALSE;
446 // add the first splitter pane - the default view in row 0
447 if (!m_wndSplitter.CreateView(1, 0,
448 RUNTIME_CLASS(CBottomView), CSize(cr.Width(), cr.Height()), pContext))
450 TRACE0("Failed to create first pane\n");
451 return FALSE;
453 m_pwndBottomView = (CBottomView *)m_wndSplitter.GetPane(1,0);
454 m_pwndBottomView->m_pwndLocator = &m_wndLocatorBar;
455 m_pwndBottomView->m_pwndLineDiffBar = &m_wndLineDiffBar;
456 m_pwndBottomView->m_pwndStatusBar = &m_wndStatusBar;
457 m_pwndBottomView->m_pMainFrame = this;
459 // now create the two views inside the nested splitter
461 if (!m_wndSplitter2.CreateView(0, 0,
462 RUNTIME_CLASS(CLeftView), CSize(cr.Width()/2, cr.Height()/2), pContext))
464 TRACE0("Failed to create second pane\n");
465 return FALSE;
467 m_pwndLeftView = (CLeftView *)m_wndSplitter2.GetPane(0,0);
468 m_pwndLeftView->m_pwndLocator = &m_wndLocatorBar;
469 m_pwndLeftView->m_pwndLineDiffBar = &m_wndLineDiffBar;
470 m_pwndLeftView->m_pwndStatusBar = &m_wndStatusBar;
471 m_pwndLeftView->m_pMainFrame = this;
473 if (!m_wndSplitter2.CreateView(0, 1,
474 RUNTIME_CLASS(CRightView), CSize(cr.Width()/2, cr.Height()/2), pContext))
476 TRACE0("Failed to create third pane\n");
477 return FALSE;
479 m_pwndRightView = (CRightView *)m_wndSplitter2.GetPane(0,1);
480 m_pwndRightView->m_pwndLocator = &m_wndLocatorBar;
481 m_pwndRightView->m_pwndLineDiffBar = &m_wndLineDiffBar;
482 m_pwndRightView->m_pwndStatusBar = &m_wndStatusBar;
483 m_pwndRightView->m_pMainFrame = this;
484 m_bInitSplitter = TRUE;
486 m_dlgFilePatches.Create(IDD_FILEPATCHES, this);
487 UpdateLayout();
488 return TRUE;
491 // Callback function
492 BOOL CMainFrame::PatchFile(CString sFilePath, bool /*bContentMods*/, bool bPropMods, CString sVersion, BOOL bAutoPatch)
494 CString sDummy;
495 //"dry run" was successful, so save the patched file somewhere...
496 CString sTempFile = CTempFiles::Instance().GetTempFilePathString();
497 CString sRejectedFile;
498 if (m_Patch.GetPatchResult(sFilePath, sTempFile, sRejectedFile) < 0)
500 MessageBox(m_Patch.GetErrorMessage(), NULL, MB_ICONERROR);
501 return FALSE;
503 sFilePath = m_Patch.GetTargetPath() + _T("\\") + sFilePath;
504 sFilePath.Replace('/', '\\');
505 if (m_bReversedPatch)
507 m_Data.m_baseFile.SetFileName(sTempFile);
508 CString temp;
509 temp.Format(_T("%s %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sFilePath), (LPCTSTR)m_Data.m_sPatchPatched);
510 m_Data.m_baseFile.SetDescriptiveName(temp);
511 m_Data.m_yourFile.SetFileName(sFilePath);
512 temp.Format(_T("%s %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sFilePath), (LPCTSTR)m_Data.m_sPatchOriginal);
513 m_Data.m_yourFile.SetDescriptiveName(temp);
514 m_Data.m_theirFile.SetOutOfUse();
515 m_Data.m_mergedFile.SetOutOfUse();
517 else
519 if ((!PathFileExists(sFilePath))||(PathIsDirectory(sFilePath)))
521 m_Data.m_baseFile.SetFileName(CTempFiles::Instance().GetTempFilePathString());
522 m_Data.m_baseFile.CreateEmptyFile();
524 else
526 m_Data.m_baseFile.SetFileName(sFilePath);
528 CString sDescription;
529 sDescription.Format(_T("%s %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sFilePath), (LPCTSTR)m_Data.m_sPatchOriginal);
530 m_Data.m_baseFile.SetDescriptiveName(sDescription);
531 m_Data.m_yourFile.SetFileName(sTempFile);
532 CString temp;
533 temp.Format(_T("%s %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sFilePath), (LPCTSTR)m_Data.m_sPatchPatched);
534 m_Data.m_yourFile.SetDescriptiveName(temp);
535 m_Data.m_theirFile.SetOutOfUse();
536 m_Data.m_mergedFile.SetFileName(sFilePath);
537 m_Data.m_bPatchRequired = bPropMods;
539 TRACE(_T("comparing %s\nwith the patched result %s\n"), (LPCTSTR)sFilePath, (LPCTSTR)sTempFile);
541 LoadViews();
542 if (!sRejectedFile.IsEmpty())
544 #if 0 // TGIT TODO
545 // start TortoiseUDiff with the rejected hunks
546 CString sTitle;
547 sTitle.Format(IDS_TITLE_REJECTEDHUNKS, (LPCTSTR)CPathUtils::GetFileNameFromPath(sFilePath));
548 CAppUtils::StartUnifiedDiffViewer(sRejectedFile, sTitle);
549 #endif
551 if (bAutoPatch)
553 PatchSave();
555 return TRUE;
558 // Callback function
559 BOOL CMainFrame::DiffFiles(CString sURL1, CString sRev1, CString sURL2, CString sRev2)
561 CString tempfile1 = CTempFiles::Instance().GetTempFilePathString();
562 CString tempfile2 = CTempFiles::Instance().GetTempFilePathString();
564 ASSERT(tempfile1.Compare(tempfile2));
566 CString sTemp;
567 CSysProgressDlg progDlg;
568 sTemp.Format(IDS_GETVERSIONOFFILE, (LPCTSTR)sRev1);
569 progDlg.SetLine(1, sTemp, true);
570 progDlg.SetLine(2, sURL1, true);
571 sTemp.LoadString(IDS_GETVERSIONOFFILETITLE);
572 progDlg.SetTitle(sTemp);
573 progDlg.SetShowProgressBar(true);
574 progDlg.SetAnimation(IDR_DOWNLOAD);
575 progDlg.SetTime(FALSE);
576 progDlg.SetProgress(1,100);
577 progDlg.ShowModeless(this);
578 if (!CAppUtils::GetVersionedFile(sURL1, sRev1, tempfile1, &progDlg, m_hWnd))
580 progDlg.Stop();
581 CString sErrMsg;
582 sErrMsg.Format(IDS_ERR_MAINFRAME_FILEVERSIONNOTFOUND, (LPCTSTR)sRev1, (LPCTSTR)sURL1);
583 MessageBox(sErrMsg, NULL, MB_ICONERROR);
584 return FALSE;
586 sTemp.Format(IDS_GETVERSIONOFFILE, (LPCTSTR)sRev2);
587 progDlg.SetLine(1, sTemp, true);
588 progDlg.SetLine(2, sURL2, true);
589 progDlg.SetProgress(50, 100);
590 if (!CAppUtils::GetVersionedFile(sURL2, sRev2, tempfile2, &progDlg, m_hWnd))
592 progDlg.Stop();
593 CString sErrMsg;
594 sErrMsg.Format(IDS_ERR_MAINFRAME_FILEVERSIONNOTFOUND, (LPCTSTR)sRev2, (LPCTSTR)sURL2);
595 MessageBox(sErrMsg, NULL, MB_ICONERROR);
596 return FALSE;
598 progDlg.SetProgress(100,100);
599 progDlg.Stop();
600 CString temp;
601 temp.Format(_T("%s Revision %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sURL1), (LPCTSTR)sRev1);
602 m_Data.m_baseFile.SetFileName(tempfile1);
603 m_Data.m_baseFile.SetDescriptiveName(temp);
604 temp.Format(_T("%s Revision %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sURL2), (LPCTSTR)sRev2);
605 m_Data.m_yourFile.SetFileName(tempfile2);
606 m_Data.m_yourFile.SetDescriptiveName(temp);
608 LoadViews();
610 return TRUE;
613 void CMainFrame::OnFileOpen()
615 if (CheckForSave(CHFSR_OPEN)==IDCANCEL)
616 return;
617 COpenDlg dlg;
618 if (dlg.DoModal()!=IDOK)
620 return;
622 m_dlgFilePatches.ShowWindow(SW_HIDE);
623 m_dlgFilePatches.Init(NULL, NULL, CString(), NULL);
624 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,
625 (LPCTSTR)dlg.m_sUnifiedDiffFile, (LPCTSTR)dlg.m_sPatchDirectory);
626 m_Data.m_baseFile.SetFileName(dlg.m_sBaseFile);
627 m_Data.m_theirFile.SetFileName(dlg.m_sTheirFile);
628 m_Data.m_yourFile.SetFileName(dlg.m_sYourFile);
629 m_Data.m_sDiffFile = dlg.m_sUnifiedDiffFile;
630 m_Data.m_sPatchPath = dlg.m_sPatchDirectory;
631 m_Data.m_mergedFile.SetOutOfUse();
632 CCrashReport::Instance().AddFile2(dlg.m_sBaseFile, NULL, _T("Basefile"), CR_AF_MAKE_FILE_COPY);
633 CCrashReport::Instance().AddFile2(dlg.m_sTheirFile, NULL, _T("Theirfile"), CR_AF_MAKE_FILE_COPY);
634 CCrashReport::Instance().AddFile2(dlg.m_sYourFile, NULL, _T("Yourfile"), CR_AF_MAKE_FILE_COPY);
635 CCrashReport::Instance().AddFile2(dlg.m_sUnifiedDiffFile, NULL, _T("Difffile"), CR_AF_MAKE_FILE_COPY);
637 if (!m_Data.IsBaseFileInUse() && m_Data.IsTheirFileInUse() && m_Data.IsYourFileInUse())
639 // a diff between two files means "Yours" against "Base", not "Theirs" against "Yours"
640 m_Data.m_baseFile.TransferDetailsFrom(m_Data.m_theirFile);
642 if (m_Data.IsBaseFileInUse() && m_Data.IsTheirFileInUse() && !m_Data.IsYourFileInUse())
644 // a diff between two files means "Yours" against "Base", not "Theirs" against "Base"
645 m_Data.m_yourFile.TransferDetailsFrom(m_Data.m_theirFile);
647 m_bSaveRequired = false;
649 LoadViews();
652 void CMainFrame::ClearViewNamesAndPaths()
654 m_pwndLeftView->m_sWindowName.Empty();
655 m_pwndLeftView->m_sFullFilePath.Empty();
656 m_pwndRightView->m_sWindowName.Empty();
657 m_pwndRightView->m_sFullFilePath.Empty();
658 m_pwndBottomView->m_sWindowName.Empty();
659 m_pwndBottomView->m_sFullFilePath.Empty();
662 bool CMainFrame::LoadViews(int line)
664 m_Data.SetBlame(m_bBlame);
665 m_Data.SetMovedBlocks(m_bViewMovedBlocks);
666 m_bHasConflicts = false;
667 CBaseView* pwndActiveView = m_pwndLeftView;
668 int nOldLine = m_pwndRightView ? m_pwndRightView->m_nTopLine : -1;
669 int nOldLineNumber =
670 m_pwndRightView && m_pwndRightView->m_pViewData ?
671 m_pwndRightView->m_pViewData->GetLineNumber(m_pwndRightView->m_nTopLine) : -1;
672 POINT ptOldCaretPos = {-1, -1};
673 if (m_pwndRightView && m_pwndRightView->IsTarget())
674 ptOldCaretPos = m_pwndRightView->GetCaretPosition();
675 if (m_pwndBottomView && m_pwndBottomView->IsTarget())
676 ptOldCaretPos = m_pwndBottomView->GetCaretPosition();
677 if (!m_Data.Load())
679 m_pwndLeftView->BuildAllScreen2ViewVector();
680 m_pwndLeftView->DocumentUpdated();
681 m_pwndRightView->DocumentUpdated();
682 m_pwndBottomView->DocumentUpdated();
683 m_wndLocatorBar.DocumentUpdated();
684 m_wndLineDiffBar.DocumentUpdated();
685 ::MessageBox(m_hWnd, m_Data.GetError(), _T("TortoiseGitMerge"), MB_ICONERROR);
686 m_Data.m_mergedFile.SetOutOfUse();
687 m_bSaveRequired = false;
688 return false;
690 SetWindowTitle();
691 m_pwndLeftView->BuildAllScreen2ViewVector();
692 m_pwndLeftView->DocumentUpdated();
693 m_pwndRightView->DocumentUpdated();
694 m_pwndBottomView->DocumentUpdated();
695 m_wndLocatorBar.DocumentUpdated();
696 m_wndLineDiffBar.DocumentUpdated();
698 m_pwndLeftView->SetWritable(false);
699 m_pwndLeftView->SetWritableIsChangable(false);
700 m_pwndLeftView->SetTarget(false);
701 m_pwndRightView->SetWritable(false);
702 m_pwndRightView->SetWritableIsChangable(false);
703 m_pwndRightView->SetTarget(false);
704 m_pwndBottomView->SetWritable(false);
705 m_pwndBottomView->SetWritableIsChangable(false);
706 m_pwndBottomView->SetTarget(false);
708 if (!m_Data.IsBaseFileInUse())
710 CSysProgressDlg progDlg;
711 if (m_Data.IsYourFileInUse() && m_Data.IsTheirFileInUse())
713 m_Data.m_baseFile.TransferDetailsFrom(m_Data.m_theirFile);
715 else if ((!m_Data.m_sDiffFile.IsEmpty())&&(!m_Patch.Init(m_Data.m_sDiffFile, m_Data.m_sPatchPath, &progDlg)))
717 progDlg.Stop();
718 ClearViewNamesAndPaths();
719 MessageBox(m_Patch.GetErrorMessage(), NULL, MB_ICONERROR);
720 m_bSaveRequired = false;
721 return false;
723 progDlg.Stop();
724 if (m_Patch.GetNumberOfFiles() > 0)
726 CString betterpatchpath = m_Patch.CheckPatchPath(m_Data.m_sPatchPath);
727 if (betterpatchpath.CompareNoCase(m_Data.m_sPatchPath)!=0)
729 CString msg;
730 msg.Format(IDS_WARNBETTERPATCHPATHFOUND, (LPCTSTR)m_Data.m_sPatchPath, (LPCTSTR)betterpatchpath);
731 if (CMessageBox::Show(m_hWnd, msg, _T("TortoiseGitMerge"), MB_ICONQUESTION | MB_YESNO)==IDYES)
733 m_Data.m_sPatchPath = betterpatchpath;
734 m_Patch.Init(m_Data.m_sDiffFile, m_Data.m_sPatchPath, &progDlg);
737 m_dlgFilePatches.Init(&m_Patch, this, m_Data.m_sPatchPath, this);
738 m_dlgFilePatches.ShowWindow(SW_SHOW);
739 ClearViewNamesAndPaths();
740 if (!m_wndSplitter.IsRowHidden(1))
741 m_wndSplitter.HideRow(1);
742 m_pwndLeftView->SetHidden(FALSE);
743 m_pwndRightView->SetHidden(FALSE);
744 m_pwndBottomView->SetHidden(TRUE);
747 if (m_Data.IsBaseFileInUse() && !m_Data.IsYourFileInUse() && m_Data.IsTheirFileInUse())
749 m_Data.m_yourFile.TransferDetailsFrom(m_Data.m_theirFile);
751 if (m_Data.IsBaseFileInUse() && m_Data.IsYourFileInUse() && !m_Data.IsTheirFileInUse())
753 //diff between YOUR and BASE
754 if (m_bOneWay)
756 if (!m_wndSplitter2.IsColumnHidden(1))
757 m_wndSplitter2.HideColumn(1);
759 m_pwndLeftView->m_pViewData = &m_Data.m_YourBaseBoth;
760 m_pwndLeftView->texttype = m_Data.m_arYourFile.GetUnicodeType();
761 m_pwndLeftView->lineendings = m_Data.m_arYourFile.GetLineEndings();
762 m_pwndLeftView->m_sWindowName = m_Data.m_baseFile.GetWindowName() + _T(" - ") + m_Data.m_yourFile.GetWindowName();
763 m_pwndLeftView->m_sFullFilePath = m_Data.m_baseFile.GetFilename() + _T(" - ") + m_Data.m_yourFile.GetFilename();
764 m_pwndLeftView->m_pWorkingFile = &m_Data.m_yourFile;
765 m_pwndLeftView->SetTarget();
766 m_pwndLeftView->SetWritableIsChangable(true);
768 m_pwndRightView->m_pViewData = NULL;
769 m_pwndRightView->m_pWorkingFile = NULL;
770 m_pwndBottomView->m_pViewData = NULL;
771 m_pwndBottomView->m_pWorkingFile = NULL;
773 if (!m_wndSplitter.IsRowHidden(1))
774 m_wndSplitter.HideRow(1);
775 m_pwndLeftView->SetHidden(FALSE);
776 m_pwndRightView->SetHidden(TRUE);
777 m_pwndBottomView->SetHidden(TRUE);
778 ::SetWindowPos(m_pwndLeftView->m_hWnd, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
780 else
782 pwndActiveView = m_pwndRightView;
783 if (m_wndSplitter2.IsColumnHidden(1))
784 m_wndSplitter2.ShowColumn();
786 m_pwndLeftView->m_pViewData = &m_Data.m_YourBaseLeft;
787 m_pwndLeftView->texttype = m_Data.m_arBaseFile.GetUnicodeType();
788 m_pwndLeftView->lineendings = m_Data.m_arBaseFile.GetLineEndings();
789 m_pwndLeftView->m_sWindowName = m_Data.m_baseFile.GetWindowName();
790 m_pwndLeftView->m_sFullFilePath = m_Data.m_baseFile.GetFilename();
791 m_pwndLeftView->m_sConvertedFilePath = m_Data.m_baseFile.GetConvertedFileName();
792 m_pwndLeftView->m_pWorkingFile = &m_Data.m_baseFile;
793 m_pwndLeftView->SetWritableIsChangable(true);
795 m_pwndRightView->m_pViewData = &m_Data.m_YourBaseRight;
796 m_pwndRightView->texttype = m_Data.m_arYourFile.GetUnicodeType();
797 m_pwndRightView->lineendings = m_Data.m_arYourFile.GetLineEndings();
798 m_pwndRightView->m_sWindowName = m_Data.m_yourFile.GetWindowName();
799 m_pwndRightView->m_sFullFilePath = m_Data.m_yourFile.GetFilename();
800 m_pwndRightView->m_sConvertedFilePath = m_Data.m_yourFile.GetConvertedFileName();
801 m_pwndRightView->m_pWorkingFile = &m_Data.m_yourFile;
802 m_pwndRightView->SetWritable();
803 m_pwndRightView->SetTarget();
805 m_pwndBottomView->m_pViewData = NULL;
806 m_pwndBottomView->m_pWorkingFile = NULL;
808 if (!m_wndSplitter.IsRowHidden(1))
809 m_wndSplitter.HideRow(1);
810 m_pwndLeftView->SetHidden(FALSE);
811 m_pwndRightView->SetHidden(FALSE);
812 m_pwndBottomView->SetHidden(TRUE);
815 else if (m_Data.IsBaseFileInUse() && m_Data.IsYourFileInUse() && m_Data.IsTheirFileInUse())
817 //diff between THEIR, YOUR and BASE
818 m_pwndBottomView->SetWritable();
819 m_pwndBottomView->SetTarget();
820 pwndActiveView = m_pwndBottomView;
822 m_pwndLeftView->m_pViewData = &m_Data.m_TheirBaseBoth;
823 m_pwndLeftView->texttype = m_Data.m_arTheirFile.GetUnicodeType();
824 m_pwndLeftView->lineendings = m_Data.m_arTheirFile.GetLineEndings();
825 m_pwndLeftView->m_sWindowName.LoadString(IDS_VIEWTITLE_THEIRS);
826 m_pwndLeftView->m_sWindowName += _T(" - ") + m_Data.m_theirFile.GetWindowName();
827 m_pwndLeftView->m_sFullFilePath = m_Data.m_theirFile.GetFilename();
828 m_pwndLeftView->m_sConvertedFilePath = m_Data.m_theirFile.GetConvertedFileName();
829 m_pwndLeftView->m_pWorkingFile = &m_Data.m_theirFile;
831 m_pwndRightView->m_pViewData = &m_Data.m_YourBaseBoth;
832 m_pwndRightView->texttype = m_Data.m_arYourFile.GetUnicodeType();
833 m_pwndRightView->lineendings = m_Data.m_arYourFile.GetLineEndings();
834 m_pwndRightView->m_sWindowName.LoadString(IDS_VIEWTITLE_MINE);
835 m_pwndRightView->m_sWindowName += _T(" - ") + m_Data.m_yourFile.GetWindowName();
836 m_pwndRightView->m_sFullFilePath = m_Data.m_yourFile.GetFilename();
837 m_pwndRightView->m_sConvertedFilePath = m_Data.m_yourFile.GetConvertedFileName();
838 m_pwndRightView->m_pWorkingFile = &m_Data.m_yourFile;
840 m_pwndBottomView->m_pViewData = &m_Data.m_Diff3;
841 m_pwndBottomView->texttype = m_Data.m_arTheirFile.GetUnicodeType();
842 m_pwndBottomView->lineendings = m_Data.m_arTheirFile.GetLineEndings();
843 m_pwndBottomView->m_sWindowName.LoadString(IDS_VIEWTITLE_MERGED);
844 m_pwndBottomView->m_sWindowName += _T(" - ") + m_Data.m_mergedFile.GetWindowName();
845 m_pwndBottomView->m_sFullFilePath = m_Data.m_mergedFile.GetFilename();
846 m_pwndBottomView->m_sConvertedFilePath = m_Data.m_mergedFile.GetConvertedFileName();
847 m_pwndBottomView->m_pWorkingFile = &m_Data.m_mergedFile;
849 if (m_wndSplitter2.IsColumnHidden(1))
850 m_wndSplitter2.ShowColumn();
851 if (m_wndSplitter.IsRowHidden(1))
852 m_wndSplitter.ShowRow();
853 m_pwndLeftView->SetHidden(FALSE);
854 m_pwndRightView->SetHidden(FALSE);
855 m_pwndBottomView->SetHidden(FALSE);
856 // in three pane view, hide the line diff bar
857 m_wndLineDiffBar.ShowPane(false, false, true);
858 m_wndLineDiffBar.DocumentUpdated();
860 if (!m_Data.m_mergedFile.InUse())
862 m_Data.m_mergedFile.SetFileName(m_Data.m_yourFile.GetFilename());
864 m_pwndLeftView->BuildAllScreen2ViewVector();
865 m_pwndLeftView->DocumentUpdated();
866 m_pwndRightView->DocumentUpdated();
867 m_pwndBottomView->DocumentUpdated();
868 m_wndLocatorBar.DocumentUpdated();
869 m_wndLineDiffBar.DocumentUpdated();
870 UpdateLayout();
871 SetActiveView(pwndActiveView);
873 if ((line >= -1) && m_pwndRightView->m_pViewData)
875 int n = line == -1 ? min( nOldLineNumber, nOldLine ) : line;
876 if (n >= 0)
877 n = m_pwndRightView->m_pViewData->FindLineNumber(n);
878 if (n < 0)
879 n = nOldLine;
881 m_pwndRightView->ScrollAllToLine(n);
882 POINT p;
883 p.x = 0;
884 p.y = n;
885 if ((ptOldCaretPos.x >= 0) || (ptOldCaretPos.y >= 0))
886 p = ptOldCaretPos;
887 m_pwndLeftView->SetCaretPosition(p);
888 m_pwndRightView->SetCaretPosition(p);
889 m_pwndBottomView->SetCaretPosition(p);
890 m_pwndBottomView->ScrollToChar(0);
891 m_pwndLeftView->ScrollToChar(0);
892 m_pwndRightView->ScrollToChar(0);
894 else
896 CRegDWORD regFirstDiff = CRegDWORD(_T("Software\\TortoiseGitMerge\\FirstDiffOnLoad"), TRUE);
897 CRegDWORD regFirstConflict = CRegDWORD(_T("Software\\TortoiseGitMerge\\FirstConflictOnLoad"), TRUE);
898 bool bGoFirstDiff = (0 != (DWORD)regFirstDiff);
899 bool bGoFirstConflict = (0 != (DWORD)regFirstConflict);
900 if (bGoFirstConflict && (CheckResolved()>=0))
902 pwndActiveView->GoToFirstConflict();
903 // Ignore the first few Mouse Move messages, so that the line diff stays on
904 // the first diff line until the user actually moves the mouse
905 m_nMoveMovesToIgnore = MOVESTOIGNORE;
907 else if (bGoFirstDiff)
909 pwndActiveView->GoToFirstDifference();
910 // Ignore the first few Mouse Move messages, so that the line diff stays on
911 // the first diff line until the user actually moves the mouse
912 m_nMoveMovesToIgnore = MOVESTOIGNORE;
914 else
916 // Avoid incorrect rendering of active pane.
917 m_pwndBottomView->ScrollToChar(0);
918 m_pwndLeftView->ScrollToChar(0);
919 m_pwndRightView->ScrollToChar(0);
922 CheckResolved();
923 if (m_bHasConflicts)
924 m_bSaveRequired = false;
925 CUndo::GetInstance().Clear();
926 return true;
929 void CMainFrame::UpdateLayout()
931 if (m_bInitSplitter)
933 m_wndSplitter.CenterSplitter();
934 m_wndSplitter2.CenterSplitter();
938 void CMainFrame::OnSize(UINT nType, int cx, int cy)
940 CFrameWndEx::OnSize(nType, cx, cy);
941 if (m_bInitSplitter && nType != SIZE_MINIMIZED)
943 if (m_wndSplitter.GetSafeHwnd())
945 if (m_wndSplitter.HasOldRowSize() && (m_wndSplitter.GetOldRowCount() == 2))
947 int oldTotal = m_wndSplitter.GetOldRowSize(0) + m_wndSplitter.GetOldRowSize(1);
948 if (oldTotal)
950 int cxCur0, cxCur1, cxMin0, cxMin1;
951 m_wndSplitter.GetRowInfo(0, cxCur0, cxMin0);
952 m_wndSplitter.GetRowInfo(1, cxCur1, cxMin1);
953 cxCur0 = m_wndSplitter.GetOldRowSize(0) * (cxCur0 + cxCur1) / oldTotal;
954 cxCur1 = m_wndSplitter.GetOldRowSize(1) * (cxCur0 + cxCur1) / oldTotal;
955 m_wndSplitter.SetRowInfo(0, cxCur0, 0);
956 m_wndSplitter.SetRowInfo(1, cxCur1, 0);
957 m_wndSplitter.RecalcLayout();
961 if (m_wndSplitter2.HasOldColSize() && (m_wndSplitter2.GetOldColCount() == 2))
963 int oldTotal = m_wndSplitter2.GetOldColSize(0) + m_wndSplitter2.GetOldColSize(1);
964 if (oldTotal)
966 int cyCur0, cyCur1, cyMin0, cyMin1;
967 m_wndSplitter2.GetColumnInfo(0, cyCur0, cyMin0);
968 m_wndSplitter2.GetColumnInfo(1, cyCur1, cyMin1);
969 cyCur0 = m_wndSplitter2.GetOldColSize(0) * (cyCur0 + cyCur1) / oldTotal;
970 cyCur1 = m_wndSplitter2.GetOldColSize(1) * (cyCur0 + cyCur1) / oldTotal;
971 m_wndSplitter2.SetColumnInfo(0, cyCur0, 0);
972 m_wndSplitter2.SetColumnInfo(1, cyCur1, 0);
973 m_wndSplitter2.RecalcLayout();
978 if ((nType == SIZE_RESTORED)&&m_bCheckReload)
980 m_bCheckReload = false;
981 CheckForReload();
984 // workaround for ribbon interface when taskbar is on the left/top
985 if (nType == SIZE_MAXIMIZED)
987 WINDOWPLACEMENT wp;
988 GetWindowPlacement(&wp);
989 wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;
990 SetWindowPlacement(&wp);
994 void CMainFrame::OnViewWhitespaces()
996 CRegDWORD regViewWhitespaces = CRegDWORD(_T("Software\\TortoiseGitMerge\\ViewWhitespaces"), 1);
997 BOOL bViewWhitespaces = regViewWhitespaces;
998 if (m_pwndLeftView)
999 bViewWhitespaces = m_pwndLeftView->m_bViewWhitespace;
1001 bViewWhitespaces = !bViewWhitespaces;
1002 regViewWhitespaces = bViewWhitespaces;
1003 if (m_pwndLeftView)
1005 m_pwndLeftView->m_bViewWhitespace = bViewWhitespaces;
1006 m_pwndLeftView->Invalidate();
1008 if (m_pwndRightView)
1010 m_pwndRightView->m_bViewWhitespace = bViewWhitespaces;
1011 m_pwndRightView->Invalidate();
1013 if (m_pwndBottomView)
1015 m_pwndBottomView->m_bViewWhitespace = bViewWhitespaces;
1016 m_pwndBottomView->Invalidate();
1020 void CMainFrame::OnUpdateViewWhitespaces(CCmdUI *pCmdUI)
1022 if (m_pwndLeftView)
1023 pCmdUI->SetCheck(m_pwndLeftView->m_bViewWhitespace);
1026 void CMainFrame::OnViewCollapsed()
1028 m_regCollapsed = !(DWORD)m_regCollapsed;
1029 m_bCollapsed = !!(DWORD)m_regCollapsed;
1031 OnViewTextFoldUnfold();
1032 m_wndLocatorBar.Invalidate();
1035 void CMainFrame::OnUpdateViewCollapsed(CCmdUI *pCmdUI)
1037 pCmdUI->SetCheck(m_bCollapsed);
1040 void CMainFrame::OnViewWraplonglines()
1042 m_bWrapLines = !(DWORD)m_regWrapLines;
1043 m_regWrapLines = m_bWrapLines;
1045 if (m_pwndLeftView) m_pwndLeftView ->WrapChanged();
1046 if (m_pwndRightView) m_pwndRightView ->WrapChanged();
1047 if (m_pwndBottomView) m_pwndBottomView->WrapChanged();
1048 OnViewTextFoldUnfold();
1049 m_wndLocatorBar.DocumentUpdated();
1052 void CMainFrame::OnViewTextFoldUnfold()
1054 OnViewTextFoldUnfold(m_pwndLeftView);
1055 OnViewTextFoldUnfold(m_pwndRightView);
1056 OnViewTextFoldUnfold(m_pwndBottomView);
1059 void CMainFrame::OnViewTextFoldUnfold(CBaseView* view)
1061 if (view == 0)
1062 return;
1063 view->BuildAllScreen2ViewVector();
1064 view->UpdateCaret();
1065 view->Invalidate();
1066 view->EnsureCaretVisible();
1069 void CMainFrame::OnUpdateViewWraplonglines(CCmdUI *pCmdUI)
1071 pCmdUI->SetCheck(m_bWrapLines);
1074 void CMainFrame::OnViewOnewaydiff()
1076 if (CheckForSave(CHFSR_RELOAD)==IDCANCEL)
1077 return;
1078 m_bOneWay = !m_bOneWay;
1079 ShowDiffBar(!m_bOneWay);
1080 LoadViews(-1);
1083 void CMainFrame::ShowDiffBar(bool bShow)
1085 if (bShow)
1087 // restore the line diff bar
1088 m_wndLineDiffBar.ShowPane(m_bLineDiff, false, true);
1089 m_wndLineDiffBar.DocumentUpdated();
1090 m_wndLocatorBar.ShowPane(m_bLocatorBar, false, true);
1091 m_wndLocatorBar.DocumentUpdated();
1093 else
1095 // in one way view, hide the line diff bar
1096 m_wndLineDiffBar.ShowPane(false, false, true);
1097 m_wndLineDiffBar.DocumentUpdated();
1101 int CMainFrame::CheckResolved()
1103 //only in three way diffs can be conflicts!
1104 m_bHasConflicts = true;
1105 if (m_pwndBottomView->IsWindowVisible())
1107 CViewData* viewdata = m_pwndBottomView->m_pViewData;
1108 if (viewdata)
1110 for (int i=0; i<viewdata->GetCount(); i++)
1112 const DiffStates state = viewdata->GetState(i);
1113 if ((DIFFSTATE_CONFLICTED == state)||(DIFFSTATE_CONFLICTED_IGNORED == state))
1114 return i;
1118 m_bHasConflicts = false;
1119 return -1;
1122 int CMainFrame::SaveFile(const CString& sFilePath)
1124 CViewData * pViewData = NULL;
1125 CFileTextLines * pOriginFile = &m_Data.m_arBaseFile;
1126 if (IsViewGood(m_pwndBottomView))
1128 pViewData = m_pwndBottomView->m_pViewData;
1130 else if (IsViewGood(m_pwndRightView))
1132 pViewData = m_pwndRightView->m_pViewData;
1133 if (m_Data.IsYourFileInUse())
1134 pOriginFile = &m_Data.m_arYourFile;
1135 else if (m_Data.IsTheirFileInUse())
1136 pOriginFile = &m_Data.m_arTheirFile;
1138 else
1140 // nothing to save!
1141 return 1;
1143 Invalidate();
1144 if ((pViewData)&&(pOriginFile))
1146 CFileTextLines file;
1147 pOriginFile->CopySettings(&file);
1148 for (int i=0; i<pViewData->GetCount(); i++)
1150 //only copy non-removed lines
1151 DiffStates state = pViewData->GetState(i);
1152 switch (state)
1154 case DIFFSTATE_CONFLICTED:
1155 case DIFFSTATE_CONFLICTED_IGNORED:
1157 int first = i;
1158 int last = i;
1161 last++;
1162 } while((last<pViewData->GetCount()) && ((pViewData->GetState(last)==DIFFSTATE_CONFLICTED)||(pViewData->GetState(last)==DIFFSTATE_CONFLICTED_IGNORED)));
1163 // TortoiseGitMerge changes here
1164 file.Add(_T("<<<<<<< .mine"), m_pwndRightView->lineendings);
1165 for (int j=first; j<last; j++)
1167 EOL lineending = m_pwndRightView->m_pViewData->GetLineEnding(j);
1168 if (lineending == EOL_NOENDING)
1169 lineending = m_pwndRightView->lineendings;
1170 file.Add(m_pwndRightView->m_pViewData->GetLine(j), lineending);
1172 file.Add(_T("======="), m_pwndRightView->lineendings);
1173 for (int j=first; j<last; j++)
1175 EOL lineending = m_pwndLeftView->m_pViewData->GetLineEnding(j);
1176 if (lineending == EOL_NOENDING)
1177 lineending = m_pwndLeftView->lineendings;
1178 file.Add(m_pwndLeftView->m_pViewData->GetLine(j), lineending);
1180 file.Add(_T(">>>>>>> .theirs"), m_pwndRightView->lineendings);
1181 i = last-1;
1183 break;
1184 case DIFFSTATE_EMPTY:
1185 case DIFFSTATE_CONFLICTEMPTY:
1186 case DIFFSTATE_IDENTICALREMOVED:
1187 case DIFFSTATE_REMOVED:
1188 case DIFFSTATE_THEIRSREMOVED:
1189 case DIFFSTATE_YOURSREMOVED:
1190 case DIFFSTATE_CONFLICTRESOLVEDEMPTY:
1191 // do not save removed lines
1192 break;
1193 default:
1194 file.Add(pViewData->GetLine(i), pViewData->GetLineEnding(i));
1195 break;
1198 if (!file.Save(sFilePath, false, false))
1200 CMessageBox::Show(m_hWnd, file.GetErrorString(), _T("TortoiseGitMerge"), MB_ICONERROR);
1201 return -1;
1203 if (sFilePath == m_Data.m_baseFile.GetFilename())
1205 m_Data.m_baseFile.StoreFileAttributes();
1207 if (sFilePath == m_Data.m_theirFile.GetFilename())
1209 m_Data.m_theirFile.StoreFileAttributes();
1211 if (sFilePath == m_Data.m_yourFile.GetFilename())
1213 m_Data.m_yourFile.StoreFileAttributes();
1215 /*if (sFilePath == m_Data.m_mergedFile.GetFilename())
1217 m_Data.m_mergedFile.StoreFileAttributes();
1218 }//*/
1219 m_dlgFilePatches.SetFileStatusAsPatched(sFilePath);
1220 if (m_pwndBottomView)
1221 m_pwndBottomView->SetModified(FALSE);
1222 if (m_pwndRightView)
1223 m_pwndRightView->SetModified(FALSE);
1224 CUndo::GetInstance().MarkAsOriginalState();
1225 if (file.GetCount() == 1 && file.GetAt(0).IsEmpty() && file.GetLineEnding(0) == EOL_NOENDING)
1226 return 0;
1227 return file.GetCount();
1229 return 1;
1232 void CMainFrame::OnFileSave()
1234 FileSave();
1237 void CMainFrame::PatchSave()
1239 bool bDoesNotExist = !PathFileExists(m_Data.m_mergedFile.GetFilename());
1240 if (m_Data.m_bPatchRequired)
1242 m_Patch.PatchPath(m_Data.m_mergedFile.GetFilename());
1244 if (!PathIsDirectory(m_Data.m_mergedFile.GetFilename()))
1246 int saveret = SaveFile(m_Data.m_mergedFile.GetFilename());
1247 if (saveret==0)
1249 // file was saved with 0 lines, remove it.
1250 m_Patch.RemoveFile(m_Data.m_mergedFile.GetFilename());
1251 // just in case
1252 DeleteFile(m_Data.m_mergedFile.GetFilename());
1254 m_Data.m_mergedFile.StoreFileAttributes();
1255 if (m_Data.m_mergedFile.GetFilename() == m_Data.m_yourFile.GetFilename())
1256 m_Data.m_yourFile.StoreFileAttributes();
1257 if ((bDoesNotExist)&&(DWORD(CRegDWORD(_T("Software\\TortoiseGitMerge\\AutoAdd"), TRUE))))
1259 // call TortoiseProc to add the new file to version control
1260 CString cmd = _T("/command:add /noui /path:\"");
1261 cmd += m_Data.m_mergedFile.GetFilename() + _T("\"");
1262 CAppUtils::RunTortoiseGitProc(cmd);
1267 bool CMainFrame::FileSave(bool bCheckResolved /*=true*/)
1269 if (!m_Data.m_mergedFile.InUse())
1270 return FileSaveAs(bCheckResolved);
1271 // check if the file has the readonly attribute set
1272 bool bDoesNotExist = false;
1273 DWORD fAttribs = GetFileAttributes(m_Data.m_mergedFile.GetFilename());
1274 if ((fAttribs != INVALID_FILE_ATTRIBUTES)&&(fAttribs & FILE_ATTRIBUTE_READONLY))
1275 return FileSaveAs(bCheckResolved);
1276 if (fAttribs == INVALID_FILE_ATTRIBUTES)
1278 bDoesNotExist = (GetLastError() == ERROR_FILE_NOT_FOUND);
1280 if (bCheckResolved && HasConflictsWontKeep())
1281 return false;
1283 if (((DWORD)CRegDWORD(_T("Software\\TortoiseGitMerge\\Backup"))) != 0)
1285 MoveFileEx(m_Data.m_mergedFile.GetFilename(), m_Data.m_mergedFile.GetFilename() + _T(".bak"), MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH);
1287 if (m_Data.m_bPatchRequired)
1289 m_Patch.PatchPath(m_Data.m_mergedFile.GetFilename());
1291 int saveret = SaveFile(m_Data.m_mergedFile.GetFilename());
1292 if (saveret==0)
1294 // file was saved with 0 lines!
1295 // ask the user if the file should be deleted
1296 CString sTemp;
1297 sTemp.Format(IDS_DELETEWHENEMPTY, (LPCTSTR)m_Data.m_mergedFile.GetFilename());
1298 if (CMessageBox::ShowCheck(m_hWnd, sTemp, _T("TortoiseGitMerge"), MB_YESNO, _T("DeleteFileWhenEmpty")) == IDYES)
1300 m_Patch.RemoveFile(m_Data.m_mergedFile.GetFilename());
1301 DeleteFile(m_Data.m_mergedFile.GetFilename());
1304 else if (saveret < 0)
1306 // error while saving the file
1307 return false;
1310 // if we're in conflict resolve mode (three pane view), check if there are no more conflicts
1311 // and if there aren't, ask to mark the file as resolved
1312 if (IsViewGood(m_pwndBottomView) && !m_bHasConflicts)
1314 CString projectRoot;
1315 if (g_GitAdminDir.HasAdminDir(m_Data.m_mergedFile.GetFilename(), false, &projectRoot))
1317 CString subpath = m_Data.m_mergedFile.GetFilename();
1318 subpath.Replace(_T('\\'), _T('/'));
1319 if (subpath.GetLength() >= projectRoot.GetLength())
1321 if (subpath[projectRoot.GetLength()] == _T('/'))
1322 subpath = subpath.Right(subpath.GetLength() - projectRoot.GetLength() - 1);
1323 else
1324 subpath = subpath.Right(subpath.GetLength() - projectRoot.GetLength());
1327 CStringA gitdir = CUnicodeUtils::GetMulti(projectRoot, CP_UTF8);
1328 git_repository *repository = NULL;
1329 git_index *index = NULL;
1330 bool hasConflictInIndex = false;
1333 if (git_repository_open(&repository, gitdir.GetBuffer()))
1335 gitdir.ReleaseBuffer();
1336 break;
1338 gitdir.ReleaseBuffer();
1340 if (git_repository_index(&index, repository))
1341 break;
1343 CStringA path = CUnicodeUtils::GetMulti(subpath, CP_UTF8);
1344 const git_index_entry * entry = git_index_get_bypath(index, path.GetBuffer(), 1);
1345 path.ReleaseBuffer();
1346 hasConflictInIndex = entry != nullptr;
1347 } while(0);
1349 if (index)
1350 git_index_free(index);
1352 if (repository)
1353 git_repository_free(repository);
1355 if (hasConflictInIndex)
1357 CString sTemp;
1358 sTemp.Format(IDS_MARKASRESOLVED, (LPCTSTR)CPathUtils::GetFileNameFromPath(m_Data.m_mergedFile.GetFilename()));
1359 if (CMessageBox::Show(m_hWnd, sTemp, _T("TortoiseGitMerge"), MB_YESNO | MB_ICONQUESTION) == IDYES)
1360 MarkAsResolved();
1365 m_bSaveRequired = false;
1366 m_Data.m_mergedFile.StoreFileAttributes();
1368 if ((bDoesNotExist)&&(DWORD(CRegDWORD(_T("Software\\TortoiseGitMerge\\AutoAdd"), TRUE))))
1370 // call TortoiseProc to add the new file to version control
1371 CString cmd = _T("/command:add /noui /path:\"");
1372 cmd += m_Data.m_mergedFile.GetFilename() + _T("\"");
1373 if(!CAppUtils::RunTortoiseGitProc(cmd))
1374 return false;
1376 return true;
1379 void CMainFrame::OnFileSaveAs()
1381 FileSaveAs();
1384 bool CMainFrame::FileSaveAs(bool bCheckResolved /*=true*/)
1386 if (bCheckResolved && HasConflictsWontKeep())
1387 return false;
1389 CString fileName;
1390 if(!TryGetFileName(fileName))
1391 return false;
1393 SaveFile(fileName);
1394 return true;
1397 void CMainFrame::OnUpdateFileSave(CCmdUI *pCmdUI)
1399 BOOL bEnable = FALSE;
1400 if (m_Data.m_mergedFile.InUse())
1402 if (IsViewGood(m_pwndBottomView)&&(m_pwndBottomView->m_pViewData))
1403 bEnable = TRUE;
1404 else if ( (IsViewGood(m_pwndRightView)&&(m_pwndRightView->m_pViewData)) &&
1405 (m_pwndRightView->IsModified() || (m_Data.m_yourFile.GetWindowName().Right(9).Compare(_T(": patched"))==0)) )
1406 bEnable = TRUE;
1408 pCmdUI->Enable(bEnable);
1411 void CMainFrame::OnUpdateFileSaveAs(CCmdUI *pCmdUI)
1413 BOOL bEnable = FALSE;
1414 if (IsViewGood(m_pwndBottomView)&&(m_pwndBottomView->m_pViewData))
1415 bEnable = TRUE;
1416 else if (IsViewGood(m_pwndRightView)&&(m_pwndRightView->m_pViewData))
1417 bEnable = TRUE;
1418 pCmdUI->Enable(bEnable);
1421 void CMainFrame::OnUpdateViewOnewaydiff(CCmdUI *pCmdUI)
1423 pCmdUI->SetCheck(!m_bOneWay);
1424 BOOL bEnable = TRUE;
1425 if (IsViewGood(m_pwndBottomView))
1427 bEnable = FALSE;
1429 pCmdUI->Enable(bEnable);
1432 void CMainFrame::OnViewOptions()
1434 CString sTemp;
1435 sTemp.LoadString(IDS_SETTINGSTITLE);
1436 CSettings dlg(sTemp);
1437 dlg.DoModal();
1438 if (dlg.IsReloadNeeded())
1440 if (CheckForSave(CHFSR_OPTIONS)==IDCANCEL)
1441 return;
1442 CDiffColors::GetInstance().LoadRegistry();
1443 LoadViews();
1444 return;
1446 CDiffColors::GetInstance().LoadRegistry();
1447 if (m_pwndBottomView)
1448 m_pwndBottomView->Invalidate();
1449 if (m_pwndLeftView)
1450 m_pwndLeftView->Invalidate();
1451 if (m_pwndRightView)
1452 m_pwndRightView->Invalidate();
1455 void CMainFrame::OnClose()
1457 if (CheckForSave(CHFSR_CLOSE)!=IDCANCEL)
1459 WINDOWPLACEMENT wp;
1461 // before it is destroyed, save the position of the window
1462 wp.length = sizeof wp;
1464 if (GetWindowPlacement(&wp))
1467 if (IsIconic())
1468 // never restore to Iconic state
1469 wp.showCmd = SW_SHOW ;
1471 if ((wp.flags & WPF_RESTORETOMAXIMIZED) != 0)
1472 // if maximized and maybe iconic restore maximized state
1473 wp.showCmd = SW_SHOWMAXIMIZED ;
1475 // and write it
1476 WriteWindowPlacement(&wp);
1478 __super::OnClose();
1482 void CMainFrame::OnActivate(UINT nValue, CWnd* /*pwnd*/, BOOL /*bActivated?*/)
1484 if (nValue != 0) // activated
1486 if (IsIconic())
1488 m_bCheckReload = TRUE;
1490 else
1491 CheckForReload();
1495 void CMainFrame::OnViewLinedown()
1497 OnViewLineUpDown(1);
1500 void CMainFrame::OnViewLineup()
1502 OnViewLineUpDown(-1);
1505 void CMainFrame::OnViewLineUpDown(int direction)
1507 if (m_pwndLeftView)
1508 m_pwndLeftView->ScrollToLine(m_pwndLeftView->m_nTopLine+direction);
1509 if (m_pwndRightView)
1510 m_pwndRightView->ScrollToLine(m_pwndRightView->m_nTopLine+direction);
1511 if (m_pwndBottomView)
1512 m_pwndBottomView->ScrollToLine(m_pwndBottomView->m_nTopLine+direction);
1513 m_wndLocatorBar.Invalidate();
1514 m_nMoveMovesToIgnore = MOVESTOIGNORE;
1517 void CMainFrame::OnViewLineleft()
1519 OnViewLineLeftRight(-1);
1522 void CMainFrame::OnViewLineright()
1524 OnViewLineLeftRight(1);
1527 void CMainFrame::OnViewLineLeftRight(int direction)
1529 if (m_pwndLeftView)
1530 m_pwndLeftView->ScrollSide(direction);
1531 if (m_pwndRightView)
1532 m_pwndRightView->ScrollSide(direction);
1533 if (m_pwndBottomView)
1534 m_pwndBottomView->ScrollSide(direction);
1537 void CMainFrame::OnEditUseTheirs()
1539 if (m_pwndBottomView)
1540 m_pwndBottomView->UseTheirTextBlock();
1542 void CMainFrame::OnUpdateEditUsetheirblock(CCmdUI *pCmdUI)
1544 pCmdUI->Enable(m_pwndBottomView && m_pwndBottomView->HasSelection());
1547 void CMainFrame::OnEditUseMine()
1549 if (m_pwndBottomView)
1550 m_pwndBottomView->UseMyTextBlock();
1552 void CMainFrame::OnUpdateEditUsemyblock(CCmdUI *pCmdUI)
1554 OnUpdateEditUsetheirblock(pCmdUI);
1557 void CMainFrame::OnEditUseTheirsThenMine()
1559 if (m_pwndBottomView)
1560 m_pwndBottomView->UseTheirAndYourBlock();
1563 void CMainFrame::OnUpdateEditUsetheirthenmyblock(CCmdUI *pCmdUI)
1565 OnUpdateEditUsetheirblock(pCmdUI);
1568 void CMainFrame::OnEditUseMineThenTheirs()
1570 if (m_pwndBottomView)
1571 m_pwndBottomView->UseYourAndTheirBlock();
1574 void CMainFrame::OnUpdateEditUseminethentheirblock(CCmdUI *pCmdUI)
1576 OnUpdateEditUsetheirblock(pCmdUI);
1579 void CMainFrame::OnEditUseleftblock()
1581 if (m_pwndBottomView->IsWindowVisible())
1582 m_pwndBottomView->UseRightBlock();
1583 else
1584 m_pwndRightView->UseLeftBlock();
1587 void CMainFrame::OnUpdateEditUseleftblock(CCmdUI *pCmdUI)
1589 pCmdUI->Enable(IsViewGood(m_pwndRightView) && m_pwndRightView->IsTarget() && m_pwndRightView->HasSelection());
1592 void CMainFrame::OnUpdateUseBlock(CCmdUI *pCmdUI)
1594 pCmdUI->Enable(TRUE);
1597 void CMainFrame::OnEditUseleftfile()
1599 if (m_pwndBottomView->IsWindowVisible())
1600 m_pwndBottomView->UseRightFile();
1601 else
1602 m_pwndRightView->UseLeftFile();
1605 void CMainFrame::OnUpdateEditUseleftfile(CCmdUI *pCmdUI)
1607 pCmdUI->Enable(IsViewGood(m_pwndRightView) && m_pwndRightView->IsTarget());
1610 void CMainFrame::OnEditUseblockfromleftbeforeright()
1612 if (m_pwndRightView)
1613 m_pwndRightView->UseBothLeftFirst();
1616 void CMainFrame::OnUpdateEditUseblockfromleftbeforeright(CCmdUI *pCmdUI)
1618 OnUpdateEditUseleftblock(pCmdUI);
1621 void CMainFrame::OnEditUseblockfromrightbeforeleft()
1623 if (m_pwndRightView)
1624 m_pwndRightView->UseBothRightFirst();
1627 void CMainFrame::OnUpdateEditUseblockfromrightbeforeleft(CCmdUI *pCmdUI)
1629 OnUpdateEditUseleftblock(pCmdUI);
1632 void CMainFrame::OnFileReload()
1634 if (CheckForSave(CHFSR_RELOAD)==IDCANCEL)
1635 return;
1636 CDiffColors::GetInstance().LoadRegistry();
1637 LoadViews(-1);
1640 void CMainFrame::ActivateFrame(int nCmdShow)
1642 // nCmdShow is the normal show mode this frame should be in
1643 // translate default nCmdShow (-1)
1644 if (nCmdShow == -1)
1646 if (!IsWindowVisible())
1647 nCmdShow = SW_SHOWNORMAL;
1648 else if (IsIconic())
1649 nCmdShow = SW_RESTORE;
1652 // bring to top before showing
1653 BringToTop(nCmdShow);
1655 if (nCmdShow != -1)
1657 // show the window as specified
1658 WINDOWPLACEMENT wp;
1660 if ( !ReadWindowPlacement(&wp) )
1662 ShowWindow(nCmdShow);
1664 else
1666 if ( nCmdShow != SW_SHOWNORMAL )
1667 wp.showCmd = nCmdShow;
1669 SetWindowPlacement(&wp);
1672 // and finally, bring to top after showing
1673 BringToTop(nCmdShow);
1677 BOOL CMainFrame::ReadWindowPlacement(WINDOWPLACEMENT * pwp)
1679 CRegString placement = CRegString(_T("Software\\TortoiseGitMerge\\WindowPos"));
1680 CString sPlacement = placement;
1681 if (sPlacement.IsEmpty())
1682 return FALSE;
1683 int nRead = _stscanf_s(sPlacement, _T("%u,%u,%d,%d,%d,%d,%d,%d,%d,%d"),
1684 &pwp->flags, &pwp->showCmd,
1685 &pwp->ptMinPosition.x, &pwp->ptMinPosition.y,
1686 &pwp->ptMaxPosition.x, &pwp->ptMaxPosition.y,
1687 &pwp->rcNormalPosition.left, &pwp->rcNormalPosition.top,
1688 &pwp->rcNormalPosition.right, &pwp->rcNormalPosition.bottom);
1689 if ( nRead != 10 )
1690 return FALSE;
1691 pwp->length = sizeof(WINDOWPLACEMENT);
1693 return TRUE;
1696 void CMainFrame::WriteWindowPlacement(WINDOWPLACEMENT * pwp)
1698 CRegString placement = CRegString(_T("Software\\TortoiseGitMerge\\WindowPos"));
1699 TCHAR szBuffer[_countof("-32767")*8 + sizeof("65535")*2];
1701 _stprintf_s(szBuffer, _T("%u,%u,%d,%d,%d,%d,%d,%d,%d,%d"),
1702 pwp->flags, pwp->showCmd,
1703 pwp->ptMinPosition.x, pwp->ptMinPosition.y,
1704 pwp->ptMaxPosition.x, pwp->ptMaxPosition.y,
1705 pwp->rcNormalPosition.left, pwp->rcNormalPosition.top,
1706 pwp->rcNormalPosition.right, pwp->rcNormalPosition.bottom);
1707 placement = szBuffer;
1710 void CMainFrame::OnUpdateMergeMarkasresolved(CCmdUI *pCmdUI)
1712 if (pCmdUI == NULL)
1713 return;
1714 BOOL bEnable = FALSE;
1715 if ((!m_bReadOnly)&&(m_Data.m_mergedFile.InUse()))
1717 if (IsViewGood(m_pwndBottomView)&&(m_pwndBottomView->m_pViewData))
1719 bEnable = TRUE;
1722 pCmdUI->Enable(bEnable);
1725 void CMainFrame::OnMergeMarkasresolved()
1727 if(HasConflictsWontKeep())
1728 return;
1730 // now check if the file has already been saved and if not, save it.
1731 if (m_Data.m_mergedFile.InUse())
1733 if (IsViewGood(m_pwndBottomView)&&(m_pwndBottomView->m_pViewData))
1735 FileSave(false);
1736 m_bSaveRequired = false;
1739 MarkAsResolved();
1742 BOOL CMainFrame::MarkAsResolved()
1744 if (m_bReadOnly)
1745 return FALSE;
1746 if (!IsViewGood(m_pwndBottomView))
1747 return FALSE;
1749 CString cmd = _T("/command:resolve /path:\"");
1750 cmd += m_Data.m_mergedFile.GetFilename();
1751 cmd += _T("\" /closeonend:1 /noquestion /skipcheck /silent");
1752 if (resolveMsgWnd)
1754 CString s;
1755 s.Format(L" /resolvemsghwnd:%I64d /resolvemsgwparam:%I64d /resolvemsglparam:%I64d", (__int64)resolveMsgWnd, (__int64)resolveMsgWParam, (__int64)resolveMsgLParam);
1756 cmd += s;
1758 if(!CAppUtils::RunTortoiseGitProc(cmd))
1759 return FALSE;
1760 m_bSaveRequired = false;
1761 return TRUE;
1764 void CMainFrame::OnUpdateMergeNextconflict(CCmdUI *pCmdUI)
1766 BOOL bShow = FALSE;
1767 if (HasNextConflict(m_pwndBottomView))
1768 bShow = TRUE;
1769 else if (HasNextConflict(m_pwndRightView))
1770 bShow = TRUE;
1771 else if (HasNextConflict(m_pwndLeftView))
1772 bShow = TRUE;
1773 pCmdUI->Enable(bShow);
1776 bool CMainFrame::HasNextConflict(CBaseView* view)
1778 if (view == 0)
1779 return false;
1780 if (!view->IsTarget())
1781 return false;
1782 return view->HasNextConflict();
1785 void CMainFrame::OnUpdateMergePreviousconflict(CCmdUI *pCmdUI)
1787 BOOL bShow = FALSE;
1788 if (HasPrevConflict(m_pwndBottomView))
1789 bShow = TRUE;
1790 else if (HasPrevConflict(m_pwndRightView))
1791 bShow = TRUE;
1792 else if (HasPrevConflict(m_pwndLeftView))
1793 bShow = TRUE;
1794 pCmdUI->Enable(bShow);
1797 bool CMainFrame::HasPrevConflict(CBaseView* view)
1799 if (view == 0)
1800 return false;
1801 if (!view->IsTarget())
1802 return false;
1803 return view->HasPrevConflict();
1806 void CMainFrame::OnUpdateNavigateNextdifference(CCmdUI *pCmdUI)
1808 CBaseView* baseView = GetActiveBaseView();
1809 BOOL bShow = FALSE;
1810 if (baseView != 0)
1811 bShow = baseView->HasNextDiff();
1812 pCmdUI->Enable(bShow);
1815 void CMainFrame::OnUpdateNavigatePreviousdifference(CCmdUI *pCmdUI)
1817 CBaseView* baseView = GetActiveBaseView();
1818 BOOL bShow = FALSE;
1819 if (baseView != 0)
1820 bShow = baseView->HasPrevDiff();
1821 pCmdUI->Enable(bShow);
1824 void CMainFrame::OnUpdateNavigateNextinlinediff(CCmdUI *pCmdUI)
1826 BOOL bShow = FALSE;
1827 if (HasNextInlineDiff(m_pwndBottomView))
1828 bShow = TRUE;
1829 else if (HasNextInlineDiff(m_pwndRightView))
1830 bShow = TRUE;
1831 else if (HasNextInlineDiff(m_pwndLeftView))
1832 bShow = TRUE;
1833 pCmdUI->Enable(bShow);
1836 bool CMainFrame::HasNextInlineDiff(CBaseView* view)
1838 if (view == 0)
1839 return false;
1840 if (!view->IsTarget())
1841 return false;
1842 return view->HasNextInlineDiff();
1845 void CMainFrame::OnUpdateNavigatePrevinlinediff(CCmdUI *pCmdUI)
1847 BOOL bShow = FALSE;
1848 if (HasPrevInlineDiff(m_pwndBottomView))
1849 bShow = TRUE;
1850 else if (HasPrevInlineDiff(m_pwndRightView))
1851 bShow = TRUE;
1852 else if (HasPrevInlineDiff(m_pwndLeftView))
1853 bShow = TRUE;
1854 pCmdUI->Enable(bShow);
1857 bool CMainFrame::HasPrevInlineDiff(CBaseView* view)
1859 if (view == 0)
1860 return false;
1861 if (!view->IsTarget())
1862 return false;
1863 return view->HasPrevInlineDiff();
1866 void CMainFrame::OnMoving(UINT fwSide, LPRECT pRect)
1868 // if the pathfilelist dialog is attached to the mainframe,
1869 // move it along with the mainframe
1870 if (::IsWindow(m_dlgFilePatches.m_hWnd))
1872 RECT patchrect;
1873 m_dlgFilePatches.GetWindowRect(&patchrect);
1874 if (::IsWindow(m_hWnd))
1876 RECT thisrect;
1877 GetWindowRect(&thisrect);
1878 if (patchrect.right == thisrect.left)
1880 m_dlgFilePatches.SetWindowPos(NULL, patchrect.left - (thisrect.left - pRect->left), patchrect.top - (thisrect.top - pRect->top),
1881 0, 0, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER);
1885 __super::OnMoving(fwSide, pRect);
1888 void CMainFrame::OnUpdateEditCopy(CCmdUI *pCmdUI)
1890 BOOL bShow = FALSE;
1891 if ((m_pwndBottomView)&&(m_pwndBottomView->HasSelection()))
1892 bShow = TRUE;
1893 else if ((m_pwndRightView)&&(m_pwndRightView->HasSelection()))
1894 bShow = TRUE;
1895 else if ((m_pwndLeftView)&&(m_pwndLeftView->HasSelection()))
1896 bShow = TRUE;
1897 pCmdUI->Enable(bShow);
1900 void CMainFrame::OnUpdateEditPaste(CCmdUI *pCmdUI)
1902 BOOL bWritable = FALSE;
1903 if ((m_pwndBottomView)&&(m_pwndBottomView->IsWritable()))
1904 bWritable = TRUE;
1905 else if ((m_pwndRightView)&&(m_pwndRightView->IsWritable()))
1906 bWritable = TRUE;
1907 else if ((m_pwndLeftView)&&(m_pwndLeftView->IsWritable()))
1908 bWritable = TRUE;
1909 pCmdUI->Enable(bWritable && ::IsClipboardFormatAvailable(CF_TEXT));
1912 void CMainFrame::OnViewSwitchleft()
1914 if (CheckForSave(CHFSR_SWITCH)!=IDCANCEL)
1916 CWorkingFile file = m_Data.m_baseFile;
1917 m_Data.m_baseFile = m_Data.m_yourFile;
1918 m_Data.m_yourFile = file;
1919 if (m_Data.m_mergedFile.GetFilename().CompareNoCase(m_Data.m_yourFile.GetFilename())==0)
1921 m_Data.m_mergedFile = m_Data.m_baseFile;
1923 else if (m_Data.m_mergedFile.GetFilename().CompareNoCase(m_Data.m_baseFile.GetFilename())==0)
1925 m_Data.m_mergedFile = m_Data.m_yourFile;
1927 LoadViews();
1931 void CMainFrame::OnUpdateViewSwitchleft(CCmdUI *pCmdUI)
1933 BOOL bEnable = !IsViewGood(m_pwndBottomView);
1934 pCmdUI->Enable(bEnable);
1937 void CMainFrame::OnUpdateViewShowfilelist(CCmdUI *pCmdUI)
1939 BOOL bEnable = m_dlgFilePatches.HasFiles();
1940 pCmdUI->Enable(bEnable);
1941 pCmdUI->SetCheck(m_dlgFilePatches.IsWindowVisible());
1944 void CMainFrame::OnViewShowfilelist()
1946 m_dlgFilePatches.ShowWindow(m_dlgFilePatches.IsWindowVisible() ? SW_HIDE : SW_SHOW);
1949 void CMainFrame::OnEditUndo()
1951 if (CUndo::GetInstance().CanUndo())
1953 CUndo::GetInstance().Undo(m_pwndLeftView, m_pwndRightView, m_pwndBottomView);
1957 void CMainFrame::OnUpdateEditUndo(CCmdUI *pCmdUI)
1959 pCmdUI->Enable(CUndo::GetInstance().CanUndo());
1962 int CMainFrame::CheckForReload()
1964 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
1965 if (bLock)
1967 return IDNO;
1969 bLock = true;
1970 bool bSourceChanged =
1971 m_Data.m_baseFile.HasSourceFileChanged()
1972 || m_Data.m_yourFile.HasSourceFileChanged()
1973 || m_Data.m_theirFile.HasSourceFileChanged()
1974 /*|| m_Data.m_mergedFile.HasSourceFileChanged()*/;
1975 if (!bSourceChanged)
1977 bLock = false;
1978 return IDNO;
1981 int idsMessage = HasUnsavedEdits() ? IDS_WARNMODIFIEDOUTSIDELOOSECHANGES : IDS_WARNMODIFIEDOUTSIDE;
1982 UINT ret = CMessageBox::Show(m_hWnd, idsMessage, IDS_APPNAME, MB_YESNO | MB_ICONQUESTION);
1984 if (ret == IDYES)
1986 CDiffColors::GetInstance().LoadRegistry();
1987 LoadViews(-1);
1989 else
1991 if (IsViewGood(m_pwndBottomView)) // three pane view
1993 /*if (m_Data.m_sourceFile.HasSourceFileChanged())
1994 m_pwndBottomView->SetModified();
1995 if (m_Data.m_mergedFile.HasSourceFileChanged())
1996 m_pwndBottomView->SetModified();//*/
1997 if (m_Data.m_yourFile.HasSourceFileChanged())
1998 m_pwndRightView->SetModified();
1999 if (m_Data.m_theirFile.HasSourceFileChanged())
2000 m_pwndLeftView->SetModified();
2002 else if (IsViewGood(m_pwndRightView)) // two pane view
2004 if (m_Data.m_baseFile.HasSourceFileChanged())
2005 m_pwndLeftView->SetModified();
2006 if (m_Data.m_yourFile.HasSourceFileChanged())
2007 m_pwndRightView->SetModified();
2009 else
2011 if (m_Data.m_yourFile.HasSourceFileChanged())
2012 m_pwndLeftView->SetModified();
2015 // no reload just store updated file time
2016 m_Data.m_baseFile.StoreFileAttributes();
2017 m_Data.m_theirFile.StoreFileAttributes();
2018 m_Data.m_yourFile.StoreFileAttributes();
2019 //m_Data.m_mergedFile.StoreFileAttributes();
2021 bLock = false;
2022 return ret;
2025 int CMainFrame::CheckForSave(ECheckForSaveReason eReason)
2027 CString sTitle(MAKEINTRESOURCE(IDS_WARNMODIFIEDLOOSECHANGES));
2028 // todo use resources instead of constants; we may hold resource id instaed of string
2029 switch (eReason)
2031 case CHFSR_CLOSE:
2032 sTitle = CString(MAKEINTRESOURCE(IDS_ASKFORSAVE)); // use more descriptive IDS_WARNMODIFIEDLOOSECHANGES instead?
2033 break;
2034 case CHFSR_SWITCH:
2035 sTitle = CString(MAKEINTRESOURCE(IDS_WARNMODIFIEDLOOSECHANGES));
2036 break;
2037 case CHFSR_RELOAD:
2038 sTitle = CString(MAKEINTRESOURCE(IDS_WARNMODIFIEDLOOSECHANGES));
2039 break;
2040 case CHFSR_OPTIONS:
2041 sTitle = CString(MAKEINTRESOURCE(IDS_WARNMODIFIEDLOOSECHANGESOPTIONS));
2042 break;
2043 case CHFSR_OPEN:
2044 sTitle = CString(MAKEINTRESOURCE(IDS_WARNMODIFIEDLOOSECHANGES));
2045 break;
2048 // TODO simplify logic, reduce code duplication
2049 if (CBaseView::IsViewGood(m_pwndBottomView))
2051 // three-way diff - by design only bottom can be changed
2053 else if (CBaseView::IsViewGood(m_pwndRightView))
2055 // two-way diff -
2056 // in 1.7 version only right was saved, now left and/or right can be save, so we need to indicate what we are asking to save
2057 if (HasUnsavedEdits(m_pwndLeftView))
2059 // both views
2060 UINT ret = IDNO;
2062 // show separate questions
2063 // first show question for left view
2064 ret = MessageBox(sTitle, 0, MB_YESNOCANCEL | MB_ICONQUESTION);
2065 if (ret == IDCANCEL)
2067 return IDCANCEL;
2069 if (ret == IDYES)
2071 if (m_pwndLeftView->SaveFile()<0)
2073 return IDCANCEL;
2076 // right file is handled old way
2079 else
2081 // only secondary (left) view
2083 // otherwise 1.7 behaviour is used
2085 else if (CBaseView::IsViewGood(m_pwndLeftView))
2087 // only one view - only one to save
2088 // 1.7 FileSave don't support this mode
2089 if (HasUnsavedEdits(m_pwndLeftView))
2091 UINT ret = IDNO;
2093 ret = MessageBox(sTitle, 0, MB_YESNOCANCEL | MB_ICONQUESTION);
2096 if (ret == IDYES)
2098 if (m_pwndLeftView->SaveFile()<0)
2099 return IDCANCEL;
2102 return IDNO;
2104 else
2106 return IDNO; // nothing to save
2109 UINT ret = IDNO;
2110 if (HasUnsavedEdits())
2112 ret = MessageBox(sTitle, 0, MB_YESNOCANCEL | MB_ICONQUESTION);
2114 if (ret == IDYES)
2116 if (!FileSave())
2117 ret = IDCANCEL;
2120 return ret;
2123 bool CMainFrame::HasUnsavedEdits() const
2125 return HasUnsavedEdits(m_pwndBottomView) || HasUnsavedEdits(m_pwndRightView) || m_bSaveRequired;
2128 bool CMainFrame::HasUnsavedEdits(const CBaseView* view)
2130 if(view == 0)
2131 return false;
2132 return view->IsModified();
2135 bool CMainFrame::IsViewGood(const CBaseView* view)
2137 return CBaseView::IsViewGood(view);
2140 void CMainFrame::OnViewInlinediffword()
2142 m_bInlineWordDiff = !m_bInlineWordDiff;
2143 if (m_pwndLeftView)
2145 m_pwndLeftView->SetInlineWordDiff(m_bInlineWordDiff);
2146 m_pwndLeftView->BuildAllScreen2ViewVector();
2147 m_pwndLeftView->DocumentUpdated();
2149 if (m_pwndRightView)
2151 m_pwndRightView->SetInlineWordDiff(m_bInlineWordDiff);
2152 m_pwndRightView->BuildAllScreen2ViewVector();
2153 m_pwndRightView->DocumentUpdated();
2155 if (m_pwndBottomView)
2157 m_pwndBottomView->SetInlineWordDiff(m_bInlineWordDiff);
2158 m_pwndBottomView->BuildAllScreen2ViewVector();
2159 m_pwndBottomView->DocumentUpdated();
2161 m_wndLineDiffBar.DocumentUpdated();
2164 void CMainFrame::OnUpdateViewInlinediffword(CCmdUI *pCmdUI)
2166 pCmdUI->Enable(m_bInlineDiff && IsViewGood(m_pwndLeftView) && IsViewGood(m_pwndRightView));
2167 pCmdUI->SetCheck(m_bInlineWordDiff);
2170 void CMainFrame::OnViewInlinediff()
2172 m_bInlineDiff = !m_bInlineDiff;
2173 if (m_pwndLeftView)
2175 m_pwndLeftView->SetInlineDiff(m_bInlineDiff);
2176 m_pwndLeftView->BuildAllScreen2ViewVector();
2177 m_pwndLeftView->DocumentUpdated();
2179 if (m_pwndRightView)
2181 m_pwndRightView->SetInlineDiff(m_bInlineDiff);
2182 m_pwndRightView->BuildAllScreen2ViewVector();
2183 m_pwndRightView->DocumentUpdated();
2185 if (m_pwndBottomView)
2187 m_pwndBottomView->SetInlineDiff(m_bInlineDiff);
2188 m_pwndBottomView->BuildAllScreen2ViewVector();
2189 m_pwndBottomView->DocumentUpdated();
2191 m_wndLineDiffBar.DocumentUpdated();
2194 void CMainFrame::OnUpdateViewInlinediff(CCmdUI *pCmdUI)
2196 pCmdUI->Enable(IsViewGood(m_pwndLeftView) && IsViewGood(m_pwndRightView));
2197 pCmdUI->SetCheck(m_bInlineDiff);
2200 void CMainFrame::OnUpdateEditCreateunifieddifffile(CCmdUI *pCmdUI)
2202 // "create unified diff file" is only available if two files
2203 // are diffed, not three.
2204 bool bEnabled = true;
2205 if (!IsViewGood(m_pwndLeftView))
2206 bEnabled = false;
2207 else if (!IsViewGood(m_pwndRightView))
2208 bEnabled = false;
2209 else if (IsViewGood(m_pwndBottomView)) //no negation here
2210 bEnabled = false;
2211 pCmdUI->Enable(bEnabled);
2214 void CMainFrame::OnEditCreateunifieddifffile()
2216 CString origFile, modifiedFile;
2217 // the original file is the one on the left
2218 if (m_pwndLeftView)
2219 origFile = m_pwndLeftView->m_sFullFilePath;
2220 if (m_pwndRightView)
2221 modifiedFile = m_pwndRightView->m_sFullFilePath;
2222 if (origFile.IsEmpty() || modifiedFile.IsEmpty())
2223 return;
2225 CString outputFile;
2226 if(!TryGetFileName(outputFile))
2227 return;
2229 CAppUtils::CreateUnifiedDiff(origFile, modifiedFile, outputFile, true);
2232 void CMainFrame::OnUpdateViewLinediffbar(CCmdUI *pCmdUI)
2234 pCmdUI->SetCheck(m_bLineDiff);
2235 pCmdUI->Enable();
2238 void CMainFrame::OnViewLinediffbar()
2240 m_bLineDiff = !m_bLineDiff;
2241 m_wndLineDiffBar.ShowPane(m_bLineDiff, false, true);
2242 m_wndLineDiffBar.DocumentUpdated();
2243 m_wndLocatorBar.ShowPane(m_bLocatorBar, false, true);
2244 m_wndLocatorBar.DocumentUpdated();
2247 void CMainFrame::OnUpdateViewLocatorbar(CCmdUI *pCmdUI)
2249 pCmdUI->SetCheck(m_bLocatorBar);
2250 pCmdUI->Enable();
2253 void CMainFrame::OnViewLocatorbar()
2255 m_bLocatorBar = !m_bLocatorBar;
2256 m_wndLocatorBar.ShowPane(m_bLocatorBar, false, true);
2257 m_wndLocatorBar.DocumentUpdated();
2258 m_wndLineDiffBar.ShowPane(m_bLineDiff, false, true);
2259 m_wndLineDiffBar.DocumentUpdated();
2262 void CMainFrame::OnViewComparewhitespaces()
2264 if (CheckForSave(CHFSR_OPTIONS)==IDCANCEL)
2265 return;
2266 CRegDWORD regIgnoreWS = CRegDWORD(_T("Software\\TortoiseGitMerge\\IgnoreWS"));
2267 regIgnoreWS = 0;
2268 LoadViews(-1);
2271 void CMainFrame::OnUpdateViewComparewhitespaces(CCmdUI *pCmdUI)
2273 CRegDWORD regIgnoreWS = CRegDWORD(_T("Software\\TortoiseGitMerge\\IgnoreWS"));
2274 DWORD dwIgnoreWS = regIgnoreWS;
2275 pCmdUI->SetCheck(dwIgnoreWS == 0);
2278 void CMainFrame::OnViewIgnorewhitespacechanges()
2280 if (CheckForSave(CHFSR_OPTIONS)==IDCANCEL)
2281 return;
2282 CRegDWORD regIgnoreWS = CRegDWORD(_T("Software\\TortoiseGitMerge\\IgnoreWS"));
2283 regIgnoreWS = 2;
2284 LoadViews(-1);
2287 void CMainFrame::OnUpdateViewIgnorewhitespacechanges(CCmdUI *pCmdUI)
2289 CRegDWORD regIgnoreWS = CRegDWORD(_T("Software\\TortoiseGitMerge\\IgnoreWS"));
2290 DWORD dwIgnoreWS = regIgnoreWS;
2291 pCmdUI->SetCheck(dwIgnoreWS == 2);
2294 void CMainFrame::OnViewIgnoreallwhitespacechanges()
2296 if (CheckForSave(CHFSR_OPTIONS)==IDCANCEL)
2297 return;
2298 CRegDWORD regIgnoreWS = CRegDWORD(_T("Software\\TortoiseGitMerge\\IgnoreWS"));
2299 regIgnoreWS = 1;
2300 LoadViews(-1);
2303 void CMainFrame::OnUpdateViewIgnoreallwhitespacechanges(CCmdUI *pCmdUI)
2305 CRegDWORD regIgnoreWS = CRegDWORD(_T("Software\\TortoiseGitMerge\\IgnoreWS"));
2306 DWORD dwIgnoreWS = regIgnoreWS;
2307 pCmdUI->SetCheck(dwIgnoreWS == 1);
2310 void CMainFrame::OnViewMovedBlocks()
2312 m_bViewMovedBlocks = !(DWORD)m_regViewModedBlocks;
2313 m_regViewModedBlocks = m_bViewMovedBlocks;
2314 LoadViews(-1);
2317 void CMainFrame::OnUpdateViewMovedBlocks(CCmdUI *pCmdUI)
2319 pCmdUI->SetCheck(m_bViewMovedBlocks);
2320 BOOL bEnable = TRUE;
2321 if (IsViewGood(m_pwndBottomView))
2323 bEnable = FALSE;
2325 pCmdUI->Enable(bEnable);
2328 bool CMainFrame::HasConflictsWontKeep()
2330 const int nConflictLine = CheckResolved();
2331 if (nConflictLine < 0)
2332 return false;
2334 CString sTemp;
2335 sTemp.Format(IDS_ERR_MAINFRAME_FILEHASCONFLICTS, m_pwndBottomView->m_pViewData->GetLineNumber(nConflictLine)+1);
2336 if (MessageBox(sTemp, 0, MB_ICONERROR | MB_YESNO)==IDYES)
2337 return false;
2339 if (m_pwndBottomView)
2340 m_pwndBottomView->GoToLine(nConflictLine);
2341 return true;
2344 bool CMainFrame::TryGetFileName(CString& result)
2346 return CCommonAppUtils::FileOpenSave(result, NULL, IDS_SAVEASTITLE, IDS_COMMONFILEFILTER, false, m_hWnd);
2349 CBaseView* CMainFrame::GetActiveBaseView() const
2351 CView* activeView = GetActiveView();
2352 CBaseView* activeBase = dynamic_cast<CBaseView*>( activeView );
2353 return activeBase;
2356 void CMainFrame::SetWindowTitle()
2358 // try to find a suitable window title
2359 CString sYour = m_Data.m_yourFile.GetDescriptiveName();
2360 if (sYour.Find(_T(" - "))>=0)
2361 sYour = sYour.Left(sYour.Find(_T(" - ")));
2362 if (sYour.Find(_T(" : "))>=0)
2363 sYour = sYour.Left(sYour.Find(_T(" : ")));
2364 CString sTheir = m_Data.m_theirFile.GetDescriptiveName();
2365 if (sTheir.IsEmpty())
2366 sTheir = m_Data.m_baseFile.GetDescriptiveName();
2367 if (sTheir.Find(_T(" - "))>=0)
2368 sTheir = sTheir.Left(sTheir.Find(_T(" - ")));
2369 if (sTheir.Find(_T(" : "))>=0)
2370 sTheir = sTheir.Left(sTheir.Find(_T(" : ")));
2372 if (!sYour.IsEmpty() && !sTheir.IsEmpty())
2374 if (sYour.CompareNoCase(sTheir)==0)
2375 SetWindowText(sYour + _T(" - TortoiseGitMerge"));
2376 else if ((sYour.GetLength() < 10) &&
2377 (sTheir.GetLength() < 10))
2378 SetWindowText(sYour + _T(" - ") + sTheir + _T(" - TortoiseGitMerge"));
2379 else
2381 // we have two very long descriptive texts here, which
2382 // means we have to find a way to use them as a window
2383 // title in a shorter way.
2384 // for simplicity, we just use the one from "yourfile"
2385 SetWindowText(sYour + _T(" - TortoiseGitMerge"));
2388 else if (!sYour.IsEmpty())
2389 SetWindowText(sYour + _T(" - TortoiseGitMerge"));
2390 else if (!sTheir.IsEmpty())
2391 SetWindowText(sTheir + _T(" - TortoiseGitMerge"));
2392 else
2393 SetWindowText(L"TortoiseGitMerge");