Open the explorer with the converted temp file selected on a Ctrl+trippleclick on...
[TortoiseGit.git] / src / TortoiseMerge / MainFrm.cpp
blobed94f32b6fa1bea2d23bc06eb83a6c4d3fe25d03
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 "OpenDlg.h"
24 #include "SysProgressDlg.h"
25 #include "Settings.h"
26 #include "MessageBox.h"
27 #include "AppUtils.h"
28 #include "PathUtils.h"
29 #include "MainFrm.h"
30 #include "LeftView.h"
31 #include "RightView.h"
32 #include "BottomView.h"
33 #include "DiffColors.h"
34 #include "mainfrm.h"
35 #include "SelectFileFilter.h"
36 #include "FormatMessageWrapper.h"
37 #include "TaskbarUUID.h"
38 #include "git2.h"
40 #ifdef _DEBUG
41 #define new DEBUG_NEW
42 #endif
44 // CMainFrame
45 const UINT TaskBarButtonCreated = RegisterWindowMessage(L"TaskbarButtonCreated");
47 IMPLEMENT_DYNCREATE(CMainFrame, CFrameWndEx)
49 BEGIN_MESSAGE_MAP(CMainFrame, CFrameWndEx)
50 ON_WM_CREATE()
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)
60 ON_WM_SIZE()
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)
69 ON_WM_CLOSE()
70 ON_WM_ACTIVATE()
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)
80 ON_WM_MOVE()
81 ON_WM_MOVING()
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)
134 END_MESSAGE_MAP()
136 static UINT indicators[] =
138 ID_SEPARATOR, // status line indicator
139 ID_INDICATOR_LEFTVIEW,
140 ID_INDICATOR_RIGHTVIEW,
141 ID_INDICATOR_BOTTOMVIEW,
142 ID_INDICATOR_CAPS,
143 ID_INDICATOR_NUM,
147 // CMainFrame construction/destruction
149 CMainFrame::CMainFrame()
150 : m_bInitSplitter(FALSE)
151 , m_bReversedPatch(FALSE)
152 , m_bHasConflicts(false)
153 , m_bInlineWordDiff(true)
154 , m_bLineDiff(true)
155 , m_bLocatorBar(true)
156 , m_nMoveMovesToIgnore(0)
157 , m_pwndLeftView(NULL)
158 , m_pwndRightView(NULL)
159 , m_pwndBottomView(NULL)
160 , m_bReadOnly(false)
161 , m_bBlame(false)
162 , m_bCheckReload(false)
163 , m_bSaveRequired(false)
164 , resolveMsgWnd(0)
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);
191 return 0;
195 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
197 if (CFrameWndEx::OnCreate(lpCreateStruct) == -1)
198 return -1;
200 OnApplicationLook(theApp.m_nAppLook);
202 if (m_bUseRibbons)
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);
209 if (pMainCat)
211 CMFCRibbonPanel * pPanel = pMainCat->GetPanel(3);
212 if (pPanel)
213 pPanel->EnableLaunchButton(ID_VIEW_OPTIONS);
216 else
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);
258 if (!m_bUseRibbons)
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);
273 return 0;
276 BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
278 if( !CFrameWndEx::PreCreateWindow(cs) )
279 return FALSE;
280 return TRUE;
283 void CMainFrame::OnApplicationLook(UINT id)
285 CWaitCursor wait;
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);
294 break;
296 case ID_VIEW_APPLOOK_OFF_XP:
297 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOfficeXP));
298 m_wndRibbonBar.SetWindows7Look(FALSE);
299 break;
301 case ID_VIEW_APPLOOK_WIN_XP:
302 CMFCVisualManagerWindows::m_b3DTabsXPTheme = TRUE;
303 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));
304 m_wndRibbonBar.SetWindows7Look(FALSE);
305 break;
307 case ID_VIEW_APPLOOK_OFF_2003:
308 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2003));
309 CDockingManager::SetDockingMode(DT_SMART);
310 m_wndRibbonBar.SetWindows7Look(FALSE);
311 break;
313 case ID_VIEW_APPLOOK_VS_2005:
314 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerVS2005));
315 CDockingManager::SetDockingMode(DT_SMART);
316 m_wndRibbonBar.SetWindows7Look(FALSE);
317 break;
319 case ID_VIEW_APPLOOK_VS_2008:
320 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerVS2008));
321 CDockingManager::SetDockingMode(DT_SMART);
322 m_wndRibbonBar.SetWindows7Look(FALSE);
323 break;
325 case ID_VIEW_APPLOOK_WIN7:
326 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows7));
327 CDockingManager::SetDockingMode(DT_SMART);
328 m_wndRibbonBar.SetWindows7Look(TRUE);
329 break;
331 default:
332 switch (theApp.m_nAppLook)
334 case ID_VIEW_APPLOOK_OFF_2007_BLUE:
335 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_LunaBlue);
336 break;
338 case ID_VIEW_APPLOOK_OFF_2007_BLACK:
339 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_ObsidianBlack);
340 break;
342 case ID_VIEW_APPLOOK_OFF_2007_SILVER:
343 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_Silver);
344 break;
346 case ID_VIEW_APPLOOK_OFF_2007_AQUA:
347 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_Aqua);
348 break;
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)
363 pCmdUI->Enable();
364 pCmdUI->SetRadio(theApp.m_nAppLook == pCmdUI->m_nID);
368 // CMainFrame diagnostics
370 #ifdef _DEBUG
371 void CMainFrame::AssertValid() const
373 CFrameWndEx::AssertValid();
376 void CMainFrame::Dump(CDumpContext& dc) const
378 CFrameWndEx::Dump(dc);
381 #endif //_DEBUG
384 // CMainFrame message handlers
387 BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT /*lpcs*/, CCreateContext* pContext)
389 CRect cr;
390 GetClientRect( &cr);
393 // split into three panes:
394 // -------------
395 // | | |
396 // | | |
397 // |------------
398 // | |
399 // | |
400 // |------------
402 // create a splitter with 2 rows, 1 column
403 if (!m_wndSplitter.CreateStatic(this, 2, 1))
405 TRACE0("Failed to CreateStaticSplitter\n");
406 return FALSE;
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");
419 return FALSE;
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");
426 return FALSE;
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");
440 return FALSE;
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");
452 return FALSE;
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);
462 UpdateLayout();
463 return TRUE;
466 // Callback function
467 BOOL CMainFrame::PatchFile(CString sFilePath, bool /*bContentMods*/, bool bPropMods, CString sVersion, BOOL bAutoPatch)
469 CString sDummy;
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);
476 return FALSE;
478 sFilePath = m_Patch.GetTargetPath() + _T("\\") + sFilePath;
479 sFilePath.Replace('/', '\\');
480 if (m_bReversedPatch)
482 m_Data.m_baseFile.SetFileName(sTempFile);
483 CString temp;
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();
492 else
494 if ((!PathFileExists(sFilePath))||(PathIsDirectory(sFilePath)))
496 m_Data.m_baseFile.SetFileName(CTempFiles::Instance().GetTempFilePathString());
497 m_Data.m_baseFile.CreateEmptyFile();
499 else
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);
507 CString temp;
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);
516 LoadViews();
517 if (!sRejectedFile.IsEmpty())
519 #if 0 // TGIT TODO
520 // start TortoiseUDiff with the rejected hunks
521 CString sTitle;
522 sTitle.Format(IDS_TITLE_REJECTEDHUNKS, (LPCTSTR)CPathUtils::GetFileNameFromPath(sFilePath));
523 CAppUtils::StartUnifiedDiffViewer(sRejectedFile, sTitle);
524 #endif
526 if (bAutoPatch)
528 PatchSave();
530 return TRUE;
533 // Callback function
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));
541 CString sTemp;
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))
555 progDlg.Stop();
556 CString sErrMsg;
557 sErrMsg.Format(IDS_ERR_MAINFRAME_FILEVERSIONNOTFOUND, (LPCTSTR)sRev1, (LPCTSTR)sURL1);
558 MessageBox(sErrMsg, NULL, MB_ICONERROR);
559 return FALSE;
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))
567 progDlg.Stop();
568 CString sErrMsg;
569 sErrMsg.Format(IDS_ERR_MAINFRAME_FILEVERSIONNOTFOUND, (LPCTSTR)sRev2, (LPCTSTR)sURL2);
570 MessageBox(sErrMsg, NULL, MB_ICONERROR);
571 return FALSE;
573 progDlg.SetProgress(100,100);
574 progDlg.Stop();
575 CString temp;
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);
583 LoadViews();
585 return TRUE;
588 void CMainFrame::OnFileOpen()
590 if (CheckForSave()==IDCANCEL)
591 return;
592 COpenDlg dlg;
593 if (dlg.DoModal()!=IDOK)
595 return;
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;
624 LoadViews();
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;
644 int nOldLineNumber =
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();
652 if (!m_Data.Load())
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;
663 return false;
665 SetWindowTitle();
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)))
687 progDlg.Stop();
688 ClearViewNamesAndPaths();
689 MessageBox(m_Patch.GetErrorMessage(), NULL, MB_ICONERROR);
690 m_bSaveRequired = false;
691 return false;
693 progDlg.Stop();
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)
699 CString msg;
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();
726 if (m_bOneWay)
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);
747 else
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();
828 UpdateLayout();
829 SetActiveView(pwndActiveView);
831 if ((line >= -1) && m_pwndRightView->m_pViewData)
833 int n = line == -1 ? min( nOldLineNumber, nOldLine ) : line;
834 if (n >= 0)
835 n = m_pwndRightView->m_pViewData->FindLineNumber(n);
836 if (n < 0)
837 n = nOldLine;
839 m_pwndRightView->ScrollAllToLine(n);
840 POINT p;
841 p.x = 0;
842 p.y = n;
843 if ((ptOldCaretPos.x >= 0) || (ptOldCaretPos.y >= 0))
844 p = ptOldCaretPos;
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);
852 else
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;
872 else
874 // Avoid incorrect rendering of active pane.
875 m_pwndBottomView->ScrollToChar(0);
876 m_pwndLeftView->ScrollToChar(0);
877 m_pwndRightView->ScrollToChar(0);
880 CheckResolved();
881 if (m_bHasConflicts)
882 m_bSaveRequired = false;
883 CUndo::GetInstance().Clear();
884 return true;
887 void CMainFrame::UpdateLayout()
889 if (m_bInitSplitter)
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);
906 if (oldTotal)
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);
922 if (oldTotal)
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;
939 CheckForReload();
942 // workaround for ribbon interface when taskbar is on the left/top
943 if (nType == SIZE_MAXIMIZED)
945 WINDOWPLACEMENT wp;
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;
956 if (m_pwndLeftView)
957 bViewWhitespaces = m_pwndLeftView->m_bViewWhitespace;
959 bViewWhitespaces = !bViewWhitespaces;
960 regViewWhitespaces = bViewWhitespaces;
961 if (m_pwndLeftView)
963 m_pwndLeftView->m_bViewWhitespace = bViewWhitespaces;
964 m_pwndLeftView->Invalidate();
966 if (m_pwndRightView)
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)
980 if (m_pwndLeftView)
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)
1019 if (view == 0)
1020 return;
1021 view->BuildAllScreen2ViewVector();
1022 view->UpdateCaret();
1023 view->Invalidate();
1024 view->EnsureCaretVisible();
1027 void CMainFrame::OnUpdateViewWraplonglines(CCmdUI *pCmdUI)
1029 pCmdUI->SetCheck(m_bWrapLines);
1032 void CMainFrame::OnViewOnewaydiff()
1034 if (CheckForSave()==IDCANCEL)
1035 return;
1036 m_bOneWay = !m_bOneWay;
1037 ShowDiffBar(!m_bOneWay);
1038 LoadViews(-1);
1041 void CMainFrame::ShowDiffBar(bool bShow)
1043 if (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();
1051 else
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;
1066 if (viewdata)
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))
1072 return i;
1076 m_bHasConflicts = false;
1077 return -1;
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;
1087 Invalidate();
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;
1096 Invalidate();
1098 else
1100 // nothing to save!
1101 return 1;
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);
1111 switch (state)
1113 case DIFFSTATE_CONFLICTED:
1114 case DIFFSTATE_CONFLICTED_IGNORED:
1116 int first = i;
1117 int last = i;
1120 last++;
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);
1140 i = last-1;
1142 break;
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
1151 break;
1152 default:
1153 file.Add(pViewData->GetLine(i), pViewData->GetLineEnding(i));
1154 break;
1157 if (!file.Save(sFilePath, false, false))
1159 CMessageBox::Show(m_hWnd, file.GetErrorString(), _T("TortoiseGitMerge"), MB_ICONERROR);
1160 return -1;
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();
1177 }//*/
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)
1185 return 0;
1186 return file.GetCount();
1188 return 1;
1191 void CMainFrame::OnFileSave()
1193 FileSave();
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());
1206 if (saveret==0)
1208 // file was saved with 0 lines, remove it.
1209 m_Patch.RemoveFile(m_Data.m_mergedFile.GetFilename());
1210 // just in case
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())
1240 return false;
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());
1251 if (saveret==0)
1253 // file was saved with 0 lines!
1254 // ask the user if the file should be deleted
1255 CString sTemp;
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
1266 return false;
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);
1282 else
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();
1295 break;
1297 gitdir.ReleaseBuffer();
1299 if (git_repository_index(&index, repository))
1300 break;
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;
1306 } while(0);
1308 if (index)
1309 git_index_free(index);
1311 if (repository)
1312 git_repository_free(repository);
1314 if (hasConflictInIndex)
1316 CString sTemp;
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)
1319 MarkAsResolved();
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))
1333 return false;
1335 return true;
1338 void CMainFrame::OnFileSaveAs()
1340 FileSaveAs();
1343 bool CMainFrame::FileSaveAs(bool bCheckResolved /*=true*/)
1345 if (bCheckResolved && HasConflictsWontKeep())
1346 return false;
1348 CString fileName;
1349 if(!TryGetFileName(fileName))
1350 return false;
1352 SaveFile(fileName);
1353 return true;
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))
1362 bEnable = TRUE;
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)) )
1365 bEnable = TRUE;
1367 pCmdUI->Enable(bEnable);
1370 void CMainFrame::OnUpdateFileSaveAs(CCmdUI *pCmdUI)
1372 BOOL bEnable = FALSE;
1373 if (IsViewGood(m_pwndBottomView)&&(m_pwndBottomView->m_pViewData))
1374 bEnable = TRUE;
1375 else if (IsViewGood(m_pwndRightView)&&(m_pwndRightView->m_pViewData))
1376 bEnable = TRUE;
1377 pCmdUI->Enable(bEnable);
1380 void CMainFrame::OnUpdateViewOnewaydiff(CCmdUI *pCmdUI)
1382 pCmdUI->SetCheck(!m_bOneWay);
1383 BOOL bEnable = TRUE;
1384 if (IsViewGood(m_pwndBottomView))
1386 bEnable = FALSE;
1388 pCmdUI->Enable(bEnable);
1391 void CMainFrame::OnViewOptions()
1393 CString sTemp;
1394 sTemp.LoadString(IDS_SETTINGSTITLE);
1395 CSettings dlg(sTemp);
1396 dlg.DoModal();
1397 if (dlg.IsReloadNeeded())
1399 if (CheckForSave()==IDCANCEL)
1400 return;
1401 CDiffColors::GetInstance().LoadRegistry();
1402 LoadViews();
1403 return;
1405 CDiffColors::GetInstance().LoadRegistry();
1406 if (m_pwndBottomView)
1407 m_pwndBottomView->Invalidate();
1408 if (m_pwndLeftView)
1409 m_pwndLeftView->Invalidate();
1410 if (m_pwndRightView)
1411 m_pwndRightView->Invalidate();
1414 void CMainFrame::OnClose()
1416 UINT ret = IDNO;
1417 if (HasUnsavedEdits())
1419 CString sTemp;
1420 sTemp.LoadString(IDS_ASKFORSAVE);
1421 ret = MessageBox(sTemp, 0, MB_YESNOCANCEL | MB_ICONQUESTION);
1423 if (ret == IDYES)
1425 if (!FileSave())
1426 return;
1429 if ((ret == IDNO)||(ret == IDYES))
1431 WINDOWPLACEMENT wp;
1433 // before it is destroyed, save the position of the window
1434 wp.length = sizeof wp;
1436 if (GetWindowPlacement(&wp))
1439 if (IsIconic())
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);
1450 __super::OnClose();
1454 void CMainFrame::OnActivate(UINT nValue, CWnd* /*pwnd*/, BOOL /*bActivated?*/) {
1455 if (nValue != 0) // activated
1457 if (IsIconic())
1459 m_bCheckReload = TRUE;
1461 else
1462 CheckForReload();
1466 void CMainFrame::OnViewLinedown()
1468 OnViewLineUpDown(1);
1471 void CMainFrame::OnViewLineup()
1473 OnViewLineUpDown(-1);
1476 void CMainFrame::OnViewLineUpDown(int direction)
1478 if (m_pwndLeftView)
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)
1500 if (m_pwndLeftView)
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();
1554 else
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();
1572 else
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)
1606 return;
1607 CDiffColors::GetInstance().LoadRegistry();
1608 LoadViews(-1);
1611 void CMainFrame::ActivateFrame(int nCmdShow)
1613 // nCmdShow is the normal show mode this frame should be in
1614 // translate default nCmdShow (-1)
1615 if (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);
1626 if (nCmdShow != -1)
1628 // show the window as specified
1629 WINDOWPLACEMENT wp;
1631 if ( !ReadWindowPlacement(&wp) )
1633 ShowWindow(nCmdShow);
1635 else
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())
1653 return FALSE;
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);
1660 if ( nRead != 10 )
1661 return FALSE;
1662 pwp->length = sizeof(WINDOWPLACEMENT);
1664 return TRUE;
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)
1683 if (pCmdUI == NULL)
1684 return;
1685 BOOL bEnable = FALSE;
1686 if ((!m_bReadOnly)&&(m_Data.m_mergedFile.InUse()))
1688 if (IsViewGood(m_pwndBottomView)&&(m_pwndBottomView->m_pViewData))
1690 bEnable = TRUE;
1693 pCmdUI->Enable(bEnable);
1696 void CMainFrame::OnMergeMarkasresolved()
1698 if(HasConflictsWontKeep())
1699 return;
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))
1706 FileSave(false);
1707 m_bSaveRequired = false;
1710 MarkAsResolved();
1713 BOOL CMainFrame::MarkAsResolved()
1715 if (m_bReadOnly)
1716 return FALSE;
1717 if (!IsViewGood(m_pwndBottomView))
1718 return FALSE;
1720 CString cmd = _T("/command:resolve /path:\"");
1721 cmd += m_Data.m_mergedFile.GetFilename();
1722 cmd += _T("\" /closeonend:1 /noquestion /skipcheck /silent");
1723 if (resolveMsgWnd)
1725 CString s;
1726 s.Format(L" /resolvemsghwnd:%I64d /resolvemsgwparam:%I64d /resolvemsglparam:%I64d", (__int64)resolveMsgWnd, (__int64)resolveMsgWParam, (__int64)resolveMsgLParam);
1727 cmd += s;
1729 if(!CAppUtils::RunTortoiseGitProc(cmd))
1730 return FALSE;
1731 m_bSaveRequired = false;
1732 return TRUE;
1735 void CMainFrame::OnUpdateMergeNextconflict(CCmdUI *pCmdUI)
1737 BOOL bShow = FALSE;
1738 if (HasNextConflict(m_pwndBottomView))
1739 bShow = TRUE;
1740 else if (HasNextConflict(m_pwndRightView))
1741 bShow = TRUE;
1742 else if (HasNextConflict(m_pwndLeftView))
1743 bShow = TRUE;
1744 pCmdUI->Enable(bShow);
1747 bool CMainFrame::HasNextConflict(CBaseView* view)
1749 if (view == 0)
1750 return false;
1751 if (!view->IsTarget())
1752 return false;
1753 return view->HasNextConflict();
1756 void CMainFrame::OnUpdateMergePreviousconflict(CCmdUI *pCmdUI)
1758 BOOL bShow = FALSE;
1759 if (HasPrevConflict(m_pwndBottomView))
1760 bShow = TRUE;
1761 else if (HasPrevConflict(m_pwndRightView))
1762 bShow = TRUE;
1763 else if (HasPrevConflict(m_pwndLeftView))
1764 bShow = TRUE;
1765 pCmdUI->Enable(bShow);
1768 bool CMainFrame::HasPrevConflict(CBaseView* view)
1770 if (view == 0)
1771 return false;
1772 if (!view->IsTarget())
1773 return false;
1774 return view->HasPrevConflict();
1777 void CMainFrame::OnUpdateNavigateNextdifference(CCmdUI *pCmdUI)
1779 CBaseView* baseView = GetActiveBaseView();
1780 BOOL bShow = FALSE;
1781 if (baseView != 0)
1782 bShow = baseView->HasNextDiff();
1783 pCmdUI->Enable(bShow);
1786 void CMainFrame::OnUpdateNavigatePreviousdifference(CCmdUI *pCmdUI)
1788 CBaseView* baseView = GetActiveBaseView();
1789 BOOL bShow = FALSE;
1790 if (baseView != 0)
1791 bShow = baseView->HasPrevDiff();
1792 pCmdUI->Enable(bShow);
1795 void CMainFrame::OnUpdateNavigateNextinlinediff(CCmdUI *pCmdUI)
1797 BOOL bShow = FALSE;
1798 if (HasNextInlineDiff(m_pwndBottomView))
1799 bShow = TRUE;
1800 else if (HasNextInlineDiff(m_pwndRightView))
1801 bShow = TRUE;
1802 else if (HasNextInlineDiff(m_pwndLeftView))
1803 bShow = TRUE;
1804 pCmdUI->Enable(bShow);
1807 bool CMainFrame::HasNextInlineDiff(CBaseView* view)
1809 if (view == 0)
1810 return false;
1811 if (!view->IsTarget())
1812 return false;
1813 return view->HasNextInlineDiff();
1816 void CMainFrame::OnUpdateNavigatePrevinlinediff(CCmdUI *pCmdUI)
1818 BOOL bShow = FALSE;
1819 if (HasPrevInlineDiff(m_pwndBottomView))
1820 bShow = TRUE;
1821 else if (HasPrevInlineDiff(m_pwndRightView))
1822 bShow = TRUE;
1823 else if (HasPrevInlineDiff(m_pwndLeftView))
1824 bShow = TRUE;
1825 pCmdUI->Enable(bShow);
1828 bool CMainFrame::HasPrevInlineDiff(CBaseView* view)
1830 if (view == 0)
1831 return false;
1832 if (!view->IsTarget())
1833 return false;
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))
1843 RECT patchrect;
1844 m_dlgFilePatches.GetWindowRect(&patchrect);
1845 if (::IsWindow(m_hWnd))
1847 RECT thisrect;
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)
1861 BOOL bShow = FALSE;
1862 if ((m_pwndBottomView)&&(m_pwndBottomView->HasSelection()))
1863 bShow = TRUE;
1864 else if ((m_pwndRightView)&&(m_pwndRightView->HasSelection()))
1865 bShow = TRUE;
1866 else if ((m_pwndLeftView)&&(m_pwndLeftView->HasSelection()))
1867 bShow = TRUE;
1868 pCmdUI->Enable(bShow);
1871 void CMainFrame::OnUpdateEditPaste(CCmdUI *pCmdUI)
1873 BOOL bWritable = FALSE;
1874 if ((m_pwndBottomView)&&(m_pwndBottomView->IsWritable()))
1875 bWritable = TRUE;
1876 else if ((m_pwndRightView)&&(m_pwndRightView->IsWritable()))
1877 bWritable = TRUE;
1878 else if ((m_pwndLeftView)&&(m_pwndLeftView->IsWritable()))
1879 bWritable = TRUE;
1880 pCmdUI->Enable(bWritable && ::IsClipboardFormatAvailable(CF_TEXT));
1883 void CMainFrame::OnViewSwitchleft()
1885 int ret = IDNO;
1886 if (HasUnsavedEdits())
1888 CString sTemp;
1889 sTemp.LoadString(IDS_ASKFORSAVE);
1890 ret = MessageBox(sTemp, 0, MB_YESNOCANCEL | MB_ICONQUESTION);
1891 if (ret == IDYES)
1893 if (!FileSave())
1894 return;
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;
1910 LoadViews();
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
1948 if (bLock)
1950 return IDNO;
1952 bLock = true;
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)
1960 bLock = false;
1961 return IDNO;
1964 int idsMessage = HasUnsavedEdits() ? IDS_WARNMODIFIEDOUTSIDELOOSECHANGES : IDS_WARNMODIFIEDOUTSIDE;
1965 UINT ret = CMessageBox::Show(m_hWnd, idsMessage, IDS_APPNAME, MB_YESNO | MB_ICONQUESTION);
1967 if (ret == IDYES)
1969 CDiffColors::GetInstance().LoadRegistry();
1970 LoadViews(-1);
1972 else
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();
1992 else
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();
2004 bLock = false;
2005 return ret;
2008 int CMainFrame::CheckForSave()
2010 UINT ret = IDNO;
2011 if (HasUnsavedEdits())
2013 CString sTemp;
2014 sTemp.LoadString(IDS_WARNMODIFIEDLOOSECHANGES);
2015 ret = MessageBox(sTemp, 0, MB_YESNOCANCEL | MB_ICONQUESTION);
2017 if (ret == IDYES)
2019 if (!FileSave())
2020 ret = IDCANCEL;
2023 return ret;
2026 bool CMainFrame::HasUnsavedEdits() const
2028 return HasUnsavedEdits(m_pwndBottomView) || HasUnsavedEdits(m_pwndRightView) || m_bSaveRequired;
2031 bool CMainFrame::HasUnsavedEdits(const CBaseView* view)
2033 if(view == 0)
2034 return false;
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;
2046 if (m_pwndLeftView)
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;
2076 if (m_pwndLeftView)
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))
2109 bEnabled = false;
2110 else if (!IsViewGood(m_pwndRightView))
2111 bEnabled = false;
2112 else if (IsViewGood(m_pwndBottomView)) //no negation here
2113 bEnabled = false;
2114 pCmdUI->Enable(bEnabled);
2117 void CMainFrame::OnEditCreateunifieddifffile()
2119 CString origFile, modifiedFile;
2120 // the original file is the one on the left
2121 if (m_pwndLeftView)
2122 origFile = m_pwndLeftView->m_sFullFilePath;
2123 if (m_pwndRightView)
2124 modifiedFile = m_pwndRightView->m_sFullFilePath;
2125 if (origFile.IsEmpty() || modifiedFile.IsEmpty())
2126 return;
2128 CString outputFile;
2129 if(!TryGetFileName(outputFile))
2130 return;
2132 CAppUtils::CreateUnifiedDiff(origFile, modifiedFile, outputFile, true);
2135 void CMainFrame::OnUpdateViewLinediffbar(CCmdUI *pCmdUI)
2137 pCmdUI->SetCheck(m_bLineDiff);
2138 pCmdUI->Enable();
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);
2153 pCmdUI->Enable();
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)
2168 return;
2169 CRegDWORD regIgnoreWS = CRegDWORD(_T("Software\\TortoiseGitMerge\\IgnoreWS"));
2170 regIgnoreWS = 0;
2171 LoadViews(-1);
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)
2184 return;
2185 CRegDWORD regIgnoreWS = CRegDWORD(_T("Software\\TortoiseGitMerge\\IgnoreWS"));
2186 regIgnoreWS = 2;
2187 LoadViews(-1);
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)
2200 return;
2201 CRegDWORD regIgnoreWS = CRegDWORD(_T("Software\\TortoiseGitMerge\\IgnoreWS"));
2202 regIgnoreWS = 1;
2203 LoadViews(-1);
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;
2217 LoadViews(-1);
2220 void CMainFrame::OnUpdateViewMovedBlocks(CCmdUI *pCmdUI)
2222 pCmdUI->SetCheck(m_bViewMovedBlocks);
2223 BOOL bEnable = TRUE;
2224 if (IsViewGood(m_pwndBottomView))
2226 bEnable = FALSE;
2228 pCmdUI->Enable(bEnable);
2231 bool CMainFrame::HasConflictsWontKeep()
2233 const int nConflictLine = CheckResolved();
2234 if (nConflictLine < 0)
2235 return false;
2237 CString sTemp;
2238 sTemp.Format(IDS_ERR_MAINFRAME_FILEHASCONFLICTS, m_pwndBottomView->m_pViewData->GetLineNumber(nConflictLine)+1);
2239 if (MessageBox(sTemp, 0, MB_ICONERROR | MB_YESNO)==IDYES)
2240 return false;
2242 if (m_pwndBottomView)
2243 m_pwndBottomView->GoToLine(nConflictLine);
2244 return true;
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 );
2256 return activeBase;
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"));
2282 else
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"));
2295 else
2296 SetWindowText(L"TortoiseGitMerge");