Do not use GitAdminDir objects
[TortoiseGit.git] / src / TortoiseMerge / MainFrm.cpp
blobd2fad3f603ecfb100778f198b8e78aae6a9f4011
1 // TortoiseGitMerge - a Diff/Patch program
3 // Copyright (C) 2008-2015 - TortoiseGit
4 // Copyright (C) 2004-2015 - TortoiseSVN
5 // Copyright (C) 2012-2014 - 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 "SelectFileFilter.h"
36 #include "FormatMessageWrapper.h"
37 #include "TaskbarUUID.h"
38 #include "git2.h"
39 #include "SmartLibgit2Ref.h" // needs to be included after git2.h
40 #include "RegexFiltersDlg.h"
41 #include "SysInfo.h"
43 #ifdef _DEBUG
44 #define new DEBUG_NEW
45 #endif
47 CCustomMFCRibbonButton button1;
49 // CMainFrame
50 const UINT TaskBarButtonCreated = RegisterWindowMessage(L"TaskbarButtonCreated");
51 #define IDT_RELOADCHECKTIMER 123
53 IMPLEMENT_DYNCREATE(CMainFrame, CFrameWndEx)
55 BEGIN_MESSAGE_MAP(CMainFrame, CFrameWndEx)
56 ON_WM_CREATE()
57 ON_COMMAND_RANGE(ID_VIEW_APPLOOK_WIN7, ID_VIEW_APPLOOK_OFF_2007_AQUA, &CMainFrame::OnApplicationLook)
58 ON_UPDATE_COMMAND_UI_RANGE(IDC_STYLEBUTTON, ID_VIEW_APPLOOK_OFF_2007_AQUA, &CMainFrame::OnUpdateApplicationLook)
59 // Global help commands
60 ON_COMMAND(ID_HELP_FINDER, CFrameWndEx::OnHelpFinder)
61 ON_COMMAND(ID_HELP, CFrameWndEx::OnHelp)
62 ON_COMMAND(ID_CONTEXT_HELP, CFrameWndEx::OnContextHelp)
63 ON_COMMAND(ID_DEFAULT_HELP, CFrameWndEx::OnHelpFinder)
64 ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
65 ON_COMMAND(ID_VIEW_WHITESPACES, OnViewWhitespaces)
66 ON_WM_SIZE()
67 ON_COMMAND(ID_FILE_SAVE, OnFileSave)
68 ON_COMMAND(ID_FILE_SAVE_AS, OnFileSaveAs)
69 ON_UPDATE_COMMAND_UI(ID_FILE_SAVE, OnUpdateFileSave)
70 ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_AS, OnUpdateFileSaveAs)
71 ON_COMMAND(ID_VIEW_ONEWAYDIFF, OnViewOnewaydiff)
72 ON_UPDATE_COMMAND_UI(ID_VIEW_ONEWAYDIFF, OnUpdateViewOnewaydiff)
73 ON_UPDATE_COMMAND_UI(ID_VIEW_WHITESPACES, OnUpdateViewWhitespaces)
74 ON_COMMAND(ID_VIEW_OPTIONS, OnViewOptions)
75 ON_WM_CLOSE()
76 ON_WM_ACTIVATE()
77 ON_COMMAND(ID_FILE_RELOAD, OnFileReload)
78 ON_COMMAND(ID_VIEW_LINEDOWN, OnViewLinedown)
79 ON_COMMAND(ID_VIEW_LINEUP, OnViewLineup)
80 ON_COMMAND(ID_VIEW_MOVEDBLOCKS, OnViewMovedBlocks)
81 ON_UPDATE_COMMAND_UI(ID_VIEW_MOVEDBLOCKS, OnUpdateViewMovedBlocks)
82 ON_UPDATE_COMMAND_UI(ID_EDIT_MARKASRESOLVED, OnUpdateMergeMarkasresolved)
83 ON_COMMAND(ID_EDIT_MARKASRESOLVED, OnMergeMarkasresolved)
84 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_NEXTCONFLICT, OnUpdateMergeNextconflict)
85 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_PREVIOUSCONFLICT, OnUpdateMergePreviousconflict)
86 ON_WM_MOVE()
87 ON_WM_MOVING()
88 ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateEditCopy)
89 ON_COMMAND(ID_VIEW_SWITCHLEFT, OnViewSwitchleft)
90 ON_UPDATE_COMMAND_UI(ID_VIEW_SWITCHLEFT, OnUpdateViewSwitchleft)
91 ON_COMMAND(ID_VIEW_LINELEFT, &CMainFrame::OnViewLineleft)
92 ON_COMMAND(ID_VIEW_LINERIGHT, &CMainFrame::OnViewLineright)
93 ON_UPDATE_COMMAND_UI(ID_VIEW_SHOWFILELIST, &CMainFrame::OnUpdateViewShowfilelist)
94 ON_COMMAND(ID_VIEW_SHOWFILELIST, &CMainFrame::OnViewShowfilelist)
95 ON_COMMAND(ID_EDIT_USETHEIRBLOCK, &CMainFrame::OnEditUseTheirs)
96 ON_COMMAND(ID_EDIT_USEMYBLOCK, &CMainFrame::OnEditUseMine)
97 ON_COMMAND(ID_EDIT_USETHEIRTHENMYBLOCK, &CMainFrame::OnEditUseTheirsThenMine)
98 ON_COMMAND(ID_EDIT_USEMINETHENTHEIRBLOCK, &CMainFrame::OnEditUseMineThenTheirs)
99 ON_COMMAND(ID_EDIT_UNDO, &CMainFrame::OnEditUndo)
100 ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, &CMainFrame::OnUpdateEditUndo)
101 ON_COMMAND(ID_EDIT_ENABLE, &CMainFrame::OnEditEnable)
102 ON_UPDATE_COMMAND_UI(ID_EDIT_ENABLE, &CMainFrame::OnUpdateEditEnable)
103 ON_UPDATE_COMMAND_UI(ID_EDIT_USEMINETHENTHEIRBLOCK, &CMainFrame::OnUpdateEditUseminethentheirblock)
104 ON_UPDATE_COMMAND_UI(ID_EDIT_USEMYBLOCK, &CMainFrame::OnUpdateEditUsemyblock)
105 ON_UPDATE_COMMAND_UI(ID_EDIT_USETHEIRBLOCK, &CMainFrame::OnUpdateEditUsetheirblock)
106 ON_UPDATE_COMMAND_UI(ID_EDIT_USETHEIRTHENMYBLOCK, &CMainFrame::OnUpdateEditUsetheirthenmyblock)
107 ON_COMMAND(ID_VIEW_INLINEDIFFWORD, &CMainFrame::OnViewInlinediffword)
108 ON_UPDATE_COMMAND_UI(ID_VIEW_INLINEDIFFWORD, &CMainFrame::OnUpdateViewInlinediffword)
109 ON_COMMAND(ID_VIEW_INLINEDIFF, &CMainFrame::OnViewInlinediff)
110 ON_UPDATE_COMMAND_UI(ID_VIEW_INLINEDIFF, &CMainFrame::OnUpdateViewInlinediff)
111 ON_UPDATE_COMMAND_UI(ID_EDIT_CREATEUNIFIEDDIFFFILE, &CMainFrame::OnUpdateEditCreateunifieddifffile)
112 ON_COMMAND(ID_EDIT_CREATEUNIFIEDDIFFFILE, &CMainFrame::OnEditCreateunifieddifffile)
113 ON_UPDATE_COMMAND_UI(ID_VIEW_LINEDIFFBAR, &CMainFrame::OnUpdateViewLinediffbar)
114 ON_COMMAND(ID_VIEW_LINEDIFFBAR, &CMainFrame::OnViewLinediffbar)
115 ON_UPDATE_COMMAND_UI(ID_VIEW_LOCATORBAR, &CMainFrame::OnUpdateViewLocatorbar)
116 ON_COMMAND(ID_VIEW_LOCATORBAR, &CMainFrame::OnViewLocatorbar)
117 ON_COMMAND(ID_EDIT_USELEFTBLOCK, &CMainFrame::OnEditUseleftblock)
118 ON_UPDATE_COMMAND_UI(ID_USEBLOCKS, &CMainFrame::OnUpdateUseBlock)
119 ON_UPDATE_COMMAND_UI(ID_EDIT_USELEFTBLOCK, &CMainFrame::OnUpdateEditUseleftblock)
120 ON_COMMAND(ID_EDIT_USELEFTFILE, &CMainFrame::OnEditUseleftfile)
121 ON_UPDATE_COMMAND_UI(ID_EDIT_USELEFTFILE, &CMainFrame::OnUpdateEditUseleftfile)
122 ON_COMMAND(ID_EDIT_USEBLOCKFROMLEFTBEFORERIGHT, &CMainFrame::OnEditUseblockfromleftbeforeright)
123 ON_UPDATE_COMMAND_UI(ID_EDIT_USEBLOCKFROMLEFTBEFORERIGHT, &CMainFrame::OnUpdateEditUseblockfromleftbeforeright)
124 ON_COMMAND(ID_EDIT_USEBLOCKFROMRIGHTBEFORELEFT, &CMainFrame::OnEditUseblockfromrightbeforeleft)
125 ON_UPDATE_COMMAND_UI(ID_EDIT_USEBLOCKFROMRIGHTBEFORELEFT, &CMainFrame::OnUpdateEditUseblockfromrightbeforeleft)
126 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_NEXTDIFFERENCE, &CMainFrame::OnUpdateNavigateNextdifference)
127 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_PREVIOUSDIFFERENCE, &CMainFrame::OnUpdateNavigatePreviousdifference)
128 ON_COMMAND(ID_VIEW_COLLAPSED, &CMainFrame::OnViewCollapsed)
129 ON_UPDATE_COMMAND_UI(ID_VIEW_COLLAPSED, &CMainFrame::OnUpdateViewCollapsed)
130 ON_COMMAND(ID_VIEW_COMPAREWHITESPACES, &CMainFrame::OnViewComparewhitespaces)
131 ON_UPDATE_COMMAND_UI(ID_VIEW_COMPAREWHITESPACES, &CMainFrame::OnUpdateViewComparewhitespaces)
132 ON_COMMAND(ID_VIEW_IGNOREWHITESPACECHANGES, &CMainFrame::OnViewIgnorewhitespacechanges)
133 ON_UPDATE_COMMAND_UI(ID_VIEW_IGNOREWHITESPACECHANGES, &CMainFrame::OnUpdateViewIgnorewhitespacechanges)
134 ON_COMMAND(ID_VIEW_IGNOREALLWHITESPACECHANGES, &CMainFrame::OnViewIgnoreallwhitespacechanges)
135 ON_UPDATE_COMMAND_UI(ID_VIEW_IGNOREALLWHITESPACECHANGES, &CMainFrame::OnUpdateViewIgnoreallwhitespacechanges)
136 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_NEXTINLINEDIFF, &CMainFrame::OnUpdateNavigateNextinlinediff)
137 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_PREVINLINEDIFF, &CMainFrame::OnUpdateNavigatePrevinlinediff)
138 ON_COMMAND(ID_VIEW_WRAPLONGLINES, &CMainFrame::OnViewWraplonglines)
139 ON_UPDATE_COMMAND_UI(ID_VIEW_WRAPLONGLINES, &CMainFrame::OnUpdateViewWraplonglines)
140 ON_REGISTERED_MESSAGE( TaskBarButtonCreated, CMainFrame::OnTaskbarButtonCreated )
141 ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, &CMainFrame::OnUpdateEditPaste)
142 ON_COMMAND(ID_INDICATOR_LEFTVIEW, &CMainFrame::OnIndicatorLeftview)
143 ON_COMMAND(ID_INDICATOR_RIGHTVIEW, &CMainFrame::OnIndicatorRightview)
144 ON_COMMAND(ID_INDICATOR_BOTTOMVIEW, &CMainFrame::OnIndicatorBottomview)
145 ON_WM_TIMER()
146 ON_COMMAND(ID_VIEW_IGNORECOMMENTS, &CMainFrame::OnViewIgnorecomments)
147 ON_UPDATE_COMMAND_UI(ID_VIEW_IGNORECOMMENTS, &CMainFrame::OnUpdateViewIgnorecomments)
148 ON_COMMAND_RANGE(ID_REGEXFILTER, ID_REGEXFILTER+400, &CMainFrame::OnRegexfilter)
149 ON_UPDATE_COMMAND_UI_RANGE(ID_REGEXFILTER, ID_REGEXFILTER+400, &CMainFrame::OnUpdateViewRegexFilter)
150 ON_COMMAND(ID_INDICATOR_LEFTVIEWCOMBOENCODING, &CMainFrame::OnDummyEnabled)
151 ON_COMMAND(ID_INDICATOR_RIGHTVIEWCOMBOENCODING, &CMainFrame::OnDummyEnabled)
152 ON_COMMAND(ID_INDICATOR_BOTTOMVIEWCOMBOENCODING, &CMainFrame::OnDummyEnabled)
153 ON_COMMAND(ID_INDICATOR_LEFTVIEWCOMBOEOL, &CMainFrame::OnDummyEnabled)
154 ON_COMMAND(ID_INDICATOR_RIGHTVIEWCOMBOEOL, &CMainFrame::OnDummyEnabled)
155 ON_COMMAND(ID_INDICATOR_BOTTOMVIEWCOMBOEOL, &CMainFrame::OnDummyEnabled)
156 ON_COMMAND(ID_INDICATOR_LEFTVIEWCOMBOTABMODE, &CMainFrame::OnDummyEnabled)
157 ON_COMMAND(ID_INDICATOR_RIGHTVIEWCOMBOTABMODE, &CMainFrame::OnDummyEnabled)
158 ON_COMMAND(ID_INDICATOR_BOTTOMVIEWCOMBOTABMODE, &CMainFrame::OnDummyEnabled)
159 ON_COMMAND_RANGE(ID_INDICATOR_LEFTENCODINGSTART, ID_INDICATOR_LEFTENCODINGSTART+19, &CMainFrame::OnEncodingLeft)
160 ON_COMMAND_RANGE(ID_INDICATOR_RIGHTENCODINGSTART, ID_INDICATOR_RIGHTENCODINGSTART+19, &CMainFrame::OnEncodingRight)
161 ON_COMMAND_RANGE(ID_INDICATOR_BOTTOMENCODINGSTART, ID_INDICATOR_BOTTOMENCODINGSTART+19, &CMainFrame::OnEncodingBottom)
162 ON_COMMAND_RANGE(ID_INDICATOR_LEFTEOLSTART, ID_INDICATOR_LEFTEOLSTART+19, &CMainFrame::OnEOLLeft)
163 ON_COMMAND_RANGE(ID_INDICATOR_RIGHTEOLSTART, ID_INDICATOR_RIGHTEOLSTART+19, &CMainFrame::OnEOLRight)
164 ON_COMMAND_RANGE(ID_INDICATOR_BOTTOMEOLSTART, ID_INDICATOR_BOTTOMEOLSTART+19, &CMainFrame::OnEOLBottom)
165 ON_COMMAND_RANGE(ID_INDICATOR_LEFTTABMODESTART, ID_INDICATOR_LEFTTABMODESTART+19, &CMainFrame::OnTabModeLeft)
166 ON_COMMAND_RANGE(ID_INDICATOR_RIGHTTABMODESTART, ID_INDICATOR_RIGHTTABMODESTART+19, &CMainFrame::OnTabModeRight)
167 ON_COMMAND_RANGE(ID_INDICATOR_BOTTOMTABMODESTART, ID_INDICATOR_BOTTOMTABMODESTART+19, &CMainFrame::OnTabModeBottom)
168 ON_UPDATE_COMMAND_UI_RANGE(ID_INDICATOR_LEFTENCODINGSTART, ID_INDICATOR_LEFTENCODINGSTART+19, &CMainFrame::OnUpdateEncodingLeft)
169 ON_UPDATE_COMMAND_UI_RANGE(ID_INDICATOR_RIGHTENCODINGSTART, ID_INDICATOR_RIGHTENCODINGSTART+19, &CMainFrame::OnUpdateEncodingRight)
170 ON_UPDATE_COMMAND_UI_RANGE(ID_INDICATOR_BOTTOMENCODINGSTART, ID_INDICATOR_BOTTOMENCODINGSTART+19, &CMainFrame::OnUpdateEncodingBottom)
171 ON_UPDATE_COMMAND_UI_RANGE(ID_INDICATOR_LEFTEOLSTART, ID_INDICATOR_LEFTEOLSTART+19, &CMainFrame::OnUpdateEOLLeft)
172 ON_UPDATE_COMMAND_UI_RANGE(ID_INDICATOR_RIGHTEOLSTART, ID_INDICATOR_RIGHTEOLSTART+19, &CMainFrame::OnUpdateEOLRight)
173 ON_UPDATE_COMMAND_UI_RANGE(ID_INDICATOR_BOTTOMEOLSTART, ID_INDICATOR_BOTTOMEOLSTART+19, &CMainFrame::OnUpdateEOLBottom)
174 ON_UPDATE_COMMAND_UI_RANGE(ID_INDICATOR_LEFTTABMODESTART, ID_INDICATOR_LEFTTABMODESTART+19, &CMainFrame::OnUpdateTabModeLeft)
175 ON_UPDATE_COMMAND_UI_RANGE(ID_INDICATOR_RIGHTTABMODESTART, ID_INDICATOR_RIGHTTABMODESTART+19, &CMainFrame::OnUpdateTabModeRight)
176 ON_UPDATE_COMMAND_UI_RANGE(ID_INDICATOR_BOTTOMTABMODESTART, ID_INDICATOR_BOTTOMTABMODESTART+19, &CMainFrame::OnUpdateTabModeBottom)
177 END_MESSAGE_MAP()
179 static UINT indicators[] =
181 ID_SEPARATOR, // status line indicator
182 ID_INDICATOR_LEFTVIEW,
183 ID_INDICATOR_RIGHTVIEW,
184 ID_INDICATOR_BOTTOMVIEW,
185 ID_INDICATOR_CAPS,
186 ID_INDICATOR_NUM,
190 // CMainFrame construction/destruction
192 CMainFrame::CMainFrame()
193 : m_bInitSplitter(FALSE)
194 , m_bReversedPatch(FALSE)
195 , m_bHasConflicts(false)
196 , m_bInlineWordDiff(true)
197 , m_bLineDiff(true)
198 , m_bLocatorBar(true)
199 , m_nMoveMovesToIgnore(0)
200 , m_pwndLeftView(NULL)
201 , m_pwndRightView(NULL)
202 , m_pwndBottomView(NULL)
203 , m_bReadOnly(false)
204 , m_bBlame(false)
205 , m_bCheckReload(false)
206 , m_bSaveRequired(false)
207 , m_bSaveRequiredOnConflicts(false)
208 , m_bDeleteBaseTheirsMineOnClose(false)
209 , resolveMsgWnd(0)
210 , resolveMsgWParam(0)
211 , resolveMsgLParam(0)
212 , m_regWrapLines(L"Software\\TortoiseGitMerge\\WrapLines", 0)
213 , m_regViewModedBlocks(L"Software\\TortoiseGitMerge\\ViewMovedBlocks", TRUE)
214 , m_regOneWay(L"Software\\TortoiseGitMerge\\OnePane")
215 , m_regCollapsed(L"Software\\TortoiseGitMerge\\Collapsed", 0)
216 , m_regInlineDiff(L"Software\\TortoiseGitMerge\\DisplayBinDiff", TRUE)
217 , m_regUseRibbons(L"Software\\TortoiseGitMerge\\UseRibbons", TRUE)
218 , m_regUseTaskDialog(L"Software\\TortoiseGitMerge\\UseTaskDialog", TRUE)
219 , m_regIgnoreComments(_T("Software\\TortoiseGitMerge\\IgnoreComments"), FALSE)
220 , m_regexIndex(-1)
222 m_bOneWay = (0 != ((DWORD)m_regOneWay));
223 theApp.m_nAppLook = theApp.GetInt(_T("ApplicationLook"), ID_VIEW_APPLOOK_VS_2005);
224 m_bCollapsed = !!(DWORD)m_regCollapsed;
225 m_bViewMovedBlocks = !!(DWORD)m_regViewModedBlocks;
226 m_bWrapLines = !!(DWORD)m_regWrapLines;
227 m_bInlineDiff = !!m_regInlineDiff;
228 m_bUseRibbons = !!m_regUseRibbons;
229 #if _WIN64
230 if (SysInfo::Instance().IsXP())
231 m_bUseRibbons = FALSE;
232 #endif
233 m_bUseTaskDialog = CTaskDialog::IsSupported() && (DWORD)m_regUseTaskDialog;
234 CMFCVisualManagerWindows::m_b3DTabsXPTheme = TRUE;
237 CMainFrame::~CMainFrame()
241 LRESULT CMainFrame::OnTaskbarButtonCreated(WPARAM /*wParam*/, LPARAM /*lParam*/)
243 SetUUIDOverlayIcon(m_hWnd);
244 return 0;
248 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
250 if (CFrameWndEx::OnCreate(lpCreateStruct) == -1)
251 return -1;
253 OnApplicationLook(theApp.m_nAppLook);
255 if (m_bUseRibbons)
257 m_wndRibbonBar.Create(this);
258 m_wndRibbonBar.LoadFromResource(IDR_RIBBON);
260 // enable the dialog launch button on the view panel
261 CMFCRibbonCategory * pMainCat = m_wndRibbonBar.GetCategory(1);
262 if (pMainCat)
264 CMFCRibbonPanel * pPanel = pMainCat->GetPanel(3);
265 if (pPanel)
266 pPanel->EnableLaunchButton(ID_VIEW_OPTIONS);
268 // now replace all buttons with our custom button class
269 for (int i = 0; i < m_wndRibbonBar.GetCategoryCount(); ++i)
271 CMFCRibbonCategory * pCat = m_wndRibbonBar.GetCategory(i);
272 for (int j = 0; j < pCat->GetPanelCount(); ++j)
274 CMFCRibbonPanel * pPanel = pCat->GetPanel(j);
275 CList<UINT, UINT> lstItems;
276 pPanel->GetItemIDsList(lstItems);
277 while (!lstItems.IsEmpty())
279 UINT id = lstItems.GetHead();
280 lstItems.RemoveHead();
281 CMFCRibbonButton * pButton = dynamic_cast<CMFCRibbonButton*>(pPanel->FindByID(id));
282 if (pButton)
284 CCustomMFCRibbonButton * c = new CCustomMFCRibbonButton(id, pButton->GetText());
285 pPanel->ReplaceByID(id, c);
290 BuildRegexSubitems();
291 if (!m_wndRibbonStatusBar.Create(this))
293 TRACE0("Failed to create ribbon status bar\n");
294 return -1; // fail to create
296 m_wndRibbonStatusBar.AddElement(new CMFCRibbonStatusBarPane(ID_SEPARATOR, CString(MAKEINTRESOURCE(AFX_IDS_IDLEMESSAGE)), TRUE), L"");
298 std::unique_ptr<CMFCRibbonButtonsGroup> apBtnGroupLeft(new CMFCRibbonButtonsGroup);
299 apBtnGroupLeft->SetID(ID_INDICATOR_LEFTVIEW);
300 apBtnGroupLeft->AddButton(new CMFCRibbonStatusBarPane(ID_SEPARATOR, CString(MAKEINTRESOURCE(IDS_STATUSBAR_LEFTVIEW)), TRUE));
301 CMFCRibbonButton * pButton = new CMFCRibbonButton(ID_INDICATOR_LEFTVIEWCOMBOENCODING, L"");
302 FillEncodingButton(pButton, ID_INDICATOR_LEFTENCODINGSTART);
303 apBtnGroupLeft->AddButton(pButton);
304 pButton = new CMFCRibbonButton(ID_INDICATOR_LEFTVIEWCOMBOEOL, L"");
305 FillEOLButton(pButton, ID_INDICATOR_LEFTEOLSTART);
306 apBtnGroupLeft->AddButton(pButton);
307 pButton = new CMFCRibbonButton(ID_INDICATOR_LEFTVIEWCOMBOTABMODE, L"");
308 FillTabModeButton(pButton, ID_INDICATOR_LEFTTABMODESTART);
309 apBtnGroupLeft->AddButton(pButton);
310 apBtnGroupLeft->AddButton(new CMFCRibbonStatusBarPane(ID_INDICATOR_LEFTVIEW, L"", TRUE));
311 m_wndRibbonStatusBar.AddExtendedElement(apBtnGroupLeft.release(), L"");
313 std::unique_ptr<CMFCRibbonButtonsGroup> apBtnGroupRight(new CMFCRibbonButtonsGroup);
314 apBtnGroupRight->SetID(ID_INDICATOR_RIGHTVIEW);
315 apBtnGroupRight->AddButton(new CMFCRibbonStatusBarPane(ID_SEPARATOR, CString(MAKEINTRESOURCE(IDS_STATUSBAR_RIGHTVIEW)), TRUE));
316 pButton = new CMFCRibbonButton(ID_INDICATOR_RIGHTVIEWCOMBOENCODING, L"");
317 FillEncodingButton(pButton, ID_INDICATOR_RIGHTENCODINGSTART);
318 apBtnGroupRight->AddButton(pButton);
319 pButton = new CMFCRibbonButton(ID_INDICATOR_RIGHTVIEWCOMBOEOL, L"");
320 FillEOLButton(pButton, ID_INDICATOR_RIGHTEOLSTART);
321 apBtnGroupRight->AddButton(pButton);
322 pButton = new CMFCRibbonButton(ID_INDICATOR_RIGHTVIEWCOMBOTABMODE, L"");
323 FillTabModeButton(pButton, ID_INDICATOR_RIGHTTABMODESTART);
324 apBtnGroupRight->AddButton(pButton);
325 apBtnGroupRight->AddButton(new CMFCRibbonStatusBarPane(ID_INDICATOR_RIGHTVIEW, L"", TRUE));
326 m_wndRibbonStatusBar.AddExtendedElement(apBtnGroupRight.release(), L"");
328 else
330 if (!m_wndMenuBar.Create(this))
332 TRACE0("Failed to create menubar\n");
333 return -1; // fail to create
335 m_wndMenuBar.SetPaneStyle(m_wndMenuBar.GetPaneStyle() | CBRS_SIZE_DYNAMIC | CBRS_TOOLTIPS | CBRS_FLYBY);
337 // prevent the menu bar from taking the focus on activation
338 CMFCPopupMenu::SetForceMenuFocus(FALSE);
339 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))
341 TRACE0("Failed to create toolbar\n");
342 return -1; // fail to create
344 m_wndToolBar.SetWindowText(_T("Main"));
345 if (!m_wndStatusBar.Create(this) ||
346 !m_wndStatusBar.SetIndicators(indicators,
347 _countof(indicators)))
349 TRACE0("Failed to create status bar\n");
350 return -1; // fail to create
352 m_wndStatusBar.EnablePaneDoubleClick();
355 if (!m_wndLocatorBar.Create(this, IDD_DIFFLOCATOR,
356 CBRS_ALIGN_LEFT | CBRS_SIZE_FIXED, ID_VIEW_LOCATORBAR))
358 TRACE0("Failed to create dialogbar\n");
359 return -1; // fail to create
361 if (!m_wndLineDiffBar.Create(this, IDD_LINEDIFF,
362 CBRS_ALIGN_BOTTOM | CBRS_SIZE_FIXED, ID_VIEW_LINEDIFFBAR))
364 TRACE0("Failed to create dialogbar\n");
365 return -1; // fail to create
367 m_wndLocatorBar.m_pMainFrm = this;
368 m_wndLineDiffBar.m_pMainFrm = this;
370 EnableDocking(CBRS_ALIGN_ANY);
371 if (!m_bUseRibbons)
373 m_wndMenuBar.EnableDocking(CBRS_ALIGN_TOP);
374 m_wndToolBar.EnableDocking(CBRS_ALIGN_TOP);
375 DockPane(&m_wndMenuBar);
376 DockPane(&m_wndToolBar);
378 DockPane(&m_wndLocatorBar);
379 DockPane(&m_wndLineDiffBar);
380 ShowPane(&m_wndLocatorBar, true, false, true);
381 ShowPane(&m_wndLineDiffBar, true, false, true);
383 m_wndLocatorBar.EnableGripper(FALSE);
384 m_wndLineDiffBar.EnableGripper(FALSE);
386 return 0;
389 BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
391 if( !CFrameWndEx::PreCreateWindow(cs) )
392 return FALSE;
393 return TRUE;
396 void CMainFrame::OnApplicationLook(UINT id)
398 CWaitCursor wait;
400 theApp.m_nAppLook = id;
402 switch (theApp.m_nAppLook)
404 case ID_VIEW_APPLOOK_WIN_2000:
405 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManager));
406 m_wndRibbonBar.SetWindows7Look(FALSE);
407 break;
409 case ID_VIEW_APPLOOK_OFF_XP:
410 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOfficeXP));
411 m_wndRibbonBar.SetWindows7Look(FALSE);
412 break;
414 case ID_VIEW_APPLOOK_WIN_XP:
415 CMFCVisualManagerWindows::m_b3DTabsXPTheme = TRUE;
416 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));
417 m_wndRibbonBar.SetWindows7Look(FALSE);
418 break;
420 case ID_VIEW_APPLOOK_OFF_2003:
421 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2003));
422 CDockingManager::SetDockingMode(DT_SMART);
423 m_wndRibbonBar.SetWindows7Look(FALSE);
424 break;
426 case ID_VIEW_APPLOOK_VS_2005:
427 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerVS2005));
428 CDockingManager::SetDockingMode(DT_SMART);
429 m_wndRibbonBar.SetWindows7Look(FALSE);
430 break;
432 case ID_VIEW_APPLOOK_VS_2008:
433 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerVS2008));
434 CDockingManager::SetDockingMode(DT_SMART);
435 m_wndRibbonBar.SetWindows7Look(FALSE);
436 break;
438 case ID_VIEW_APPLOOK_WIN7:
439 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows7));
440 CDockingManager::SetDockingMode(DT_SMART);
441 m_wndRibbonBar.SetWindows7Look(TRUE);
442 break;
444 default:
445 switch (theApp.m_nAppLook)
447 case ID_VIEW_APPLOOK_OFF_2007_BLUE:
448 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_LunaBlue);
449 break;
451 case ID_VIEW_APPLOOK_OFF_2007_BLACK:
452 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_ObsidianBlack);
453 break;
455 case ID_VIEW_APPLOOK_OFF_2007_SILVER:
456 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_Silver);
457 break;
459 case ID_VIEW_APPLOOK_OFF_2007_AQUA:
460 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_Aqua);
461 break;
464 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2007));
465 CDockingManager::SetDockingMode(DT_SMART);
466 m_wndRibbonBar.SetWindows7Look(FALSE);
469 RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_UPDATENOW | RDW_FRAME | RDW_ERASE);
471 theApp.WriteInt(_T("ApplicationLook"), theApp.m_nAppLook);
474 void CMainFrame::OnUpdateApplicationLook(CCmdUI* pCmdUI)
476 pCmdUI->Enable();
477 pCmdUI->SetRadio(theApp.m_nAppLook == pCmdUI->m_nID);
481 // CMainFrame diagnostics
483 #ifdef _DEBUG
484 void CMainFrame::AssertValid() const
486 CFrameWndEx::AssertValid();
489 void CMainFrame::Dump(CDumpContext& dc) const
491 CFrameWndEx::Dump(dc);
494 #endif //_DEBUG
497 // CMainFrame message handlers
500 BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT /*lpcs*/, CCreateContext* pContext)
502 CRect cr;
503 GetClientRect( &cr);
506 // split into three panes:
507 // -------------
508 // | | |
509 // | | |
510 // |------------
511 // | |
512 // | |
513 // |------------
515 // create a splitter with 2 rows, 1 column
516 if (!m_wndSplitter.CreateStatic(this, 2, 1))
518 TRACE0("Failed to CreateStaticSplitter\n");
519 return FALSE;
522 // add the second splitter pane - which is a nested splitter with 2 columns
523 if (!m_wndSplitter2.CreateStatic(
524 &m_wndSplitter, // our parent window is the first splitter
525 1, 2, // the new splitter is 1 row, 2 columns
526 WS_CHILD | WS_VISIBLE | WS_BORDER, // style, WS_BORDER is needed
527 m_wndSplitter.IdFromRowCol(0, 0)
528 // new splitter is in the first row, 1st column of first splitter
531 TRACE0("Failed to create nested splitter\n");
532 return FALSE;
534 // add the first splitter pane - the default view in row 0
535 if (!m_wndSplitter.CreateView(1, 0,
536 RUNTIME_CLASS(CBottomView), CSize(cr.Width(), cr.Height()), pContext))
538 TRACE0("Failed to create first pane\n");
539 return FALSE;
541 m_pwndBottomView = (CBottomView *)m_wndSplitter.GetPane(1,0);
542 m_pwndBottomView->m_pwndLocator = &m_wndLocatorBar;
543 m_pwndBottomView->m_pwndLineDiffBar = &m_wndLineDiffBar;
544 if (m_bUseRibbons)
545 m_pwndBottomView->m_pwndRibbonStatusBar = &m_wndRibbonStatusBar;
546 else
547 m_pwndBottomView->m_pwndStatusBar = &m_wndStatusBar;
548 m_pwndBottomView->m_pMainFrame = this;
550 // now create the two views inside the nested splitter
552 if (!m_wndSplitter2.CreateView(0, 0,
553 RUNTIME_CLASS(CLeftView), CSize(cr.Width()/2, cr.Height()/2), pContext))
555 TRACE0("Failed to create second pane\n");
556 return FALSE;
558 m_pwndLeftView = (CLeftView *)m_wndSplitter2.GetPane(0,0);
559 m_pwndLeftView->m_pwndLocator = &m_wndLocatorBar;
560 m_pwndLeftView->m_pwndLineDiffBar = &m_wndLineDiffBar;
561 if (m_bUseRibbons)
562 m_pwndLeftView->m_pwndRibbonStatusBar = &m_wndRibbonStatusBar;
563 else
564 m_pwndLeftView->m_pwndStatusBar = &m_wndStatusBar;
565 m_pwndLeftView->m_pMainFrame = this;
567 if (!m_wndSplitter2.CreateView(0, 1,
568 RUNTIME_CLASS(CRightView), CSize(cr.Width()/2, cr.Height()/2), pContext))
570 TRACE0("Failed to create third pane\n");
571 return FALSE;
573 m_pwndRightView = (CRightView *)m_wndSplitter2.GetPane(0,1);
574 m_pwndRightView->m_pwndLocator = &m_wndLocatorBar;
575 m_pwndRightView->m_pwndLineDiffBar = &m_wndLineDiffBar;
576 if (m_bUseRibbons)
577 m_pwndRightView->m_pwndRibbonStatusBar = &m_wndRibbonStatusBar;
578 else
579 m_pwndRightView->m_pwndStatusBar = &m_wndStatusBar;
580 m_pwndRightView->m_pMainFrame = this;
581 m_bInitSplitter = TRUE;
583 m_dlgFilePatches.Create(IDD_FILEPATCHES, this);
584 UpdateLayout();
585 return TRUE;
588 // Callback function
589 BOOL CMainFrame::PatchFile(CString sFilePath, bool /*bContentMods*/, bool bPropMods, CString sVersion, BOOL bAutoPatch)
591 CString sDummy;
592 //"dry run" was successful, so save the patched file somewhere...
593 CString sTempFile = CTempFiles::Instance().GetTempFilePathString();
594 CString sRejectedFile, sBasePath;
595 if (m_Patch.GetPatchResult(sFilePath, sTempFile, sRejectedFile, sBasePath) < 0)
597 MessageBox(m_Patch.GetErrorMessage(), NULL, MB_ICONERROR);
598 return FALSE;
600 sFilePath = m_Patch.GetTargetPath() + _T("\\") + sFilePath;
601 sFilePath.Replace('/', '\\');
602 if (sBasePath.IsEmpty())
603 sBasePath = sFilePath;
604 if (m_bReversedPatch)
606 m_Data.m_baseFile.SetFileName(sTempFile);
607 CString temp;
608 temp.Format(_T("%s %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sFilePath), (LPCTSTR)m_Data.m_sPatchPatched);
609 m_Data.m_baseFile.SetDescriptiveName(temp);
610 m_Data.m_yourFile.SetFileName(sFilePath);
611 temp.Format(_T("%s %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sFilePath), (LPCTSTR)m_Data.m_sPatchOriginal);
612 m_Data.m_yourFile.SetDescriptiveName(temp);
613 m_Data.m_theirFile.SetOutOfUse();
614 m_Data.m_mergedFile.SetOutOfUse();
616 else
618 if ((!PathFileExists(sBasePath))||(PathIsDirectory(sBasePath)))
620 m_Data.m_baseFile.SetFileName(CTempFiles::Instance().GetTempFilePathString());
621 m_Data.m_baseFile.CreateEmptyFile();
623 else
625 m_Data.m_baseFile.SetFileName(sBasePath);
627 CString sDescription;
628 sDescription.Format(_T("%s %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sBasePath), (LPCTSTR)m_Data.m_sPatchOriginal);
629 m_Data.m_baseFile.SetDescriptiveName(sDescription);
630 if (sBasePath == sFilePath)
632 m_Data.m_yourFile.SetFileName(sTempFile);
633 CString temp;
634 temp.Format(_T("%s %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sBasePath), (LPCTSTR)m_Data.m_sPatchPatched);
635 m_Data.m_yourFile.SetDescriptiveName(temp);
636 m_Data.m_theirFile.SetOutOfUse();
638 else
640 if (!PathFileExists(sFilePath) || PathIsDirectory(sFilePath))
642 m_Data.m_yourFile.SetFileName(CTempFiles::Instance().GetTempFilePathString());
643 m_Data.m_yourFile.CreateEmptyFile();
644 CString temp;
645 temp.Format(_T("%s %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sFilePath), CString(MAKEINTRESOURCE(IDS_NOTFOUNDVIEWTITLEINDICATOR)));
646 m_Data.m_yourFile.SetDescriptiveName(temp);
648 else
649 m_Data.m_yourFile.SetFileName(sFilePath);
650 m_Data.m_theirFile.SetFileName(sTempFile);
651 CString temp;
652 temp.Format(_T("%s %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sFilePath), (LPCTSTR)m_Data.m_sPatchPatched);
653 m_Data.m_theirFile.SetDescriptiveName(temp);
655 m_Data.m_mergedFile.SetFileName(sFilePath);
656 m_Data.m_bPatchRequired = bPropMods;
658 TRACE(_T("comparing %s\nwith the patched result %s\n"), (LPCTSTR)sFilePath, (LPCTSTR)sTempFile);
660 LoadViews();
661 if (!sRejectedFile.IsEmpty())
663 #if 0 // TGIT TODO
664 // start TortoiseUDiff with the rejected hunks
665 CString sTitle;
666 sTitle.Format(IDS_TITLE_REJECTEDHUNKS, (LPCTSTR)CPathUtils::GetFileNameFromPath(sFilePath));
667 CAppUtils::StartUnifiedDiffViewer(sRejectedFile, sTitle);
668 #endif
670 if (bAutoPatch)
672 if (sBasePath != sFilePath && HasConflictsWontKeep())
673 return FALSE;
675 PatchSave();
677 return TRUE;
680 // Callback function
681 BOOL CMainFrame::DiffFiles(CString sURL1, CString sRev1, CString sURL2, CString sRev2)
683 CString tempfile1 = CTempFiles::Instance().GetTempFilePathString();
684 CString tempfile2 = CTempFiles::Instance().GetTempFilePathString();
686 ASSERT(tempfile1.Compare(tempfile2));
688 CString sTemp;
689 CSysProgressDlg progDlg;
690 sTemp.Format(IDS_GETVERSIONOFFILE, (LPCTSTR)sRev1);
691 progDlg.SetLine(1, sTemp, true);
692 progDlg.SetLine(2, sURL1, true);
693 sTemp.LoadString(IDS_GETVERSIONOFFILETITLE);
694 progDlg.SetTitle(sTemp);
695 progDlg.SetShowProgressBar(true);
696 progDlg.SetAnimation(IDR_DOWNLOAD);
697 progDlg.SetTime(FALSE);
698 progDlg.SetProgress(1,100);
699 progDlg.ShowModeless(this);
700 if (!CAppUtils::GetVersionedFile(sURL1, sRev1, tempfile1, &progDlg, m_hWnd))
702 progDlg.Stop();
703 CString sErrMsg;
704 sErrMsg.Format(IDS_ERR_MAINFRAME_FILEVERSIONNOTFOUND, (LPCTSTR)sRev1, (LPCTSTR)sURL1);
705 MessageBox(sErrMsg, NULL, MB_ICONERROR);
706 return FALSE;
708 sTemp.Format(IDS_GETVERSIONOFFILE, (LPCTSTR)sRev2);
709 progDlg.SetLine(1, sTemp, true);
710 progDlg.SetLine(2, sURL2, true);
711 progDlg.SetProgress(50, 100);
712 if (!CAppUtils::GetVersionedFile(sURL2, sRev2, tempfile2, &progDlg, m_hWnd))
714 progDlg.Stop();
715 CString sErrMsg;
716 sErrMsg.Format(IDS_ERR_MAINFRAME_FILEVERSIONNOTFOUND, (LPCTSTR)sRev2, (LPCTSTR)sURL2);
717 MessageBox(sErrMsg, NULL, MB_ICONERROR);
718 return FALSE;
720 progDlg.SetProgress(100,100);
721 progDlg.Stop();
722 CString temp;
723 temp.Format(_T("%s Revision %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sURL1), (LPCTSTR)sRev1);
724 m_Data.m_baseFile.SetFileName(tempfile1);
725 m_Data.m_baseFile.SetDescriptiveName(temp);
726 temp.Format(_T("%s Revision %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sURL2), (LPCTSTR)sRev2);
727 m_Data.m_yourFile.SetFileName(tempfile2);
728 m_Data.m_yourFile.SetDescriptiveName(temp);
730 LoadViews();
732 return TRUE;
735 void CMainFrame::OnFileOpen()
737 if (CheckForSave(CHFSR_OPEN)==IDCANCEL)
738 return;
739 return OnFileOpen(false);
742 void CMainFrame::OnFileOpen(bool fillyours)
744 COpenDlg dlg;
745 if (fillyours)
746 dlg.m_sBaseFile = m_Data.m_yourFile.GetFilename();
747 if (dlg.DoModal() != IDOK)
749 return;
751 m_dlgFilePatches.ShowWindow(SW_HIDE);
752 m_dlgFilePatches.Init(NULL, NULL, CString(), NULL);
753 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,
754 (LPCTSTR)dlg.m_sUnifiedDiffFile, (LPCTSTR)dlg.m_sPatchDirectory);
755 m_Data.m_baseFile.SetFileName(dlg.m_sBaseFile);
756 m_Data.m_theirFile.SetFileName(dlg.m_sTheirFile);
757 m_Data.m_yourFile.SetFileName(dlg.m_sYourFile);
758 m_Data.m_sDiffFile = dlg.m_sUnifiedDiffFile;
759 m_Data.m_sPatchPath = dlg.m_sPatchDirectory;
760 m_Data.m_mergedFile.SetOutOfUse();
761 CCrashReport::Instance().AddFile2(dlg.m_sBaseFile, NULL, _T("Basefile"), CR_AF_MAKE_FILE_COPY);
762 CCrashReport::Instance().AddFile2(dlg.m_sTheirFile, NULL, _T("Theirfile"), CR_AF_MAKE_FILE_COPY);
763 CCrashReport::Instance().AddFile2(dlg.m_sYourFile, NULL, _T("Yourfile"), CR_AF_MAKE_FILE_COPY);
764 CCrashReport::Instance().AddFile2(dlg.m_sUnifiedDiffFile, NULL, _T("Difffile"), CR_AF_MAKE_FILE_COPY);
766 if (!m_Data.IsBaseFileInUse() && m_Data.IsTheirFileInUse() && m_Data.IsYourFileInUse())
768 // a diff between two files means "Yours" against "Base", not "Theirs" against "Yours"
769 m_Data.m_baseFile.TransferDetailsFrom(m_Data.m_theirFile);
771 if (m_Data.IsBaseFileInUse() && m_Data.IsTheirFileInUse() && !m_Data.IsYourFileInUse())
773 // a diff between two files means "Yours" against "Base", not "Theirs" against "Base"
774 m_Data.m_yourFile.TransferDetailsFrom(m_Data.m_theirFile);
776 m_bSaveRequired = false;
778 LoadViews();
781 void CMainFrame::ClearViewNamesAndPaths()
783 m_pwndLeftView->m_sWindowName.Empty();
784 m_pwndLeftView->m_sFullFilePath.Empty();
785 m_pwndLeftView->m_sReflectedName.Empty();
786 m_pwndRightView->m_sWindowName.Empty();
787 m_pwndRightView->m_sFullFilePath.Empty();
788 m_pwndRightView->m_sReflectedName.Empty();
789 m_pwndBottomView->m_sWindowName.Empty();
790 m_pwndBottomView->m_sFullFilePath.Empty();
791 m_pwndBottomView->m_sReflectedName.Empty();
794 bool CMainFrame::LoadViews(int line)
796 LoadIgnoreCommentData();
797 m_Data.SetBlame(m_bBlame);
798 m_Data.SetMovedBlocks(m_bViewMovedBlocks);
799 m_bHasConflicts = false;
800 CBaseView* pwndActiveView = m_pwndLeftView;
801 int nOldLine = m_pwndRightView ? m_pwndRightView->m_nTopLine : -1;
802 int nOldLineNumber =
803 m_pwndRightView && m_pwndRightView->m_pViewData ?
804 m_pwndRightView->m_pViewData->GetLineNumber(m_pwndRightView->m_nTopLine) : -1;
805 POINT ptOldCaretPos = {-1, -1};
806 if (m_pwndRightView && m_pwndRightView->IsTarget())
807 ptOldCaretPos = m_pwndRightView->GetCaretPosition();
808 if (m_pwndBottomView && m_pwndBottomView->IsTarget())
809 ptOldCaretPos = m_pwndBottomView->GetCaretPosition();
810 CString sExt = CPathUtils::GetFileExtFromPath(m_Data.m_baseFile.GetFilename()).MakeLower();
811 sExt.TrimLeft(L".");
812 auto sC = m_IgnoreCommentsMap.find(sExt);
813 if (sC == m_IgnoreCommentsMap.end())
815 sExt = CPathUtils::GetFileExtFromPath(m_Data.m_yourFile.GetFilename()).MakeLower();
816 sC = m_IgnoreCommentsMap.find(sExt);
817 if (sC == m_IgnoreCommentsMap.end())
819 sExt = CPathUtils::GetFileExtFromPath(m_Data.m_theirFile.GetFilename()).MakeLower();
820 sC = m_IgnoreCommentsMap.find(sExt);
823 if (sC != m_IgnoreCommentsMap.end())
824 m_Data.SetCommentTokens(std::get<0>(sC->second), std::get<1>(sC->second), std::get<2>(sC->second));
825 else
826 m_Data.SetCommentTokens(L"", L"", L"");
827 if (!m_Data.Load())
829 m_pwndLeftView->BuildAllScreen2ViewVector();
830 m_pwndLeftView->DocumentUpdated();
831 m_pwndRightView->DocumentUpdated();
832 m_pwndBottomView->DocumentUpdated();
833 m_wndLocatorBar.DocumentUpdated();
834 m_wndLineDiffBar.DocumentUpdated();
835 ::MessageBox(m_hWnd, m_Data.GetError(), _T("TortoiseGitMerge"), MB_ICONERROR);
836 m_Data.m_mergedFile.SetOutOfUse();
837 m_bSaveRequired = false;
838 return false;
840 SetWindowTitle();
841 m_pwndLeftView->BuildAllScreen2ViewVector();
842 m_pwndLeftView->DocumentUpdated();
843 m_pwndRightView->DocumentUpdated();
844 m_pwndBottomView->DocumentUpdated();
845 m_wndLocatorBar.DocumentUpdated();
846 m_wndLineDiffBar.DocumentUpdated();
848 m_pwndLeftView->SetWritable(false);
849 m_pwndLeftView->SetWritableIsChangable(false);
850 m_pwndLeftView->SetTarget(false);
851 m_pwndRightView->SetWritable(false);
852 m_pwndRightView->SetWritableIsChangable(false);
853 m_pwndRightView->SetTarget(false);
854 m_pwndBottomView->SetWritable(false);
855 m_pwndBottomView->SetWritableIsChangable(false);
856 m_pwndBottomView->SetTarget(false);
858 if (!m_Data.IsBaseFileInUse())
860 CSysProgressDlg progDlg;
861 if (m_Data.IsYourFileInUse() && m_Data.IsTheirFileInUse())
863 m_Data.m_baseFile.TransferDetailsFrom(m_Data.m_theirFile);
865 else if ((!m_Data.m_sDiffFile.IsEmpty())&&(!m_Patch.Init(m_Data.m_sDiffFile, m_Data.m_sPatchPath, &progDlg)))
867 progDlg.Stop();
868 ClearViewNamesAndPaths();
869 MessageBox(m_Patch.GetErrorMessage(), NULL, MB_ICONERROR);
870 m_bSaveRequired = false;
871 return false;
873 progDlg.Stop();
874 if (m_Patch.GetNumberOfFiles() > 0)
876 CString betterpatchpath = m_Patch.CheckPatchPath(m_Data.m_sPatchPath);
877 if (betterpatchpath.CompareNoCase(m_Data.m_sPatchPath)!=0)
879 CString msg;
880 msg.Format(IDS_WARNBETTERPATCHPATHFOUND, (LPCTSTR)m_Data.m_sPatchPath, (LPCTSTR)betterpatchpath);
881 if (m_bUseTaskDialog)
883 CTaskDialog taskdlg(msg,
884 CString(MAKEINTRESOURCE(IDS_WARNBETTERPATCHPATHFOUND_TASK2)),
885 L"TortoiseGitMerge",
887 TDF_ENABLE_HYPERLINKS|TDF_USE_COMMAND_LINKS|TDF_ALLOW_DIALOG_CANCELLATION|TDF_POSITION_RELATIVE_TO_WINDOW);
888 CString task3;
889 WCHAR t3[MAX_PATH] = {0};
890 CString cp = betterpatchpath.Left(MAX_PATH-1);
891 PathCompactPathEx(t3, cp, 50, 0);
892 task3.Format(IDS_WARNBETTERPATCHPATHFOUND_TASK3, t3);
893 taskdlg.AddCommandControl(1, task3);
894 CString task4;
895 WCHAR t4[MAX_PATH] = {0};
896 cp = m_Data.m_sPatchPath.Left(MAX_PATH-1);
897 PathCompactPathEx(t4, cp, 50, 0);
898 task4.Format(IDS_WARNBETTERPATCHPATHFOUND_TASK4, t4);
899 taskdlg.AddCommandControl(2, task4);
900 taskdlg.SetDefaultCommandControl(1);
901 taskdlg.SetMainIcon(TD_INFORMATION_ICON);
902 taskdlg.SetCommonButtons(TDCBF_CANCEL_BUTTON);
903 if (taskdlg.DoModal(m_hWnd) == 1)
905 m_Data.m_sPatchPath = betterpatchpath;
906 m_Patch.Init(m_Data.m_sDiffFile, m_Data.m_sPatchPath, &progDlg);
909 else if (::MessageBox(m_hWnd, msg, _T("TortoiseGitMerge"), MB_ICONQUESTION | MB_YESNO)==IDYES)
911 m_Data.m_sPatchPath = betterpatchpath;
912 m_Patch.Init(m_Data.m_sDiffFile, m_Data.m_sPatchPath, &progDlg);
915 m_dlgFilePatches.Init(&m_Patch, this, m_Data.m_sPatchPath, this);
916 m_dlgFilePatches.ShowWindow(SW_SHOW);
917 ClearViewNamesAndPaths();
918 if (!m_wndSplitter.IsRowHidden(1))
919 m_wndSplitter.HideRow(1);
920 m_pwndLeftView->SetHidden(FALSE);
921 m_pwndRightView->SetHidden(FALSE);
922 m_pwndBottomView->SetHidden(TRUE);
925 if (m_Data.IsBaseFileInUse() && !m_Data.IsYourFileInUse() && m_Data.IsTheirFileInUse())
927 m_Data.m_yourFile.TransferDetailsFrom(m_Data.m_theirFile);
929 if (m_Data.IsBaseFileInUse() && m_Data.IsYourFileInUse() && !m_Data.IsTheirFileInUse())
931 //diff between YOUR and BASE
932 if (m_bOneWay)
934 pwndActiveView = m_pwndLeftView;
935 if (!m_wndSplitter2.IsColumnHidden(1))
936 m_wndSplitter2.HideColumn(1);
938 m_pwndLeftView->m_pViewData = &m_Data.m_YourBaseBoth;
939 m_pwndLeftView->SetTextType(m_Data.m_arYourFile.GetUnicodeType());
940 m_pwndLeftView->SetLineEndingStyle(m_Data.m_arYourFile.GetLineEndings());
941 m_pwndLeftView->m_sWindowName = m_Data.m_baseFile.GetWindowName() + _T(" - ") + m_Data.m_yourFile.GetWindowName();
942 m_pwndLeftView->m_sFullFilePath = m_Data.m_baseFile.GetFilename() + _T(" - ") + m_Data.m_yourFile.GetFilename();
943 m_pwndLeftView->m_sReflectedName = m_Data.m_yourFile.GetReflectedName();
944 m_pwndLeftView->m_pWorkingFile = &m_Data.m_yourFile;
945 m_pwndLeftView->SetTarget();
946 m_pwndLeftView->SetWritableIsChangable(true);
948 m_pwndRightView->m_pViewData = NULL;
949 m_pwndRightView->m_pWorkingFile = NULL;
950 m_pwndBottomView->m_pViewData = NULL;
951 m_pwndBottomView->m_pWorkingFile = NULL;
953 if (!m_wndSplitter.IsRowHidden(1))
954 m_wndSplitter.HideRow(1);
955 m_pwndLeftView->SetHidden(FALSE);
956 m_pwndRightView->SetHidden(TRUE);
957 m_pwndBottomView->SetHidden(TRUE);
958 ::SetWindowPos(m_pwndLeftView->m_hWnd, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
960 else
962 pwndActiveView = m_pwndRightView;
963 if (m_wndSplitter2.IsColumnHidden(1))
964 m_wndSplitter2.ShowColumn();
966 m_pwndLeftView->m_pViewData = &m_Data.m_YourBaseLeft;
967 m_pwndLeftView->SetTextType(m_Data.m_arBaseFile.GetUnicodeType());
968 m_pwndLeftView->SetLineEndingStyle(m_Data.m_arBaseFile.GetLineEndings());
969 m_pwndLeftView->m_sWindowName = m_Data.m_baseFile.GetWindowName();
970 m_pwndLeftView->m_sFullFilePath = m_Data.m_baseFile.GetFilename();
971 m_pwndLeftView->m_sConvertedFilePath = m_Data.m_baseFile.GetConvertedFileName();
972 m_pwndLeftView->m_sReflectedName = m_Data.m_baseFile.GetReflectedName();
973 m_pwndLeftView->m_pWorkingFile = &m_Data.m_baseFile;
974 m_pwndLeftView->SetWritableIsChangable(true);
976 m_pwndRightView->m_pViewData = &m_Data.m_YourBaseRight;
977 m_pwndRightView->SetTextType(m_Data.m_arYourFile.GetUnicodeType());
978 m_pwndRightView->SetLineEndingStyle(m_Data.m_arYourFile.GetLineEndings());
979 m_pwndRightView->m_sWindowName = m_Data.m_yourFile.GetWindowName();
980 m_pwndRightView->m_sFullFilePath = m_Data.m_yourFile.GetFilename();
981 m_pwndRightView->m_sConvertedFilePath = m_Data.m_yourFile.GetConvertedFileName();
982 m_pwndRightView->m_sReflectedName = m_Data.m_yourFile.GetReflectedName();
983 m_pwndRightView->m_pWorkingFile = &m_Data.m_yourFile;
984 m_pwndRightView->SetWritable();
985 m_pwndRightView->SetTarget();
987 m_pwndBottomView->m_pViewData = NULL;
988 m_pwndBottomView->m_pWorkingFile = NULL;
990 if (!m_wndSplitter.IsRowHidden(1))
991 m_wndSplitter.HideRow(1);
992 m_pwndLeftView->SetHidden(FALSE);
993 m_pwndRightView->SetHidden(FALSE);
994 m_pwndBottomView->SetHidden(TRUE);
996 bool hasMods, hasConflicts, hasWhitespaceMods;
997 pwndActiveView->CheckModifications(hasMods, hasConflicts, hasWhitespaceMods);
998 if (!hasMods && !hasConflicts)
1000 // files appear identical, show a dialog informing the user that there are or might
1001 // be other differences
1002 bool hasEncodingDiff = m_Data.m_arBaseFile.GetUnicodeType() != m_Data.m_arYourFile.GetUnicodeType();
1003 bool hasEOLDiff = m_Data.m_arBaseFile.GetLineEndings() != m_Data.m_arYourFile.GetLineEndings();
1004 if (hasWhitespaceMods || hasEncodingDiff || hasEOLDiff)
1006 // text is identical, but the files do not match
1007 CString sWarning(MAKEINTRESOURCE(IDS_TEXTIDENTICAL_MAIN));
1008 CString sWhitespace(MAKEINTRESOURCE(IDS_TEXTIDENTICAL_WHITESPACE));
1009 CString sEncoding(MAKEINTRESOURCE(IDS_TEXTIDENTICAL_ENCODING));
1010 CString sEOL(MAKEINTRESOURCE(IDS_TEXTIDENTICAL_EOL));
1011 if (hasWhitespaceMods)
1013 sWarning += L"\r\n";
1014 sWarning += sWhitespace;
1016 if (hasEncodingDiff)
1018 sWarning += L"\r\n";
1019 sWarning += sEncoding;
1020 sWarning += L" (";
1021 sWarning += m_Data.m_arBaseFile.GetEncodingName(m_Data.m_arBaseFile.GetUnicodeType());
1022 sWarning += L", ";
1023 sWarning += m_Data.m_arYourFile.GetEncodingName(m_Data.m_arYourFile.GetUnicodeType());
1024 sWarning += L")";
1026 if (hasEOLDiff)
1028 sWarning += L"\r\n";
1029 sWarning += sEOL;
1031 AfxMessageBox(sWarning, MB_ICONINFORMATION);
1035 else if (m_Data.IsBaseFileInUse() && m_Data.IsYourFileInUse() && m_Data.IsTheirFileInUse())
1037 //diff between THEIR, YOUR and BASE
1038 m_pwndBottomView->SetWritable();
1039 m_pwndBottomView->SetTarget();
1040 pwndActiveView = m_pwndBottomView;
1042 m_pwndLeftView->m_pViewData = &m_Data.m_TheirBaseBoth;
1043 m_pwndLeftView->SetTextType(m_Data.m_arTheirFile.GetUnicodeType());
1044 m_pwndLeftView->SetLineEndingStyle(m_Data.m_arTheirFile.GetLineEndings());
1045 m_pwndLeftView->m_sWindowName.LoadString(IDS_VIEWTITLE_THEIRS);
1046 m_pwndLeftView->m_sWindowName += _T(" - ") + m_Data.m_theirFile.GetWindowName();
1047 m_pwndLeftView->m_sFullFilePath = m_Data.m_theirFile.GetFilename();
1048 m_pwndLeftView->m_sConvertedFilePath = m_Data.m_theirFile.GetConvertedFileName();
1049 m_pwndLeftView->m_sReflectedName = m_Data.m_theirFile.GetReflectedName();
1050 m_pwndLeftView->m_pWorkingFile = &m_Data.m_theirFile;
1052 m_pwndRightView->m_pViewData = &m_Data.m_YourBaseBoth;
1053 m_pwndRightView->SetTextType(m_Data.m_arYourFile.GetUnicodeType());
1054 m_pwndRightView->SetLineEndingStyle(m_Data.m_arYourFile.GetLineEndings());
1055 m_pwndRightView->m_sWindowName.LoadString(IDS_VIEWTITLE_MINE);
1056 m_pwndRightView->m_sWindowName += _T(" - ") + m_Data.m_yourFile.GetWindowName();
1057 m_pwndRightView->m_sFullFilePath = m_Data.m_yourFile.GetFilename();
1058 m_pwndRightView->m_sConvertedFilePath = m_Data.m_yourFile.GetConvertedFileName();
1059 m_pwndRightView->m_sReflectedName = m_Data.m_yourFile.GetReflectedName();
1060 m_pwndRightView->m_pWorkingFile = &m_Data.m_yourFile;
1062 m_pwndBottomView->m_pViewData = &m_Data.m_Diff3;
1063 m_pwndBottomView->SetTextType(m_Data.m_arTheirFile.GetUnicodeType());
1064 m_pwndBottomView->SetLineEndingStyle(m_Data.m_arTheirFile.GetLineEndings());
1065 m_pwndBottomView->m_sWindowName.LoadString(IDS_VIEWTITLE_MERGED);
1066 m_pwndBottomView->m_sWindowName += _T(" - ") + m_Data.m_mergedFile.GetWindowName();
1067 m_pwndBottomView->m_sFullFilePath = m_Data.m_mergedFile.GetFilename();
1068 m_pwndBottomView->m_sConvertedFilePath = m_Data.m_mergedFile.GetConvertedFileName();
1069 m_pwndBottomView->m_sReflectedName = m_Data.m_mergedFile.GetReflectedName();
1070 m_pwndBottomView->m_pWorkingFile = &m_Data.m_mergedFile;
1072 if (m_wndSplitter2.IsColumnHidden(1))
1073 m_wndSplitter2.ShowColumn();
1074 if (m_wndSplitter.IsRowHidden(1))
1075 m_wndSplitter.ShowRow();
1076 m_pwndLeftView->SetHidden(FALSE);
1077 m_pwndRightView->SetHidden(FALSE);
1078 m_pwndBottomView->SetHidden(FALSE);
1079 // in three pane view, hide the line diff bar
1080 m_wndLineDiffBar.ShowPane(false, false, true);
1081 m_wndLineDiffBar.DocumentUpdated();
1083 if (!m_Data.m_mergedFile.InUse())
1085 m_Data.m_mergedFile.SetFileName(m_Data.m_yourFile.GetFilename());
1087 m_pwndLeftView->BuildAllScreen2ViewVector();
1088 m_pwndLeftView->DocumentUpdated();
1089 m_pwndRightView->DocumentUpdated();
1090 m_pwndBottomView->DocumentUpdated();
1091 m_wndLocatorBar.DocumentUpdated();
1092 m_wndLineDiffBar.DocumentUpdated();
1093 UpdateLayout();
1094 SetActiveView(pwndActiveView);
1096 if ((line >= -1) && m_pwndRightView->m_pViewData)
1098 int n = line == -1 ? min( nOldLineNumber, nOldLine ) : line;
1099 if (n >= 0)
1100 n = m_pwndRightView->m_pViewData->FindLineNumber(n);
1101 if (n < 0)
1102 n = nOldLine;
1104 m_pwndRightView->ScrollAllToLine(n);
1105 POINT p;
1106 p.x = 0;
1107 p.y = n;
1108 if ((ptOldCaretPos.x >= 0) || (ptOldCaretPos.y >= 0))
1109 p = ptOldCaretPos;
1110 m_pwndLeftView->SetCaretPosition(p);
1111 m_pwndRightView->SetCaretPosition(p);
1112 m_pwndBottomView->SetCaretPosition(p);
1113 m_pwndBottomView->ScrollToChar(0);
1114 m_pwndLeftView->ScrollToChar(0);
1115 m_pwndRightView->ScrollToChar(0);
1117 else
1119 CRegDWORD regFirstDiff = CRegDWORD(_T("Software\\TortoiseGitMerge\\FirstDiffOnLoad"), TRUE);
1120 CRegDWORD regFirstConflict = CRegDWORD(_T("Software\\TortoiseGitMerge\\FirstConflictOnLoad"), TRUE);
1121 bool bGoFirstDiff = (0 != (DWORD)regFirstDiff);
1122 bool bGoFirstConflict = (0 != (DWORD)regFirstConflict);
1123 if (bGoFirstConflict && (CheckResolved()>=0))
1125 pwndActiveView->GoToFirstConflict();
1126 // Ignore the first few Mouse Move messages, so that the line diff stays on
1127 // the first diff line until the user actually moves the mouse
1128 m_nMoveMovesToIgnore = MOVESTOIGNORE;
1130 else if (bGoFirstDiff)
1132 pwndActiveView->GoToFirstDifference();
1133 // Ignore the first few Mouse Move messages, so that the line diff stays on
1134 // the first diff line until the user actually moves the mouse
1135 m_nMoveMovesToIgnore = MOVESTOIGNORE;
1137 else
1139 // Avoid incorrect rendering of active pane.
1140 m_pwndBottomView->ScrollToChar(0);
1141 m_pwndLeftView->ScrollToChar(0);
1142 m_pwndRightView->ScrollToChar(0);
1145 CheckResolved();
1146 if (m_bHasConflicts && !m_bSaveRequiredOnConflicts)
1147 m_bSaveRequired = false;
1148 CUndo::GetInstance().Clear();
1149 return true;
1152 void CMainFrame::UpdateLayout()
1154 if (m_bInitSplitter)
1156 m_wndSplitter.CenterSplitter();
1157 m_wndSplitter2.CenterSplitter();
1161 void CMainFrame::OnSize(UINT nType, int cx, int cy)
1163 CFrameWndEx::OnSize(nType, cx, cy);
1164 if (m_bInitSplitter && nType != SIZE_MINIMIZED)
1166 if (m_wndSplitter.GetSafeHwnd())
1168 if (m_wndSplitter.HasOldRowSize() && (m_wndSplitter.GetOldRowCount() == 2))
1170 int oldTotal = m_wndSplitter.GetOldRowSize(0) + m_wndSplitter.GetOldRowSize(1);
1171 if (oldTotal)
1173 int cxCur0, cxCur1, cxMin0, cxMin1;
1174 m_wndSplitter.GetRowInfo(0, cxCur0, cxMin0);
1175 m_wndSplitter.GetRowInfo(1, cxCur1, cxMin1);
1176 cxCur0 = m_wndSplitter.GetOldRowSize(0) * (cxCur0 + cxCur1) / oldTotal;
1177 cxCur1 = m_wndSplitter.GetOldRowSize(1) * (cxCur0 + cxCur1) / oldTotal;
1178 m_wndSplitter.SetRowInfo(0, cxCur0, 0);
1179 m_wndSplitter.SetRowInfo(1, cxCur1, 0);
1180 m_wndSplitter.RecalcLayout();
1184 if (m_wndSplitter2.HasOldColSize() && (m_wndSplitter2.GetOldColCount() == 2))
1186 int oldTotal = m_wndSplitter2.GetOldColSize(0) + m_wndSplitter2.GetOldColSize(1);
1187 if (oldTotal)
1189 int cyCur0, cyCur1, cyMin0, cyMin1;
1190 m_wndSplitter2.GetColumnInfo(0, cyCur0, cyMin0);
1191 m_wndSplitter2.GetColumnInfo(1, cyCur1, cyMin1);
1192 cyCur0 = m_wndSplitter2.GetOldColSize(0) * (cyCur0 + cyCur1) / oldTotal;
1193 cyCur1 = m_wndSplitter2.GetOldColSize(1) * (cyCur0 + cyCur1) / oldTotal;
1194 m_wndSplitter2.SetColumnInfo(0, cyCur0, 0);
1195 m_wndSplitter2.SetColumnInfo(1, cyCur1, 0);
1196 m_wndSplitter2.RecalcLayout();
1201 if ((nType == SIZE_RESTORED)&&m_bCheckReload)
1203 m_bCheckReload = false;
1204 CheckForReload();
1206 #if _MSC_VER < 1800
1207 // workaround for ribbon interface when the task bar is on the left or top
1208 // The bug has been fixed in VS2013
1209 // http://connect.microsoft.com/VisualStudio/feedback/details/791229/cmfcribbonbar-app-does-not-maximize-correctly-if-windows-7-taskbar-is-docked-on-left
1210 if (nType == SIZE_MAXIMIZED)
1212 HMONITOR hMon = MonitorFromWindow(this->m_hWnd, MONITOR_DEFAULTTONEAREST);
1213 MONITORINFOEX mix;
1214 mix.cbSize = sizeof(MONITORINFOEX);
1215 bool primary = true; // assume primary monitor
1216 CRect rect(0, 0, 0, 0);
1217 if (GetMonitorInfo(hMon, &mix))
1219 primary = (mix.dwFlags == MONITORINFOF_PRIMARY);
1220 rect = mix.rcWork;
1222 else
1224 ::SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0);
1226 if (primary)
1228 WINDOWPLACEMENT wp;
1229 GetWindowPlacement(&wp);
1230 if (wp.ptMaxPosition.x || wp.ptMaxPosition.y)
1232 wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;
1233 SetWindowPlacement(&wp);
1236 else
1238 MoveWindow(rect);
1241 #endif
1244 void CMainFrame::OnViewWhitespaces()
1246 CRegDWORD regViewWhitespaces = CRegDWORD(_T("Software\\TortoiseGitMerge\\ViewWhitespaces"), 1);
1247 BOOL bViewWhitespaces = regViewWhitespaces;
1248 if (m_pwndLeftView)
1249 bViewWhitespaces = m_pwndLeftView->m_bViewWhitespace;
1251 bViewWhitespaces = !bViewWhitespaces;
1252 regViewWhitespaces = bViewWhitespaces;
1253 if (m_pwndLeftView)
1255 m_pwndLeftView->m_bViewWhitespace = bViewWhitespaces;
1256 m_pwndLeftView->Invalidate();
1258 if (m_pwndRightView)
1260 m_pwndRightView->m_bViewWhitespace = bViewWhitespaces;
1261 m_pwndRightView->Invalidate();
1263 if (m_pwndBottomView)
1265 m_pwndBottomView->m_bViewWhitespace = bViewWhitespaces;
1266 m_pwndBottomView->Invalidate();
1270 void CMainFrame::OnUpdateViewWhitespaces(CCmdUI *pCmdUI)
1272 if (m_pwndLeftView)
1273 pCmdUI->SetCheck(m_pwndLeftView->m_bViewWhitespace);
1276 void CMainFrame::OnViewCollapsed()
1278 m_regCollapsed = !(DWORD)m_regCollapsed;
1279 m_bCollapsed = !!(DWORD)m_regCollapsed;
1281 OnViewTextFoldUnfold();
1282 m_wndLocatorBar.Invalidate();
1285 void CMainFrame::OnUpdateViewCollapsed(CCmdUI *pCmdUI)
1287 pCmdUI->SetCheck(m_bCollapsed);
1290 void CMainFrame::OnViewWraplonglines()
1292 m_bWrapLines = !(DWORD)m_regWrapLines;
1293 m_regWrapLines = m_bWrapLines;
1295 if (m_pwndLeftView) m_pwndLeftView ->WrapChanged();
1296 if (m_pwndRightView) m_pwndRightView ->WrapChanged();
1297 if (m_pwndBottomView) m_pwndBottomView->WrapChanged();
1298 OnViewTextFoldUnfold();
1299 m_wndLocatorBar.DocumentUpdated();
1302 void CMainFrame::OnViewTextFoldUnfold()
1304 OnViewTextFoldUnfold(m_pwndLeftView);
1305 OnViewTextFoldUnfold(m_pwndRightView);
1306 OnViewTextFoldUnfold(m_pwndBottomView);
1309 void CMainFrame::OnViewTextFoldUnfold(CBaseView* view)
1311 if (view == 0)
1312 return;
1313 view->BuildAllScreen2ViewVector();
1314 view->UpdateCaret();
1315 view->Invalidate();
1316 view->EnsureCaretVisible();
1319 void CMainFrame::OnUpdateViewWraplonglines(CCmdUI *pCmdUI)
1321 pCmdUI->SetCheck(m_bWrapLines);
1324 void CMainFrame::OnViewOnewaydiff()
1326 if (CheckForSave(CHFSR_RELOAD)==IDCANCEL)
1327 return;
1328 m_bOneWay = !m_bOneWay;
1329 ShowDiffBar(!m_bOneWay);
1330 LoadViews(-1);
1333 void CMainFrame::ShowDiffBar(bool bShow)
1335 if (bShow)
1337 // restore the line diff bar
1338 m_wndLineDiffBar.ShowPane(m_bLineDiff, false, true);
1339 m_wndLineDiffBar.DocumentUpdated();
1340 m_wndLocatorBar.ShowPane(m_bLocatorBar, false, true);
1341 m_wndLocatorBar.DocumentUpdated();
1343 else
1345 // in one way view, hide the line diff bar
1346 m_wndLineDiffBar.ShowPane(false, false, true);
1347 m_wndLineDiffBar.DocumentUpdated();
1351 int CMainFrame::CheckResolved()
1353 //only in three way diffs can be conflicts!
1354 m_bHasConflicts = true;
1355 if (IsViewGood(m_pwndBottomView))
1357 CViewData* viewdata = m_pwndBottomView->m_pViewData;
1358 if (viewdata)
1360 for (int i=0; i<viewdata->GetCount(); i++)
1362 const DiffStates state = viewdata->GetState(i);
1363 if ((DIFFSTATE_CONFLICTED == state)||(DIFFSTATE_CONFLICTED_IGNORED == state))
1364 return i;
1368 m_bHasConflicts = false;
1369 return -1;
1372 int CMainFrame::SaveFile(const CString& sFilePath)
1374 CBaseView * pView = NULL;
1375 CViewData * pViewData = NULL;
1376 CFileTextLines * pOriginFile = &m_Data.m_arBaseFile;
1377 if (IsViewGood(m_pwndBottomView))
1379 pView = m_pwndBottomView;
1380 pViewData = m_pwndBottomView->m_pViewData;
1382 else if (IsViewGood(m_pwndRightView))
1384 pView = m_pwndRightView;
1385 pViewData = m_pwndRightView->m_pViewData;
1386 if (m_Data.IsYourFileInUse())
1387 pOriginFile = &m_Data.m_arYourFile;
1388 else if (m_Data.IsTheirFileInUse())
1389 pOriginFile = &m_Data.m_arTheirFile;
1391 else
1393 // nothing to save!
1394 return 1;
1396 Invalidate();
1397 if ((pViewData)&&(pOriginFile))
1399 CFileTextLines file;
1400 pOriginFile->CopySettings(&file);
1401 CFileTextLines::SaveParams saveParams;
1402 saveParams.m_LineEndings = pView->GetLineEndings();
1403 saveParams.m_UnicodeType = pView->GetTextType();
1404 file.SetSaveParams(saveParams);
1405 for (int i=0; i<pViewData->GetCount(); i++)
1407 //only copy non-removed lines
1408 DiffStates state = pViewData->GetState(i);
1409 switch (state)
1411 case DIFFSTATE_CONFLICTED:
1412 case DIFFSTATE_CONFLICTED_IGNORED:
1414 int first = i;
1415 int last = i;
1418 last++;
1419 } while((last<pViewData->GetCount()) && ((pViewData->GetState(last)==DIFFSTATE_CONFLICTED)||(pViewData->GetState(last)==DIFFSTATE_CONFLICTED_IGNORED)));
1420 // TortoiseGitMerge changes here
1421 file.Add(_T("<<<<<<< .mine"), m_pwndRightView->GetLineEndings());
1422 for (int j=first; j<last; j++)
1424 EOL lineending = m_pwndRightView->m_pViewData->GetLineEnding(j);
1425 if (lineending == EOL_NOENDING)
1426 lineending = m_pwndRightView->GetLineEndings();
1427 file.Add(m_pwndRightView->m_pViewData->GetLine(j), lineending);
1429 file.Add(_T("======="), m_pwndRightView->GetLineEndings());
1430 for (int j=first; j<last; j++)
1432 EOL lineending = m_pwndLeftView->m_pViewData->GetLineEnding(j);
1433 if (lineending == EOL_NOENDING)
1434 lineending = m_pwndLeftView->GetLineEndings();
1435 file.Add(m_pwndLeftView->m_pViewData->GetLine(j), lineending);
1437 file.Add(_T(">>>>>>> .theirs"), m_pwndRightView->GetLineEndings());
1438 i = last-1;
1440 break;
1441 case DIFFSTATE_EMPTY:
1442 case DIFFSTATE_CONFLICTEMPTY:
1443 case DIFFSTATE_IDENTICALREMOVED:
1444 case DIFFSTATE_REMOVED:
1445 case DIFFSTATE_THEIRSREMOVED:
1446 case DIFFSTATE_YOURSREMOVED:
1447 case DIFFSTATE_CONFLICTRESOLVEDEMPTY:
1448 // do not save removed lines
1449 break;
1450 default:
1451 file.Add(pViewData->GetLine(i), pViewData->GetLineEnding(i));
1452 break;
1455 if (!file.Save(sFilePath, false, false))
1457 CMessageBox::Show(m_hWnd, file.GetErrorString(), _T("TortoiseGitMerge"), MB_ICONERROR);
1458 return -1;
1460 if (sFilePath == m_Data.m_baseFile.GetFilename())
1462 m_Data.m_baseFile.StoreFileAttributes();
1464 if (sFilePath == m_Data.m_theirFile.GetFilename())
1466 m_Data.m_theirFile.StoreFileAttributes();
1468 if (sFilePath == m_Data.m_yourFile.GetFilename())
1470 m_Data.m_yourFile.StoreFileAttributes();
1472 /*if (sFilePath == m_Data.m_mergedFile.GetFilename())
1474 m_Data.m_mergedFile.StoreFileAttributes();
1475 }//*/
1476 m_dlgFilePatches.SetFileStatusAsPatched(sFilePath);
1477 if (IsViewGood(m_pwndBottomView))
1478 m_pwndBottomView->SetModified(FALSE);
1479 else if (IsViewGood(m_pwndRightView))
1480 m_pwndRightView->SetModified(FALSE);
1481 CUndo::GetInstance().MarkAsOriginalState(
1482 false,
1483 IsViewGood(m_pwndRightView) && (pViewData == m_pwndRightView->m_pViewData),
1484 IsViewGood(m_pwndBottomView) && (pViewData == m_pwndBottomView->m_pViewData));
1485 if (file.GetCount() == 1 && file.GetAt(0).IsEmpty() && file.GetLineEnding(0) == EOL_NOENDING)
1486 return 0;
1487 return file.GetCount();
1489 return 1;
1492 void CMainFrame::OnFileSave()
1494 // when multiple files are set as writable we have to ask what file to save
1495 int nEditableViewCount =
1496 (CBaseView::IsViewGood(m_pwndLeftView) && m_pwndLeftView->IsWritable() ? 1 : 0)
1497 + (CBaseView::IsViewGood(m_pwndRightView) && m_pwndRightView->IsWritable() ? 1 : 0)
1498 + (CBaseView::IsViewGood(m_pwndBottomView) && m_pwndBottomView->IsWritable() ? 1 : 0);
1499 bool bLeftIsModified = CBaseView::IsViewGood(m_pwndLeftView) && m_pwndLeftView->IsModified();
1500 bool bRightIsModified = CBaseView::IsViewGood(m_pwndRightView) && m_pwndRightView->IsModified();
1501 bool bBottomIsModified = CBaseView::IsViewGood(m_pwndBottomView) && m_pwndBottomView->IsModified();
1502 int nModifiedViewCount =
1503 (bLeftIsModified ? 1 : 0)
1504 + (bRightIsModified ? 1 : 0)
1505 + (bBottomIsModified ? 1 : 0);
1506 if (nEditableViewCount>1)
1508 if (nModifiedViewCount == 1)
1510 if (bLeftIsModified)
1511 m_pwndLeftView->SaveFile(SAVE_REMOVEDLINES);
1512 else
1513 FileSave();
1515 else if (nModifiedViewCount>0)
1517 // both views
1518 UINT ret = IDNO;
1519 if (m_bUseTaskDialog)
1521 CTaskDialog taskdlg(CString(MAKEINTRESOURCE(IDS_SAVE_MORE)),
1522 CString(MAKEINTRESOURCE(IDS_SAVE)),
1523 CString(MAKEINTRESOURCE(IDS_APPNAME)),
1525 TDF_ENABLE_HYPERLINKS|TDF_USE_COMMAND_LINKS|TDF_ALLOW_DIALOG_CANCELLATION|TDF_POSITION_RELATIVE_TO_WINDOW);
1526 CString sTaskTemp;
1527 if (m_pwndLeftView->m_pWorkingFile->InUse() && !m_pwndLeftView->m_pWorkingFile->IsReadonly())
1528 sTaskTemp.Format(IDS_ASKFORSAVE_SAVELEFT, (LPCTSTR)m_pwndLeftView->m_pWorkingFile->GetFilename());
1529 else
1530 sTaskTemp = CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_SAVELEFTAS));
1531 taskdlg.AddCommandControl(201, sTaskTemp, bLeftIsModified);// left
1532 if (bLeftIsModified) {
1533 taskdlg.SetDefaultCommandControl(201);
1535 if (m_pwndRightView->m_pWorkingFile->InUse() && !m_pwndRightView->m_pWorkingFile->IsReadonly())
1536 sTaskTemp.Format(IDS_ASKFORSAVE_SAVERIGHT, (LPCTSTR)m_pwndRightView->m_pWorkingFile->GetFilename());
1537 else
1538 sTaskTemp = CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_SAVERIGHTAS));
1539 taskdlg.AddCommandControl(202, sTaskTemp, bRightIsModified); // right
1540 if (bRightIsModified) {
1541 taskdlg.SetDefaultCommandControl(202);
1543 taskdlg.AddCommandControl(203, CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_SAVEALL2)), nModifiedViewCount>1); // both
1544 if (nModifiedViewCount>1) {
1545 taskdlg.SetDefaultCommandControl(203);
1547 taskdlg.SetCommonButtons(TDCBF_CANCEL_BUTTON);
1548 taskdlg.SetMainIcon(TD_WARNING_ICON);
1549 ret = (UINT)taskdlg.DoModal(m_hWnd);
1550 switch (ret)
1552 case 201: // left
1553 m_pwndLeftView->SaveFile(SAVE_REMOVEDLINES);
1554 break;
1555 case 203: // both
1556 m_pwndLeftView->SaveFile(SAVE_REMOVEDLINES);
1557 case 202: // right
1558 m_pwndRightView->SaveFile();
1559 break;
1564 else
1566 // only target view was modified
1567 FileSave();
1571 void CMainFrame::PatchSave()
1573 bool bDoesNotExist = !PathFileExists(m_Data.m_mergedFile.GetFilename());
1574 if (m_Data.m_bPatchRequired)
1576 m_Patch.PatchPath(m_Data.m_mergedFile.GetFilename());
1578 if (!PathIsDirectory(m_Data.m_mergedFile.GetFilename()))
1580 int saveret = SaveFile(m_Data.m_mergedFile.GetFilename());
1581 if (saveret==0)
1583 // file was saved with 0 lines, remove it.
1584 m_Patch.RemoveFile(m_Data.m_mergedFile.GetFilename());
1585 // just in case
1586 DeleteFile(m_Data.m_mergedFile.GetFilename());
1588 m_Data.m_mergedFile.StoreFileAttributes();
1589 if (m_Data.m_mergedFile.GetFilename() == m_Data.m_yourFile.GetFilename())
1590 m_Data.m_yourFile.StoreFileAttributes();
1591 if ((bDoesNotExist)&&(DWORD(CRegDWORD(_T("Software\\TortoiseGitMerge\\AutoAdd"), TRUE))))
1593 // call TortoiseProc to add the new file to version control
1594 CString cmd = _T("/command:add /noui /path:\"");
1595 cmd += m_Data.m_mergedFile.GetFilename() + _T("\"");
1596 CAppUtils::RunTortoiseGitProc(cmd);
1601 bool CMainFrame::FileSave(bool bCheckResolved /*=true*/)
1603 if (HasMarkedBlocks())
1605 if (m_bUseTaskDialog)
1607 CString sTitle(MAKEINTRESOURCE(IDS_WARNMARKEDBLOCKS));
1608 CString sSubTitle(MAKEINTRESOURCE(IDS_ASKFORSAVE_MARKEDBLOCKS));
1609 CString sAppName(MAKEINTRESOURCE(IDS_APPNAME));
1610 CTaskDialog taskdlg(sTitle,
1611 sSubTitle,
1612 sAppName,
1614 TDF_ENABLE_HYPERLINKS|TDF_USE_COMMAND_LINKS|TDF_ALLOW_DIALOG_CANCELLATION|TDF_POSITION_RELATIVE_TO_WINDOW);
1615 taskdlg.AddCommandControl(10, CString(MAKEINTRESOURCE(IDS_MARKEDBLOCKSSAVEINCLUDE)));
1616 taskdlg.AddCommandControl(11, CString(MAKEINTRESOURCE(IDS_MARKEDBLOCKSSAVEEXCLUDE)));
1617 taskdlg.AddCommandControl(12, CString(MAKEINTRESOURCE(IDS_MARKEDBLCOKSSAVEIGNORE)));
1618 taskdlg.AddCommandControl(IDCANCEL, CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_CANCEL_OPEN)));
1619 taskdlg.SetCommonButtons(TDCBF_CANCEL_BUTTON);
1620 taskdlg.SetDefaultCommandControl(10);
1621 taskdlg.SetMainIcon(TD_WARNING_ICON);
1622 UINT ret = (UINT)taskdlg.DoModal(m_hWnd);
1623 if (ret == 10)
1624 m_pwndRightView->LeaveOnlyMarkedBlocks();
1625 else if (ret == 11)
1626 m_pwndRightView->UseViewFileOfMarked();
1627 else if (ret == 12)
1628 m_pwndRightView->UseViewFileExceptEdited();
1629 else
1630 return false;
1632 else
1634 CString sTitle(MAKEINTRESOURCE(IDS_ASKFORSAVE_MARKEDBLOCKS));
1635 CString msg(MAKEINTRESOURCE(IDS_WARNMARKEDBLOCKS));
1636 msg += _T("\r\n\r\n") + CString(MAKEINTRESOURCE(IDS_MSGBOX_YES)) + _T(": ");
1637 msg += CString(MAKEINTRESOURCE(IDS_MARKEDBLOCKSSAVEINCLUDE));
1638 msg += _T("\r\n\r\n") + CString(MAKEINTRESOURCE(IDS_MSGBOX_NO)) + _T(": ");
1639 msg += CString(MAKEINTRESOURCE(IDS_MARKEDBLOCKSSAVEEXCLUDE));
1640 msg += _T("\r\n\r\n") + CString(MAKEINTRESOURCE(IDS_MSGBOX_CANCEL)) + _T(": ");
1641 msg += CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_CANCEL_OPEN));
1642 int ret = CMessageBox::Show(m_hWnd, msg, sTitle, MB_YESNOCANCEL | MB_ICONQUESTION);
1643 if (ret == IDYES)
1644 m_pwndRightView->LeaveOnlyMarkedBlocks();
1645 else if (ret == IDNO)
1646 m_pwndRightView->UseViewFileOfMarked();
1647 else
1648 return false;
1652 if (!m_Data.m_mergedFile.InUse())
1653 return FileSaveAs(bCheckResolved);
1654 // check if the file has the readonly attribute set
1655 bool bDoesNotExist = false;
1656 DWORD fAttribs = GetFileAttributes(m_Data.m_mergedFile.GetFilename());
1657 if ((fAttribs != INVALID_FILE_ATTRIBUTES)&&(fAttribs & FILE_ATTRIBUTE_READONLY))
1658 return FileSaveAs(bCheckResolved);
1659 if (fAttribs == INVALID_FILE_ATTRIBUTES)
1661 bDoesNotExist = (GetLastError() == ERROR_FILE_NOT_FOUND);
1663 if (bCheckResolved && HasConflictsWontKeep())
1664 return false;
1666 if (((DWORD)CRegDWORD(_T("Software\\TortoiseGitMerge\\Backup"))) != 0)
1668 MoveFileEx(m_Data.m_mergedFile.GetFilename(), m_Data.m_mergedFile.GetFilename() + _T(".bak"), MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH);
1670 if (m_Data.m_bPatchRequired)
1672 m_Patch.PatchPath(m_Data.m_mergedFile.GetFilename());
1674 int saveret = SaveFile(m_Data.m_mergedFile.GetFilename());
1675 if (saveret==0)
1677 // file was saved with 0 lines!
1678 // ask the user if the file should be deleted
1679 bool bDelete = false;
1680 if (m_bUseTaskDialog)
1682 CString msg;
1683 msg.Format(IDS_DELETEWHENEMPTY, (LPCTSTR)CPathUtils::GetFileNameFromPath(m_Data.m_mergedFile.GetFilename()));
1684 CTaskDialog taskdlg(msg,
1685 CString(MAKEINTRESOURCE(IDS_DELETEWHENEMPTY_TASK2)),
1686 CString(MAKEINTRESOURCE(IDS_APPNAME)),
1688 TDF_ENABLE_HYPERLINKS|TDF_USE_COMMAND_LINKS|TDF_ALLOW_DIALOG_CANCELLATION|TDF_POSITION_RELATIVE_TO_WINDOW);
1689 taskdlg.AddCommandControl(1, CString(MAKEINTRESOURCE(IDS_DELETEWHENEMPTY_TASK3)));
1690 taskdlg.AddCommandControl(2, CString(MAKEINTRESOURCE(IDS_DELETEWHENEMPTY_TASK4)));
1691 taskdlg.SetCommonButtons(TDCBF_CANCEL_BUTTON);
1692 taskdlg.SetDefaultCommandControl(1);
1693 taskdlg.SetMainIcon(TD_WARNING_ICON);
1694 bDelete = (taskdlg.DoModal(m_hWnd) == 1);
1696 else
1698 CString sTemp;
1699 sTemp.Format(IDS_DELETEWHENEMPTY, (LPCTSTR)m_Data.m_mergedFile.GetFilename());
1700 bDelete = (CMessageBox::ShowCheck(m_hWnd, sTemp, _T("TortoiseGitMerge"), MB_YESNO, _T("DeleteFileWhenEmpty")) == IDYES);
1702 if (bDelete)
1704 m_Patch.RemoveFile(m_Data.m_mergedFile.GetFilename());
1705 DeleteFile(m_Data.m_mergedFile.GetFilename());
1708 else if (saveret < 0)
1710 // error while saving the file
1711 return false;
1714 // if we're in conflict resolve mode (three pane view), check if there are no more conflicts
1715 // and if there aren't, ask to mark the file as resolved
1716 if (IsViewGood(m_pwndBottomView) && !m_bHasConflicts && bCheckResolved)
1718 CString projectRoot;
1719 if (GitAdminDir::HasAdminDir(m_Data.m_mergedFile.GetFilename(), false, &projectRoot))
1721 CString subpath = m_Data.m_mergedFile.GetFilename();
1722 subpath.Replace(_T('\\'), _T('/'));
1723 if (subpath.GetLength() >= projectRoot.GetLength())
1725 if (subpath[projectRoot.GetLength()] == _T('/'))
1726 subpath = subpath.Right(subpath.GetLength() - projectRoot.GetLength() - 1);
1727 else
1728 subpath = subpath.Right(subpath.GetLength() - projectRoot.GetLength());
1731 CAutoRepository repository(projectRoot);
1732 bool hasConflictInIndex = false;
1735 if (!repository)
1736 break;
1738 CAutoIndex index;
1739 if (git_repository_index(index.GetPointer(), repository))
1740 break;
1742 CStringA path = CUnicodeUtils::GetMulti(subpath, CP_UTF8);
1743 const git_index_entry * entry = git_index_get_bypath(index, path, 1);
1744 hasConflictInIndex = entry != nullptr;
1745 } while(0);
1747 if (hasConflictInIndex)
1749 bool bResolve = false;
1750 if (m_bUseTaskDialog)
1752 CString msg;
1753 msg.Format(IDS_MARKASRESOLVED, (LPCTSTR)CPathUtils::GetFileNameFromPath(m_Data.m_mergedFile.GetFilename()));
1754 CTaskDialog taskdlg(msg,
1755 CString(MAKEINTRESOURCE(IDS_MARKASRESOLVED_TASK2)),
1756 CString(MAKEINTRESOURCE(IDS_APPNAME)),
1758 TDF_ENABLE_HYPERLINKS|TDF_USE_COMMAND_LINKS|TDF_ALLOW_DIALOG_CANCELLATION|TDF_POSITION_RELATIVE_TO_WINDOW);
1759 taskdlg.AddCommandControl(1, CString(MAKEINTRESOURCE(IDS_MARKASRESOLVED_TASK3)));
1760 taskdlg.AddCommandControl(2, CString(MAKEINTRESOURCE(IDS_MARKASRESOLVED_TASK4)));
1761 taskdlg.SetCommonButtons(TDCBF_CANCEL_BUTTON);
1762 taskdlg.SetDefaultCommandControl(1);
1763 taskdlg.SetMainIcon(TD_WARNING_ICON);
1764 bResolve = (taskdlg.DoModal(m_hWnd) == 1);
1766 else
1768 CString sTemp;
1769 sTemp.Format(IDS_MARKASRESOLVED, (LPCTSTR)CPathUtils::GetFileNameFromPath(m_Data.m_mergedFile.GetFilename()));
1770 bResolve = (CMessageBox::Show(m_hWnd, sTemp, _T("TortoiseGitMerge"), MB_YESNO | MB_ICONQUESTION) == IDYES);
1772 if (bResolve)
1774 MarkAsResolved();
1780 m_bSaveRequired = false;
1781 m_Data.m_mergedFile.StoreFileAttributes();
1783 if ((bDoesNotExist)&&(DWORD(CRegDWORD(_T("Software\\TortoiseGitMerge\\AutoAdd"), TRUE))))
1785 // call TortoiseProc to add the new file to version control
1786 CString cmd = _T("/command:add /noui /path:\"");
1787 cmd += m_Data.m_mergedFile.GetFilename() + _T("\"");
1788 if(!CAppUtils::RunTortoiseGitProc(cmd))
1789 return false;
1791 return true;
1794 void CMainFrame::OnFileSaveAs()
1796 if (m_bUseTaskDialog)
1798 // ask what file to save as
1799 bool bHaveConflict = (CheckResolved() >= 0);
1800 CTaskDialog taskdlg(
1801 CString(MAKEINTRESOURCE(bHaveConflict ? IDS_ASKFORSAVEAS_MORECONFLICT : IDS_ASKFORSAVEAS_MORE)),
1802 CString(MAKEINTRESOURCE(IDS_ASKFORSAVEAS)),
1803 CString(MAKEINTRESOURCE(IDS_APPNAME)),
1805 TDF_ENABLE_HYPERLINKS|TDF_USE_COMMAND_LINKS|TDF_ALLOW_DIALOG_CANCELLATION|TDF_POSITION_RELATIVE_TO_WINDOW);
1806 // default can be last view (target) as was in 1.7 or actual (where is cursor) as is in most text editor
1807 if (IsViewGood(m_pwndLeftView))
1809 taskdlg.AddCommandControl(201, CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_SAVELEFTAS))); // left
1810 taskdlg.SetDefaultCommandControl(201);
1812 if (IsViewGood(m_pwndRightView))
1814 taskdlg.AddCommandControl(202, CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_SAVERIGHTAS))); // right
1815 taskdlg.SetDefaultCommandControl(202);
1817 if (IsViewGood(m_pwndBottomView))
1819 taskdlg.AddCommandControl(203, CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_SAVEBOTTOMAS))); // bottom
1820 taskdlg.SetDefaultCommandControl(203);
1822 if (bHaveConflict)
1824 taskdlg.AddCommandControl(204, CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_NEEDRESOLVE))); // resolve
1825 taskdlg.SetDefaultCommandControl(204);
1827 taskdlg.SetCommonButtons(TDCBF_CANCEL_BUTTON);
1828 taskdlg.SetMainIcon(bHaveConflict ? TD_WARNING_ICON : TD_INFORMATION_ICON);
1829 int nCommand = (int)taskdlg.DoModal(m_hWnd);
1830 CString sFileName;
1831 switch (nCommand)
1833 case 201: // left
1834 if (TryGetFileName(sFileName))
1836 // in 2, 3 view display we want to keep removed lines
1837 m_pwndLeftView->SaveFileTo(sFileName, IsViewGood(m_pwndRightView) ? SAVE_REMOVEDLINES : 0);
1839 break;
1840 case 202: // right
1841 if (TryGetFileName(sFileName))
1843 m_pwndRightView->SaveFileTo(sFileName);
1845 break;
1846 case 203: // bottom
1847 FileSaveAs();
1848 break;
1849 case 204: // continue resolving
1850 if (m_pwndBottomView)
1852 m_pwndBottomView->GoToLine(CheckResolved());
1854 break;
1857 else
1859 int nEditableViewCount =
1860 (CBaseView::IsViewGood(m_pwndLeftView) && m_pwndLeftView->IsWritable() ? 1 : 0)
1861 + (CBaseView::IsViewGood(m_pwndRightView) && m_pwndRightView->IsWritable() ? 1 : 0)
1862 + (CBaseView::IsViewGood(m_pwndBottomView) && m_pwndBottomView->IsWritable() ? 1 : 0);
1863 bool bLeftIsModified = CBaseView::IsViewGood(m_pwndLeftView) && m_pwndLeftView->IsModified();
1864 bool bRightIsModified = CBaseView::IsViewGood(m_pwndRightView) && m_pwndRightView->IsModified();
1865 bool bBottomIsModified = CBaseView::IsViewGood(m_pwndBottomView) && m_pwndBottomView->IsModified();
1866 int nModifiedViewCount =
1867 (bLeftIsModified ? 1 : 0)
1868 + (bRightIsModified ? 1 : 0)
1869 + (bBottomIsModified ? 1 : 0);
1870 if (nEditableViewCount>1)
1872 if (nModifiedViewCount == 1)
1874 if (bLeftIsModified)
1876 CString sFileName;
1877 if (TryGetFileName(sFileName))
1879 m_pwndLeftView->SaveFileTo(sFileName);
1882 else
1883 FileSaveAs();
1885 else
1887 FileSaveAs();
1888 CString sFileName;
1889 if (TryGetFileName(sFileName))
1891 m_pwndLeftView->SaveFileTo(sFileName);
1898 bool CMainFrame::FileSaveAs(bool bCheckResolved /*=true*/)
1900 if (bCheckResolved && HasConflictsWontKeep())
1901 return false;
1903 CString fileName;
1904 if(!TryGetFileName(fileName))
1905 return false;
1907 SaveFile(fileName);
1908 return true;
1911 void CMainFrame::OnUpdateFileSave(CCmdUI *pCmdUI)
1913 BOOL bEnable = FALSE;
1914 if (m_Data.m_mergedFile.InUse())
1916 if (IsViewGood(m_pwndBottomView)&&(m_pwndBottomView->m_pViewData))
1917 bEnable = TRUE;
1918 else if ( (IsViewGood(m_pwndRightView)&&(m_pwndRightView->m_pViewData)) &&
1919 (m_pwndRightView->IsModified() || (m_Data.m_yourFile.GetWindowName().Right(9).Compare(_T(": patched"))==0)) )
1920 bEnable = TRUE;
1921 else if (IsViewGood(m_pwndLeftView)
1922 && (m_pwndLeftView->m_pViewData)
1923 && (m_pwndLeftView->IsModified()))
1924 bEnable = TRUE;
1926 pCmdUI->Enable(bEnable);
1929 void CMainFrame::OnUpdateFileSaveAs(CCmdUI *pCmdUI)
1931 // any file is open we can save it as
1932 BOOL bEnable = FALSE;
1933 if (IsViewGood(m_pwndBottomView)&&(m_pwndBottomView->m_pViewData))
1934 bEnable = TRUE;
1935 else if (IsViewGood(m_pwndRightView)&&(m_pwndRightView->m_pViewData))
1936 bEnable = TRUE;
1937 else if (IsViewGood(m_pwndLeftView)&&(m_pwndLeftView->m_pViewData))
1938 bEnable = TRUE;
1939 pCmdUI->Enable(bEnable);
1942 void CMainFrame::OnUpdateViewOnewaydiff(CCmdUI *pCmdUI)
1944 pCmdUI->SetCheck(!m_bOneWay);
1945 BOOL bEnable = TRUE;
1946 if (IsViewGood(m_pwndBottomView))
1948 bEnable = FALSE;
1950 pCmdUI->Enable(bEnable);
1953 void CMainFrame::OnViewOptions()
1955 CString sTemp;
1956 sTemp.LoadString(IDS_SETTINGSTITLE);
1957 CSettings dlg(sTemp);
1958 dlg.DoModal();
1959 if (dlg.IsReloadNeeded())
1961 if (CheckForSave(CHFSR_OPTIONS)==IDCANCEL)
1962 return;
1963 CDiffColors::GetInstance().LoadRegistry();
1964 LoadViews();
1965 return;
1967 CDiffColors::GetInstance().LoadRegistry();
1968 if (m_pwndBottomView)
1969 m_pwndBottomView->Invalidate();
1970 if (m_pwndLeftView)
1971 m_pwndLeftView->Invalidate();
1972 if (m_pwndRightView)
1973 m_pwndRightView->Invalidate();
1976 void CMainFrame::OnClose()
1978 if (CheckForSave(CHFSR_CLOSE)!=IDCANCEL)
1980 WINDOWPLACEMENT wp;
1982 // before it is destroyed, save the position of the window
1983 wp.length = sizeof wp;
1985 if (GetWindowPlacement(&wp))
1988 if (IsIconic())
1989 // never restore to Iconic state
1990 wp.showCmd = SW_SHOW ;
1992 if ((wp.flags & WPF_RESTORETOMAXIMIZED) != 0)
1993 // if maximized and maybe iconic restore maximized state
1994 wp.showCmd = SW_SHOWMAXIMIZED ;
1996 // and write it
1997 WriteWindowPlacement(&wp);
1999 __super::OnClose();
2003 void CMainFrame::OnActivate(UINT nValue, CWnd* /*pwnd*/, BOOL /*bActivated?*/)
2005 if (nValue != 0) // activated
2007 if (IsIconic())
2009 m_bCheckReload = TRUE;
2011 else
2013 // use a timer to give other messages time to get processed
2014 // first, like e.g. the WM_CLOSE message in case the user
2015 // clicked the close button and that brought the window
2016 // to the front - in that case checking for reload wouldn't
2017 // do any good.
2018 SetTimer(IDT_RELOADCHECKTIMER, 300, NULL);
2023 void CMainFrame::OnViewLinedown()
2025 OnViewLineUpDown(1);
2028 void CMainFrame::OnViewLineup()
2030 OnViewLineUpDown(-1);
2033 void CMainFrame::OnViewLineUpDown(int direction)
2035 if (m_pwndLeftView)
2036 m_pwndLeftView->ScrollToLine(m_pwndLeftView->m_nTopLine+direction);
2037 if (m_pwndRightView)
2038 m_pwndRightView->ScrollToLine(m_pwndRightView->m_nTopLine+direction);
2039 if (m_pwndBottomView)
2040 m_pwndBottomView->ScrollToLine(m_pwndBottomView->m_nTopLine+direction);
2041 m_wndLocatorBar.Invalidate();
2042 m_nMoveMovesToIgnore = MOVESTOIGNORE;
2045 void CMainFrame::OnViewLineleft()
2047 OnViewLineLeftRight(-1);
2050 void CMainFrame::OnViewLineright()
2052 OnViewLineLeftRight(1);
2055 void CMainFrame::OnViewLineLeftRight(int direction)
2057 if (m_pwndLeftView)
2058 m_pwndLeftView->ScrollSide(direction);
2059 if (m_pwndRightView)
2060 m_pwndRightView->ScrollSide(direction);
2061 if (m_pwndBottomView)
2062 m_pwndBottomView->ScrollSide(direction);
2065 void CMainFrame::OnEditUseTheirs()
2067 if (m_pwndBottomView)
2068 m_pwndBottomView->UseTheirTextBlock();
2070 void CMainFrame::OnUpdateEditUsetheirblock(CCmdUI *pCmdUI)
2072 pCmdUI->Enable(m_pwndBottomView && m_pwndBottomView->HasSelection());
2075 void CMainFrame::OnEditUseMine()
2077 if (m_pwndBottomView)
2078 m_pwndBottomView->UseMyTextBlock();
2080 void CMainFrame::OnUpdateEditUsemyblock(CCmdUI *pCmdUI)
2082 OnUpdateEditUsetheirblock(pCmdUI);
2085 void CMainFrame::OnEditUseTheirsThenMine()
2087 if (m_pwndBottomView)
2088 m_pwndBottomView->UseTheirAndYourBlock();
2091 void CMainFrame::OnUpdateEditUsetheirthenmyblock(CCmdUI *pCmdUI)
2093 OnUpdateEditUsetheirblock(pCmdUI);
2096 void CMainFrame::OnEditUseMineThenTheirs()
2098 if (m_pwndBottomView)
2099 m_pwndBottomView->UseYourAndTheirBlock();
2102 void CMainFrame::OnUpdateEditUseminethentheirblock(CCmdUI *pCmdUI)
2104 OnUpdateEditUsetheirblock(pCmdUI);
2107 void CMainFrame::OnEditUseleftblock()
2109 if (m_pwndBottomView->IsWindowVisible())
2110 m_pwndBottomView->UseRightBlock();
2111 else
2112 m_pwndRightView->UseLeftBlock();
2115 void CMainFrame::OnUpdateEditUseleftblock(CCmdUI *pCmdUI)
2117 pCmdUI->Enable(IsViewGood(m_pwndRightView) && m_pwndRightView->IsTarget() && m_pwndRightView->HasSelection());
2120 void CMainFrame::OnUpdateUseBlock(CCmdUI *pCmdUI)
2122 pCmdUI->Enable(TRUE);
2125 void CMainFrame::OnEditUseleftfile()
2127 if (m_pwndBottomView->IsWindowVisible())
2128 m_pwndBottomView->UseRightFile();
2129 else
2130 m_pwndRightView->UseLeftFile();
2133 void CMainFrame::OnUpdateEditUseleftfile(CCmdUI *pCmdUI)
2135 pCmdUI->Enable(IsViewGood(m_pwndRightView) && m_pwndRightView->IsTarget());
2138 void CMainFrame::OnEditUseblockfromleftbeforeright()
2140 if (m_pwndRightView)
2141 m_pwndRightView->UseBothLeftFirst();
2144 void CMainFrame::OnUpdateEditUseblockfromleftbeforeright(CCmdUI *pCmdUI)
2146 OnUpdateEditUseleftblock(pCmdUI);
2149 void CMainFrame::OnEditUseblockfromrightbeforeleft()
2151 if (m_pwndRightView)
2152 m_pwndRightView->UseBothRightFirst();
2155 void CMainFrame::OnUpdateEditUseblockfromrightbeforeleft(CCmdUI *pCmdUI)
2157 OnUpdateEditUseleftblock(pCmdUI);
2160 void CMainFrame::OnFileReload()
2162 if (CheckForSave(CHFSR_RELOAD)==IDCANCEL)
2163 return;
2164 CDiffColors::GetInstance().LoadRegistry();
2165 LoadViews(-1);
2168 void CMainFrame::ActivateFrame(int nCmdShow)
2170 // nCmdShow is the normal show mode this frame should be in
2171 // translate default nCmdShow (-1)
2172 if (nCmdShow == -1)
2174 if (!IsWindowVisible())
2175 nCmdShow = SW_SHOWNORMAL;
2176 else if (IsIconic())
2177 nCmdShow = SW_RESTORE;
2180 // bring to top before showing
2181 BringToTop(nCmdShow);
2183 if (nCmdShow != -1)
2185 // show the window as specified
2186 WINDOWPLACEMENT wp;
2188 if ( !ReadWindowPlacement(&wp) )
2190 ShowWindow(nCmdShow);
2192 else
2194 if ( nCmdShow != SW_SHOWNORMAL )
2195 wp.showCmd = nCmdShow;
2197 SetWindowPlacement(&wp);
2200 // and finally, bring to top after showing
2201 BringToTop(nCmdShow);
2205 BOOL CMainFrame::ReadWindowPlacement(WINDOWPLACEMENT * pwp)
2207 CRegString placement = CRegString(_T("Software\\TortoiseGitMerge\\WindowPos"));
2208 CString sPlacement = placement;
2209 if (sPlacement.IsEmpty())
2210 return FALSE;
2211 int nRead = _stscanf_s(sPlacement, _T("%u,%u,%d,%d,%d,%d,%d,%d,%d,%d"),
2212 &pwp->flags, &pwp->showCmd,
2213 &pwp->ptMinPosition.x, &pwp->ptMinPosition.y,
2214 &pwp->ptMaxPosition.x, &pwp->ptMaxPosition.y,
2215 &pwp->rcNormalPosition.left, &pwp->rcNormalPosition.top,
2216 &pwp->rcNormalPosition.right, &pwp->rcNormalPosition.bottom);
2217 if ( nRead != 10 )
2218 return FALSE;
2219 pwp->length = sizeof(WINDOWPLACEMENT);
2221 return TRUE;
2224 void CMainFrame::WriteWindowPlacement(WINDOWPLACEMENT * pwp)
2226 CRegString placement(L"Software\\TortoiseGitMerge\\WindowPos");
2227 TCHAR szBuffer[_countof("-32767")*8 + sizeof("65535")*2];
2229 _stprintf_s(szBuffer, _T("%u,%u,%d,%d,%d,%d,%d,%d,%d,%d"),
2230 pwp->flags, pwp->showCmd,
2231 pwp->ptMinPosition.x, pwp->ptMinPosition.y,
2232 pwp->ptMaxPosition.x, pwp->ptMaxPosition.y,
2233 pwp->rcNormalPosition.left, pwp->rcNormalPosition.top,
2234 pwp->rcNormalPosition.right, pwp->rcNormalPosition.bottom);
2235 placement = szBuffer;
2238 void CMainFrame::OnUpdateMergeMarkasresolved(CCmdUI *pCmdUI)
2240 if (pCmdUI == NULL)
2241 return;
2242 BOOL bEnable = FALSE;
2243 if ((!m_bReadOnly)&&(m_Data.m_mergedFile.InUse()))
2245 if (IsViewGood(m_pwndBottomView)&&(m_pwndBottomView->m_pViewData))
2247 bEnable = TRUE;
2250 pCmdUI->Enable(bEnable);
2253 void CMainFrame::OnMergeMarkasresolved()
2255 if(HasConflictsWontKeep())
2256 return;
2258 // now check if the file has already been saved and if not, save it.
2259 if (m_Data.m_mergedFile.InUse())
2261 if (IsViewGood(m_pwndBottomView)&&(m_pwndBottomView->m_pViewData))
2263 FileSave(false);
2264 m_bSaveRequired = false;
2267 MarkAsResolved();
2270 BOOL CMainFrame::MarkAsResolved()
2272 if (m_bReadOnly)
2273 return FALSE;
2274 if (!IsViewGood(m_pwndBottomView))
2275 return FALSE;
2277 CString cmd = _T("/command:resolve /path:\"");
2278 cmd += m_Data.m_mergedFile.GetFilename();
2279 cmd += _T("\" /closeonend:1 /noquestion /skipcheck /silent");
2280 if (resolveMsgWnd)
2282 CString s;
2283 s.Format(L" /resolvemsghwnd:%I64d /resolvemsgwparam:%I64d /resolvemsglparam:%I64d", (__int64)resolveMsgWnd, (__int64)resolveMsgWParam, (__int64)resolveMsgLParam);
2284 cmd += s;
2286 if(!CAppUtils::RunTortoiseGitProc(cmd))
2287 return FALSE;
2288 m_bSaveRequired = false;
2289 return TRUE;
2292 void CMainFrame::OnUpdateMergeNextconflict(CCmdUI *pCmdUI)
2294 BOOL bShow = FALSE;
2295 if (HasNextConflict(m_pwndBottomView))
2296 bShow = TRUE;
2297 else if (HasNextConflict(m_pwndRightView))
2298 bShow = TRUE;
2299 else if (HasNextConflict(m_pwndLeftView))
2300 bShow = TRUE;
2301 pCmdUI->Enable(bShow);
2304 bool CMainFrame::HasNextConflict(CBaseView* view)
2306 if (view == 0)
2307 return false;
2308 if (!view->IsTarget())
2309 return false;
2310 return view->HasNextConflict();
2313 void CMainFrame::OnUpdateMergePreviousconflict(CCmdUI *pCmdUI)
2315 BOOL bShow = FALSE;
2316 if (HasPrevConflict(m_pwndBottomView))
2317 bShow = TRUE;
2318 else if (HasPrevConflict(m_pwndRightView))
2319 bShow = TRUE;
2320 else if (HasPrevConflict(m_pwndLeftView))
2321 bShow = TRUE;
2322 pCmdUI->Enable(bShow);
2325 bool CMainFrame::HasPrevConflict(CBaseView* view)
2327 if (view == 0)
2328 return false;
2329 if (!view->IsTarget())
2330 return false;
2331 return view->HasPrevConflict();
2334 void CMainFrame::OnUpdateNavigateNextdifference(CCmdUI *pCmdUI)
2336 CBaseView* baseView = GetActiveBaseView();
2337 BOOL bShow = FALSE;
2338 if (baseView != 0)
2339 bShow = baseView->HasNextDiff();
2340 pCmdUI->Enable(bShow);
2343 void CMainFrame::OnUpdateNavigatePreviousdifference(CCmdUI *pCmdUI)
2345 CBaseView* baseView = GetActiveBaseView();
2346 BOOL bShow = FALSE;
2347 if (baseView != 0)
2348 bShow = baseView->HasPrevDiff();
2349 pCmdUI->Enable(bShow);
2352 void CMainFrame::OnUpdateNavigateNextinlinediff(CCmdUI *pCmdUI)
2354 BOOL bShow = FALSE;
2355 if (HasNextInlineDiff(m_pwndBottomView))
2356 bShow = TRUE;
2357 else if (HasNextInlineDiff(m_pwndRightView))
2358 bShow = TRUE;
2359 else if (HasNextInlineDiff(m_pwndLeftView))
2360 bShow = TRUE;
2361 pCmdUI->Enable(bShow);
2364 bool CMainFrame::HasNextInlineDiff(CBaseView* view)
2366 if (view == 0)
2367 return false;
2368 if (!view->IsTarget())
2369 return false;
2370 return view->HasNextInlineDiff();
2373 void CMainFrame::OnUpdateNavigatePrevinlinediff(CCmdUI *pCmdUI)
2375 BOOL bShow = FALSE;
2376 if (HasPrevInlineDiff(m_pwndBottomView))
2377 bShow = TRUE;
2378 else if (HasPrevInlineDiff(m_pwndRightView))
2379 bShow = TRUE;
2380 else if (HasPrevInlineDiff(m_pwndLeftView))
2381 bShow = TRUE;
2382 pCmdUI->Enable(bShow);
2385 bool CMainFrame::HasPrevInlineDiff(CBaseView* view)
2387 if (view == 0)
2388 return false;
2389 if (!view->IsTarget())
2390 return false;
2391 return view->HasPrevInlineDiff();
2394 void CMainFrame::OnMoving(UINT fwSide, LPRECT pRect)
2396 // if the pathfilelist dialog is attached to the mainframe,
2397 // move it along with the mainframe
2398 if (::IsWindow(m_dlgFilePatches.m_hWnd))
2400 RECT patchrect;
2401 m_dlgFilePatches.GetWindowRect(&patchrect);
2402 if (::IsWindow(m_hWnd))
2404 RECT thisrect;
2405 GetWindowRect(&thisrect);
2406 if (patchrect.right == thisrect.left)
2408 m_dlgFilePatches.SetWindowPos(NULL, patchrect.left - (thisrect.left - pRect->left), patchrect.top - (thisrect.top - pRect->top),
2409 0, 0, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER);
2413 __super::OnMoving(fwSide, pRect);
2416 void CMainFrame::OnUpdateEditCopy(CCmdUI *pCmdUI)
2418 BOOL bShow = FALSE;
2419 if ((m_pwndBottomView)&&(m_pwndBottomView->HasSelection()))
2420 bShow = TRUE;
2421 else if ((m_pwndRightView)&&(m_pwndRightView->HasSelection()))
2422 bShow = TRUE;
2423 else if ((m_pwndLeftView)&&(m_pwndLeftView->HasSelection()))
2424 bShow = TRUE;
2425 pCmdUI->Enable(bShow);
2428 void CMainFrame::OnUpdateEditPaste(CCmdUI *pCmdUI)
2430 BOOL bWritable = FALSE;
2431 if ((m_pwndBottomView)&&(m_pwndBottomView->IsWritable()))
2432 bWritable = TRUE;
2433 else if ((m_pwndRightView)&&(m_pwndRightView->IsWritable()))
2434 bWritable = TRUE;
2435 else if ((m_pwndLeftView)&&(m_pwndLeftView->IsWritable()))
2436 bWritable = TRUE;
2437 pCmdUI->Enable(bWritable && ::IsClipboardFormatAvailable(CF_TEXT));
2440 void CMainFrame::OnViewSwitchleft()
2442 if (CheckForSave(CHFSR_SWITCH)!=IDCANCEL)
2444 CWorkingFile file = m_Data.m_baseFile;
2445 m_Data.m_baseFile = m_Data.m_yourFile;
2446 m_Data.m_yourFile = file;
2447 if (m_Data.m_mergedFile.GetFilename().CompareNoCase(m_Data.m_yourFile.GetFilename())==0)
2449 m_Data.m_mergedFile = m_Data.m_baseFile;
2451 else if (m_Data.m_mergedFile.GetFilename().CompareNoCase(m_Data.m_baseFile.GetFilename())==0)
2453 m_Data.m_mergedFile = m_Data.m_yourFile;
2455 LoadViews();
2459 void CMainFrame::OnUpdateViewSwitchleft(CCmdUI *pCmdUI)
2461 BOOL bEnable = !IsViewGood(m_pwndBottomView);
2462 pCmdUI->Enable(bEnable);
2465 void CMainFrame::OnUpdateViewShowfilelist(CCmdUI *pCmdUI)
2467 BOOL bEnable = m_dlgFilePatches.HasFiles();
2468 pCmdUI->Enable(bEnable);
2469 pCmdUI->SetCheck(m_dlgFilePatches.IsWindowVisible());
2472 void CMainFrame::OnViewShowfilelist()
2474 m_dlgFilePatches.ShowWindow(m_dlgFilePatches.IsWindowVisible() ? SW_HIDE : SW_SHOW);
2477 void CMainFrame::OnEditUndo()
2479 if (CUndo::GetInstance().CanUndo())
2481 CUndo::GetInstance().Undo(m_pwndLeftView, m_pwndRightView, m_pwndBottomView);
2485 void CMainFrame::OnUpdateEditUndo(CCmdUI *pCmdUI)
2487 pCmdUI->Enable(CUndo::GetInstance().CanUndo());
2490 void CMainFrame::OnEditEnable()
2492 CBaseView * pView = GetActiveBaseView();
2493 if (pView && pView->IsReadonlyChangable())
2495 bool isReadOnly = pView->IsReadonly();
2496 pView->SetReadonly(!isReadOnly);
2500 void CMainFrame::OnUpdateEditEnable(CCmdUI *pCmdUI)
2502 CBaseView * pView = GetActiveBaseView();
2503 if (pView)
2505 pCmdUI->Enable(pView->IsReadonlyChangable() || !pView->IsReadonly());
2506 pCmdUI->SetCheck(!pView->IsReadonly());
2508 else
2510 pCmdUI->Enable(FALSE);
2514 void CMainFrame::OnIndicatorLeftview()
2516 if (m_bUseRibbons)
2517 return;
2518 if (IsViewGood(m_pwndLeftView))
2520 m_pwndLeftView->AskUserForNewLineEndingsAndTextType(IDS_STATUSBAR_LEFTVIEW);
2524 void CMainFrame::OnIndicatorRightview()
2526 if (m_bUseRibbons)
2527 return;
2528 if (IsViewGood(m_pwndRightView))
2530 m_pwndRightView->AskUserForNewLineEndingsAndTextType(IDS_STATUSBAR_RIGHTVIEW);
2534 void CMainFrame::OnIndicatorBottomview()
2536 if (m_bUseRibbons)
2537 return;
2538 if (IsViewGood(m_pwndBottomView))
2540 m_pwndBottomView->AskUserForNewLineEndingsAndTextType(IDS_STATUSBAR_BOTTOMVIEW);
2544 int CMainFrame::CheckForReload()
2546 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
2547 if (bLock)
2549 return IDNO;
2551 bLock = true;
2552 bool bSourceChanged =
2553 m_Data.m_baseFile.HasSourceFileChanged()
2554 || m_Data.m_yourFile.HasSourceFileChanged()
2555 || m_Data.m_theirFile.HasSourceFileChanged()
2556 /*|| m_Data.m_mergedFile.HasSourceFileChanged()*/;
2557 if (!bSourceChanged)
2559 bLock = false;
2560 return IDNO;
2563 UINT ret = IDNO;
2564 if (m_bUseTaskDialog)
2566 CString msg = HasUnsavedEdits() ? CString(MAKEINTRESOURCE(IDS_WARNMODIFIEDOUTSIDELOOSECHANGES)) : CString(MAKEINTRESOURCE(IDS_WARNMODIFIEDOUTSIDE));
2567 CTaskDialog taskdlg(msg,
2568 CString(MAKEINTRESOURCE(IDS_WARNMODIFIEDOUTSIDE_TASK2)),
2569 L"TortoiseGitMerge",
2571 TDF_ENABLE_HYPERLINKS|TDF_USE_COMMAND_LINKS|TDF_ALLOW_DIALOG_CANCELLATION|TDF_POSITION_RELATIVE_TO_WINDOW);
2572 CString sTask3;
2573 if (HasUnsavedEdits())
2574 sTask3.LoadString(IDS_WARNMODIFIEDOUTSIDE_TASK3);
2575 else
2576 sTask3.LoadString(IDS_WARNMODIFIEDOUTSIDE_TASK4);
2577 taskdlg.AddCommandControl(IDYES, sTask3);
2578 taskdlg.AddCommandControl(IDNO, CString(MAKEINTRESOURCE(IDS_WARNMODIFIEDOUTSIDE_TASK5)));
2579 taskdlg.SetCommonButtons(TDCBF_CANCEL_BUTTON);
2580 taskdlg.SetDefaultCommandControl(IDYES);
2581 taskdlg.SetMainIcon(TD_WARNING_ICON);
2582 ret = (UINT)taskdlg.DoModal(m_hWnd);
2584 else
2586 int idsMessage = HasUnsavedEdits() ? IDS_WARNMODIFIEDOUTSIDELOOSECHANGES : IDS_WARNMODIFIEDOUTSIDE;
2587 ret = CMessageBox::Show(m_hWnd, idsMessage, IDS_APPNAME, MB_YESNO | MB_ICONQUESTION);
2590 if (ret == IDYES)
2592 CDiffColors::GetInstance().LoadRegistry();
2593 LoadViews(-1);
2595 else
2597 if (IsViewGood(m_pwndBottomView)) // three pane view
2599 /*if (m_Data.m_sourceFile.HasSourceFileChanged())
2600 m_pwndBottomView->SetModified();
2601 if (m_Data.m_mergedFile.HasSourceFileChanged())
2602 m_pwndBottomView->SetModified();//*/
2603 if (m_Data.m_yourFile.HasSourceFileChanged())
2604 m_pwndRightView->SetModified();
2605 if (m_Data.m_theirFile.HasSourceFileChanged())
2606 m_pwndLeftView->SetModified();
2608 else if (IsViewGood(m_pwndRightView)) // two pane view
2610 if (m_Data.m_baseFile.HasSourceFileChanged())
2611 m_pwndLeftView->SetModified();
2612 if (m_Data.m_yourFile.HasSourceFileChanged())
2613 m_pwndRightView->SetModified();
2615 else
2617 if (m_Data.m_yourFile.HasSourceFileChanged())
2618 m_pwndLeftView->SetModified();
2621 // no reload just store updated file time
2622 m_Data.m_baseFile.StoreFileAttributes();
2623 m_Data.m_theirFile.StoreFileAttributes();
2624 m_Data.m_yourFile.StoreFileAttributes();
2625 //m_Data.m_mergedFile.StoreFileAttributes();
2627 bLock = false;
2628 return ret;
2631 int CMainFrame::CheckForSave(ECheckForSaveReason eReason)
2633 int idTitle = IDS_WARNMODIFIEDLOOSECHANGES;
2634 int idNoSave = IDS_ASKFORSAVE_TASK7;
2635 int idCancelAction = IDS_ASKFORSAVE_CANCEL_OPEN;
2636 switch (eReason)
2638 case CHFSR_CLOSE:
2639 //idTitle = IDS_WARNMODIFIEDLOOSECHANGES;
2640 idNoSave = IDS_ASKFORSAVE_TASK4;
2641 idCancelAction = IDS_ASKFORSAVE_TASK5;
2642 break;
2643 case CHFSR_SWITCH:
2644 //idTitle = IDS_WARNMODIFIEDLOOSECHANGES;
2645 //idNoSave = IDS_ASKFORSAVE_TASK7;
2646 idCancelAction = IDS_ASKFORSAVE_TASK8;
2647 break;
2648 case CHFSR_RELOAD:
2649 //idTitle = IDS_WARNMODIFIEDLOOSECHANGES;
2650 //idNoSave = IDS_ASKFORSAVE_TASK7;
2651 idCancelAction = IDS_ASKFORSAVE_CANCEL_OPEN;
2652 break;
2653 case CHFSR_OPTIONS:
2654 idTitle = IDS_WARNMODIFIEDLOOSECHANGESOPTIONS;
2655 //idNoSave = IDS_ASKFORSAVE_TASK7;
2656 idCancelAction = IDS_ASKFORSAVE_CANCEL_OPTIONS;
2657 break;
2658 case CHFSR_OPEN:
2659 //idTitle = IDS_WARNMODIFIEDLOOSECHANGES;
2660 idNoSave = IDS_ASKFORSAVE_NOSAVE_OPEN;
2661 idCancelAction = IDS_ASKFORSAVE_CANCEL_OPEN;
2662 break;
2665 CString sTitle(MAKEINTRESOURCE(idTitle));
2666 CString sSubTitle(MAKEINTRESOURCE(IDS_ASKFORSAVE_TASK2));
2667 CString sNoSave(MAKEINTRESOURCE(idNoSave));
2668 CString sCancelAction(MAKEINTRESOURCE(idCancelAction));
2669 CString sAppName(MAKEINTRESOURCE(IDS_APPNAME));
2671 // TODO simplify logic, reduce code duplication
2672 if (CBaseView::IsViewGood(m_pwndBottomView))
2674 // three-way diff - by design only bottom can be changed
2675 // use 1.7 way to do that
2677 else if (CBaseView::IsViewGood(m_pwndRightView))
2679 // two-way diff -
2680 // 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
2681 if (HasUnsavedEdits(m_pwndLeftView))
2683 // both views
2684 UINT ret = IDNO;
2685 if (m_bUseTaskDialog)
2687 CTaskDialog taskdlg(sTitle,
2688 sSubTitle,
2689 sAppName,
2691 TDF_ENABLE_HYPERLINKS|TDF_USE_COMMAND_LINKS|TDF_ALLOW_DIALOG_CANCELLATION|TDF_POSITION_RELATIVE_TO_WINDOW);
2692 CString sTaskTemp;
2693 if (m_pwndLeftView->m_pWorkingFile->InUse() && !m_pwndLeftView->m_pWorkingFile->IsReadonly())
2694 sTaskTemp.Format(IDS_ASKFORSAVE_SAVELEFT, (LPCTSTR)m_pwndLeftView->m_pWorkingFile->GetFilename());
2695 else
2696 sTaskTemp = CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_SAVELEFTAS));
2697 taskdlg.AddCommandControl(201, sTaskTemp); // left
2698 taskdlg.SetDefaultCommandControl(201);
2699 if (HasUnsavedEdits(m_pwndRightView))
2701 if (m_pwndRightView->m_pWorkingFile->InUse() && !m_pwndRightView->m_pWorkingFile->IsReadonly())
2702 sTaskTemp.Format(IDS_ASKFORSAVE_SAVERIGHT, (LPCTSTR)m_pwndRightView->m_pWorkingFile->GetFilename());
2703 else
2704 sTaskTemp = CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_SAVERIGHTAS));
2705 taskdlg.AddCommandControl(202, sTaskTemp); // right
2706 taskdlg.AddCommandControl(203, CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_SAVEALL2))); // both
2707 taskdlg.SetDefaultCommandControl(203);
2709 taskdlg.AddCommandControl(IDNO, sNoSave); // none
2710 taskdlg.AddCommandControl(IDCANCEL, sCancelAction); // cancel
2711 taskdlg.SetCommonButtons(TDCBF_CANCEL_BUTTON);
2712 taskdlg.SetMainIcon(TD_WARNING_ICON);
2713 ret = (UINT)taskdlg.DoModal(m_hWnd);
2714 switch (ret)
2716 case 201: // left
2717 m_pwndLeftView->SaveFile(SAVE_REMOVEDLINES);
2718 break;
2719 case 203: // both
2720 m_pwndLeftView->SaveFile(SAVE_REMOVEDLINES);
2721 case 202: // right
2722 m_pwndRightView->SaveFile();
2723 break;
2725 if (ret != IDCANCEL && (eReason == CHFSR_CLOSE || eReason == CHFSR_OPEN))
2726 DeleteBaseTheirsMineOnClose();
2727 return ret;
2729 else
2731 // show separate questions
2732 // first show question for left view
2733 ret = MessageBox(sTitle, 0, MB_YESNOCANCEL | MB_ICONQUESTION);
2734 if (ret == IDCANCEL)
2736 return IDCANCEL;
2738 if (ret == IDYES)
2740 if (m_pwndLeftView->SaveFile(SAVE_REMOVEDLINES)<0)
2742 return IDCANCEL;
2745 // right file is handled old way
2746 if (eReason == CHFSR_CLOSE || eReason == CHFSR_OPEN)
2747 DeleteBaseTheirsMineOnClose();
2750 else
2752 // only secondary (left) view
2754 // only right view - 1.7 implementation is used
2756 else if (CBaseView::IsViewGood(m_pwndLeftView))
2758 // only one view - only one to save
2759 // 1.7 FileSave don't support this mode
2760 if (HasUnsavedEdits(m_pwndLeftView))
2762 UINT ret = IDNO;
2763 if (m_bUseTaskDialog)
2765 CTaskDialog taskdlg(sTitle,
2766 sSubTitle,
2767 sAppName,
2769 TDF_ENABLE_HYPERLINKS|TDF_USE_COMMAND_LINKS|TDF_ALLOW_DIALOG_CANCELLATION|TDF_POSITION_RELATIVE_TO_WINDOW);
2770 CString sTask3;
2771 if (m_Data.m_mergedFile.InUse())
2772 sTask3.Format(IDS_ASKFORSAVE_TASK3, (LPCTSTR)m_Data.m_mergedFile.GetFilename());
2773 else
2774 sTask3.LoadString(IDS_ASKFORSAVE_TASK6);
2775 taskdlg.AddCommandControl(IDYES, sTask3);
2776 taskdlg.AddCommandControl(IDNO, sNoSave);
2777 taskdlg.AddCommandControl(IDCANCEL, sCancelAction);
2778 taskdlg.SetCommonButtons(TDCBF_CANCEL_BUTTON);
2779 taskdlg.SetDefaultCommandControl(IDYES);
2780 taskdlg.SetMainIcon(TD_WARNING_ICON);
2781 ret = (UINT)taskdlg.DoModal(m_hWnd);
2783 else
2785 ret = MessageBox(sTitle, 0, MB_YESNOCANCEL | MB_ICONQUESTION);
2788 if (ret == IDYES)
2790 if (m_pwndLeftView->SaveFile()<0)
2791 return IDCANCEL;
2794 if (eReason == CHFSR_CLOSE || eReason == CHFSR_OPEN)
2795 DeleteBaseTheirsMineOnClose();
2796 return IDNO;
2798 else
2800 if (eReason == CHFSR_CLOSE || eReason == CHFSR_OPEN)
2801 DeleteBaseTheirsMineOnClose();
2802 return IDNO; // nothing to save
2805 // 1.7 implementation
2806 UINT ret = IDNO;
2807 if (HasUnsavedEdits())
2809 if (m_bUseTaskDialog)
2811 CTaskDialog taskdlg(sTitle,
2812 sSubTitle,
2813 sAppName,
2815 TDF_ENABLE_HYPERLINKS|TDF_USE_COMMAND_LINKS|TDF_ALLOW_DIALOG_CANCELLATION|TDF_POSITION_RELATIVE_TO_WINDOW);
2816 CString sTask3;
2817 if (m_Data.m_mergedFile.InUse())
2818 sTask3.Format(IDS_ASKFORSAVE_TASK3, (LPCTSTR)m_Data.m_mergedFile.GetFilename());
2819 else
2820 sTask3.LoadString(IDS_ASKFORSAVE_TASK6);
2821 taskdlg.AddCommandControl(IDYES, sTask3);
2822 taskdlg.AddCommandControl(IDNO, sNoSave);
2823 taskdlg.AddCommandControl(IDCANCEL, sCancelAction);
2824 taskdlg.SetCommonButtons(TDCBF_CANCEL_BUTTON);
2825 taskdlg.SetDefaultCommandControl(IDYES);
2826 taskdlg.SetMainIcon(TD_WARNING_ICON);
2827 ret = (UINT)taskdlg.DoModal(m_hWnd);
2829 else
2831 ret = MessageBox(sTitle, 0, MB_YESNOCANCEL | MB_ICONQUESTION);
2834 if (ret == IDYES)
2836 if (!FileSave())
2837 ret = IDCANCEL;
2841 if (ret != IDCANCEL && (eReason == CHFSR_CLOSE || eReason == CHFSR_OPEN))
2842 DeleteBaseTheirsMineOnClose();
2844 return ret;
2847 void CMainFrame::DeleteBaseTheirsMineOnClose()
2849 if (!m_bDeleteBaseTheirsMineOnClose)
2850 return;
2852 m_bDeleteBaseTheirsMineOnClose = false;
2854 DeleteFile(m_Data.m_baseFile.GetFilename());
2855 DeleteFile(m_Data.m_theirFile.GetFilename());
2856 DeleteFile(m_Data.m_yourFile.GetFilename());
2859 bool CMainFrame::HasUnsavedEdits() const
2861 return HasUnsavedEdits(m_pwndBottomView) || HasUnsavedEdits(m_pwndRightView) || m_bSaveRequired;
2864 bool CMainFrame::HasUnsavedEdits(const CBaseView* view)
2866 if (!CBaseView::IsViewGood(view))
2867 return false;
2868 return view->IsModified();
2871 bool CMainFrame::HasMarkedBlocks() const
2873 return CBaseView::IsViewGood(m_pwndRightView) && m_pwndRightView->HasMarkedBlocks();
2876 bool CMainFrame::IsViewGood(const CBaseView* view)
2878 return CBaseView::IsViewGood(view);
2881 void CMainFrame::OnViewInlinediffword()
2883 m_bInlineWordDiff = !m_bInlineWordDiff;
2884 if (m_pwndLeftView)
2886 m_pwndLeftView->SetInlineWordDiff(m_bInlineWordDiff);
2887 m_pwndLeftView->BuildAllScreen2ViewVector();
2888 m_pwndLeftView->DocumentUpdated();
2890 if (m_pwndRightView)
2892 m_pwndRightView->SetInlineWordDiff(m_bInlineWordDiff);
2893 m_pwndRightView->BuildAllScreen2ViewVector();
2894 m_pwndRightView->DocumentUpdated();
2896 if (m_pwndBottomView)
2898 m_pwndBottomView->SetInlineWordDiff(m_bInlineWordDiff);
2899 m_pwndBottomView->BuildAllScreen2ViewVector();
2900 m_pwndBottomView->DocumentUpdated();
2902 m_wndLineDiffBar.DocumentUpdated();
2905 void CMainFrame::OnUpdateViewInlinediffword(CCmdUI *pCmdUI)
2907 pCmdUI->Enable(m_bInlineDiff && IsViewGood(m_pwndLeftView) && IsViewGood(m_pwndRightView));
2908 pCmdUI->SetCheck(m_bInlineWordDiff);
2911 void CMainFrame::OnViewInlinediff()
2913 m_bInlineDiff = !m_bInlineDiff;
2914 if (m_pwndLeftView)
2916 m_pwndLeftView->SetInlineDiff(m_bInlineDiff);
2917 m_pwndLeftView->BuildAllScreen2ViewVector();
2918 m_pwndLeftView->DocumentUpdated();
2920 if (m_pwndRightView)
2922 m_pwndRightView->SetInlineDiff(m_bInlineDiff);
2923 m_pwndRightView->BuildAllScreen2ViewVector();
2924 m_pwndRightView->DocumentUpdated();
2926 if (m_pwndBottomView)
2928 m_pwndBottomView->SetInlineDiff(m_bInlineDiff);
2929 m_pwndBottomView->BuildAllScreen2ViewVector();
2930 m_pwndBottomView->DocumentUpdated();
2932 m_wndLineDiffBar.DocumentUpdated();
2935 void CMainFrame::OnUpdateViewInlinediff(CCmdUI *pCmdUI)
2937 pCmdUI->Enable(IsViewGood(m_pwndLeftView) && IsViewGood(m_pwndRightView));
2938 pCmdUI->SetCheck(m_bInlineDiff);
2941 void CMainFrame::OnUpdateEditCreateunifieddifffile(CCmdUI *pCmdUI)
2943 // "create unified diff file" is only available if two files
2944 // are diffed, not three.
2945 bool bEnabled = true;
2946 if (!IsViewGood(m_pwndLeftView))
2947 bEnabled = false;
2948 else if (!IsViewGood(m_pwndRightView))
2949 bEnabled = false;
2950 else if (IsViewGood(m_pwndBottomView)) //no negation here
2951 bEnabled = false;
2952 pCmdUI->Enable(bEnabled);
2955 void CMainFrame::OnEditCreateunifieddifffile()
2957 CString origFile, modifiedFile;
2958 // the original file is the one on the left
2959 if (m_pwndLeftView)
2960 origFile = m_pwndLeftView->m_sFullFilePath;
2961 if (m_pwndRightView)
2962 modifiedFile = m_pwndRightView->m_sFullFilePath;
2963 if (origFile.IsEmpty() || modifiedFile.IsEmpty())
2964 return;
2966 CString outputFile;
2967 if(!TryGetFileName(outputFile))
2968 return;
2970 CRegStdDWORD regContextLines(L"Software\\TortoiseGitMerge\\ContextLines", (DWORD)-1);
2971 CAppUtils::CreateUnifiedDiff(origFile, modifiedFile, outputFile, regContextLines, true);
2974 void CMainFrame::OnUpdateViewLinediffbar(CCmdUI *pCmdUI)
2976 pCmdUI->SetCheck(m_bLineDiff);
2977 pCmdUI->Enable();
2980 void CMainFrame::OnViewLinediffbar()
2982 m_bLineDiff = !m_bLineDiff;
2983 m_wndLineDiffBar.ShowPane(m_bLineDiff, false, true);
2984 m_wndLineDiffBar.DocumentUpdated();
2985 m_wndLocatorBar.ShowPane(m_bLocatorBar, false, true);
2986 m_wndLocatorBar.DocumentUpdated();
2989 void CMainFrame::OnUpdateViewLocatorbar(CCmdUI *pCmdUI)
2991 pCmdUI->SetCheck(m_bLocatorBar);
2992 pCmdUI->Enable();
2995 void CMainFrame::OnViewLocatorbar()
2997 m_bLocatorBar = !m_bLocatorBar;
2998 m_wndLocatorBar.ShowPane(m_bLocatorBar, false, true);
2999 m_wndLocatorBar.DocumentUpdated();
3000 m_wndLineDiffBar.ShowPane(m_bLineDiff, false, true);
3001 m_wndLineDiffBar.DocumentUpdated();
3004 void CMainFrame::OnViewComparewhitespaces()
3006 if (CheckForSave(CHFSR_OPTIONS)==IDCANCEL)
3007 return;
3008 CRegDWORD regIgnoreWS(L"Software\\TortoiseGitMerge\\IgnoreWS");
3009 regIgnoreWS = 0;
3010 LoadViews(-1);
3013 void CMainFrame::OnUpdateViewComparewhitespaces(CCmdUI *pCmdUI)
3015 CRegDWORD regIgnoreWS(L"Software\\TortoiseGitMerge\\IgnoreWS");
3016 DWORD dwIgnoreWS = regIgnoreWS;
3017 pCmdUI->SetCheck(dwIgnoreWS == 0);
3020 void CMainFrame::OnViewIgnorewhitespacechanges()
3022 if (CheckForSave(CHFSR_OPTIONS)==IDCANCEL)
3023 return;
3024 CRegDWORD regIgnoreWS(L"Software\\TortoiseGitMerge\\IgnoreWS");
3025 regIgnoreWS = 2;
3026 LoadViews(-1);
3029 void CMainFrame::OnUpdateViewIgnorewhitespacechanges(CCmdUI *pCmdUI)
3031 CRegDWORD regIgnoreWS(L"Software\\TortoiseGitMerge\\IgnoreWS");
3032 DWORD dwIgnoreWS = regIgnoreWS;
3033 pCmdUI->SetCheck(dwIgnoreWS == 2);
3036 void CMainFrame::OnViewIgnoreallwhitespacechanges()
3038 if (CheckForSave(CHFSR_OPTIONS)==IDCANCEL)
3039 return;
3040 CRegDWORD regIgnoreWS(L"Software\\TortoiseGitMerge\\IgnoreWS");
3041 regIgnoreWS = 1;
3042 LoadViews(-1);
3045 void CMainFrame::OnUpdateViewIgnoreallwhitespacechanges(CCmdUI *pCmdUI)
3047 CRegDWORD regIgnoreWS(L"Software\\TortoiseGitMerge\\IgnoreWS");
3048 DWORD dwIgnoreWS = regIgnoreWS;
3049 pCmdUI->SetCheck(dwIgnoreWS == 1);
3052 void CMainFrame::OnViewMovedBlocks()
3054 m_bViewMovedBlocks = !(DWORD)m_regViewModedBlocks;
3055 m_regViewModedBlocks = m_bViewMovedBlocks;
3056 LoadViews(-1);
3059 void CMainFrame::OnUpdateViewMovedBlocks(CCmdUI *pCmdUI)
3061 pCmdUI->SetCheck(m_bViewMovedBlocks);
3062 BOOL bEnable = TRUE;
3063 if (IsViewGood(m_pwndBottomView))
3065 bEnable = FALSE;
3067 pCmdUI->Enable(bEnable);
3070 bool CMainFrame::HasConflictsWontKeep()
3072 const int nConflictLine = CheckResolved();
3073 if (nConflictLine < 0)
3074 return false;
3075 if (m_pwndBottomView == nullptr)
3076 return false;
3078 CString sTemp;
3079 sTemp.Format(IDS_ERR_MAINFRAME_FILEHASCONFLICTS, m_pwndBottomView->m_pViewData->GetLineNumber(nConflictLine)+1);
3080 bool bSave = false;
3081 if (m_bUseTaskDialog)
3083 CTaskDialog taskdlg(sTemp,
3084 CString(MAKEINTRESOURCE(IDS_ERR_MAINFRAME_FILEHASCONFLICTS_TASK2)),
3085 L"TortoiseGitMerge",
3087 TDF_ENABLE_HYPERLINKS|TDF_USE_COMMAND_LINKS|TDF_ALLOW_DIALOG_CANCELLATION|TDF_POSITION_RELATIVE_TO_WINDOW);
3088 taskdlg.AddCommandControl(1, CString(MAKEINTRESOURCE(IDS_ERR_MAINFRAME_FILEHASCONFLICTS_TASK3)));
3089 taskdlg.AddCommandControl(2, CString(MAKEINTRESOURCE(IDS_ERR_MAINFRAME_FILEHASCONFLICTS_TASK4)));
3090 taskdlg.SetCommonButtons(TDCBF_CANCEL_BUTTON);
3091 taskdlg.SetDefaultCommandControl(2);
3092 taskdlg.SetMainIcon(TD_ERROR_ICON);
3093 bSave = (taskdlg.DoModal(m_hWnd) == 1);
3095 else
3097 bSave = (MessageBox(sTemp, 0, MB_ICONERROR | MB_YESNO)==IDYES);
3100 if (bSave)
3101 return false;
3103 m_pwndBottomView->GoToLine(nConflictLine);
3104 return true;
3107 bool CMainFrame::TryGetFileName(CString& result)
3109 return CCommonAppUtils::FileOpenSave(result, NULL, IDS_SAVEASTITLE, IDS_COMMONFILEFILTER, false, m_hWnd);
3112 CBaseView* CMainFrame::GetActiveBaseView() const
3114 CView* activeView = GetActiveView();
3115 CBaseView* activeBase = dynamic_cast<CBaseView*>( activeView );
3116 return activeBase;
3119 void CMainFrame::SetWindowTitle()
3121 // try to find a suitable window title
3122 CString sYour = m_Data.m_yourFile.GetDescriptiveName();
3123 if (sYour.Find(_T(" - "))>=0)
3124 sYour = sYour.Left(sYour.Find(_T(" - ")));
3125 if (sYour.Find(_T(" : "))>=0)
3126 sYour = sYour.Left(sYour.Find(_T(" : ")));
3127 CString sTheir = m_Data.m_theirFile.GetDescriptiveName();
3128 if (sTheir.IsEmpty())
3129 sTheir = m_Data.m_baseFile.GetDescriptiveName();
3130 if (sTheir.Find(_T(" - "))>=0)
3131 sTheir = sTheir.Left(sTheir.Find(_T(" - ")));
3132 if (sTheir.Find(_T(" : "))>=0)
3133 sTheir = sTheir.Left(sTheir.Find(_T(" : ")));
3135 if (!sYour.IsEmpty() && !sTheir.IsEmpty())
3137 if (sYour.CompareNoCase(sTheir)==0)
3138 SetWindowText(sYour + _T(" - TortoiseGitMerge"));
3139 else if ((sYour.GetLength() < 10) &&
3140 (sTheir.GetLength() < 10))
3141 SetWindowText(sYour + _T(" - ") + sTheir + _T(" - TortoiseGitMerge"));
3142 else
3144 // we have two very long descriptive texts here, which
3145 // means we have to find a way to use them as a window
3146 // title in a shorter way.
3147 // for simplicity, we just use the one from "yourfile"
3148 SetWindowText(sYour + _T(" - TortoiseGitMerge"));
3151 else if (!sYour.IsEmpty())
3152 SetWindowText(sYour + _T(" - TortoiseGitMerge"));
3153 else if (!sTheir.IsEmpty())
3154 SetWindowText(sTheir + _T(" - TortoiseGitMerge"));
3155 else
3156 SetWindowText(L"TortoiseGitMerge");
3159 void CMainFrame::OnTimer(UINT_PTR nIDEvent)
3161 switch (nIDEvent)
3163 case IDT_RELOADCHECKTIMER:
3164 KillTimer(nIDEvent);
3165 CheckForReload();
3166 break;
3169 __super::OnTimer(nIDEvent);
3172 void CMainFrame::LoadIgnoreCommentData()
3174 static bool bLoaded = false;
3175 if (bLoaded)
3176 return;
3177 CString sPath = CPathUtils::GetAppDataDirectory() + L"ignorecomments.txt";
3178 if (!PathFileExists(sPath))
3180 // ignore comments file does not exist (yet), so create a default one
3181 HRSRC hRes = FindResource(NULL, MAKEINTRESOURCE(IDR_IGNORECOMMENTSTXT), L"config");
3182 if (hRes)
3184 HGLOBAL hResourceLoaded = LoadResource(NULL, hRes);
3185 if (hResourceLoaded)
3187 char * lpResLock = (char *) LockResource(hResourceLoaded);
3188 DWORD dwSizeRes = SizeofResource(NULL, hRes);
3189 if (lpResLock)
3191 HANDLE hFile = CreateFile(sPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
3192 if (hFile != INVALID_HANDLE_VALUE)
3194 DWORD dwWritten = 0;
3195 WriteFile(hFile, lpResLock, dwSizeRes, &dwWritten, NULL);
3196 CloseHandle(hFile);
3205 CStdioFile file;
3206 if (file.Open(sPath, CFile::modeRead))
3208 CString sLine;
3209 while (file.ReadString(sLine))
3211 int eqpos = sLine.Find('=');
3212 if (eqpos >= 0)
3214 CString sExts = sLine.Left(eqpos);
3215 CString sComments = sLine.Mid(eqpos+1);
3217 int pos = sComments.Find(',');
3218 CString sLineStart = sComments.Left(pos);
3219 pos = sComments.Find(',', pos);
3220 int pos2 = sComments.Find(',', pos+1);
3221 CString sBlockStart = sComments.Mid(pos+1, pos2-pos-1);
3222 CString sBlockEnd = sComments.Mid(pos2+1);
3224 auto commentTuple = std::make_tuple(sLineStart, sBlockStart, sBlockEnd);
3226 pos = 0;
3227 CString temp;
3228 for (;;)
3230 temp = sExts.Tokenize(_T(","),pos);
3231 if (temp.IsEmpty())
3233 break;
3235 ASSERT(m_IgnoreCommentsMap.find(temp) == m_IgnoreCommentsMap.end());
3236 m_IgnoreCommentsMap[temp] = commentTuple;
3242 catch (CFileException* e)
3244 e->Delete();
3246 bLoaded = true;
3249 void CMainFrame::OnViewIgnorecomments()
3251 if (CheckForSave(CHFSR_OPTIONS)==IDCANCEL)
3252 return;
3253 m_regIgnoreComments = !DWORD(m_regIgnoreComments);
3254 LoadViews(-1);
3257 void CMainFrame::OnUpdateViewIgnorecomments(CCmdUI *pCmdUI)
3259 // only enable if we have comments defined for this file extension
3260 CString sExt = CPathUtils::GetFileExtFromPath(m_Data.m_baseFile.GetFilename()).MakeLower();
3261 sExt.TrimLeft(L".");
3262 auto sC = m_IgnoreCommentsMap.find(sExt);
3263 if (sC == m_IgnoreCommentsMap.end())
3265 sExt = CPathUtils::GetFileExtFromPath(m_Data.m_yourFile.GetFilename()).MakeLower();
3266 sExt.TrimLeft(L".");
3267 sC = m_IgnoreCommentsMap.find(sExt);
3268 if (sC == m_IgnoreCommentsMap.end())
3270 sExt = CPathUtils::GetFileExtFromPath(m_Data.m_theirFile.GetFilename()).MakeLower();
3271 sExt.TrimLeft(L".");
3272 sC = m_IgnoreCommentsMap.find(sExt);
3275 pCmdUI->Enable(sC != m_IgnoreCommentsMap.end());
3277 pCmdUI->SetCheck(DWORD(m_regIgnoreComments) != 0);
3281 void CMainFrame::OnRegexfilter(UINT cmd)
3283 if ((cmd == ID_REGEXFILTER)||(cmd == (ID_REGEXFILTER+1)))
3285 CRegexFiltersDlg dlg(this);
3286 dlg.SetIniFile(&m_regexIni);
3287 if (dlg.DoModal() == IDOK)
3289 FILE * pFile = NULL;
3290 _tfopen_s(&pFile, CPathUtils::GetAppDataDirectory() + L"regexfilters.ini", _T("wb"));
3291 m_regexIni.SaveFile(pFile);
3292 fclose(pFile);
3294 BuildRegexSubitems();
3296 else
3298 if (cmd == (UINT)m_regexIndex)
3300 if (CheckForSave(CHFSR_OPTIONS)==IDCANCEL)
3301 return;
3302 m_Data.SetRegexTokens(std::wregex(), L"");
3303 m_regexIndex = -1;
3304 LoadViews(-1);
3306 else
3308 CSimpleIni::TNamesDepend sections;
3309 m_regexIni.GetAllSections(sections);
3310 int index = ID_REGEXFILTER + 2;
3311 m_regexIndex = -1;
3312 for (const auto& section : sections)
3314 if (cmd == (UINT)index)
3316 if (CheckForSave(CHFSR_OPTIONS)==IDCANCEL)
3317 break;
3320 std::wregex rx(m_regexIni.GetValue(section, L"regex", L""));
3321 m_Data.SetRegexTokens(rx, m_regexIni.GetValue(section, L"replace", L""));
3323 catch (std::exception &ex)
3325 MessageBox(_T("Regex is invalid!\r\n") + CString(ex.what()));
3327 m_regexIndex = index;
3328 LoadViews(-1);
3329 break;
3331 ++index;
3337 void CMainFrame::OnUpdateViewRegexFilter( CCmdUI *pCmdUI )
3339 pCmdUI->Enable();
3340 pCmdUI->SetCheck(pCmdUI->m_nID == (UINT)m_regexIndex);
3343 void CMainFrame::BuildRegexSubitems()
3345 CArray<CMFCRibbonBaseElement*, CMFCRibbonBaseElement*> arButtons;
3346 m_wndRibbonBar.GetElementsByID(ID_REGEXFILTER, arButtons);
3347 if (arButtons.GetCount() == 1)
3349 CMFCRibbonButton * pButton = (CMFCRibbonButton*)arButtons.GetAt(0);
3350 if (pButton)
3352 pButton->RemoveAllSubItems();
3353 pButton->AddSubItem(new CMFCRibbonButton(ID_REGEXFILTER+1, CString(MAKEINTRESOURCE(IDS_CONFIGUREREGEXES)), 47));
3355 CString sIniPath = CPathUtils::GetAppDataDirectory() + L"regexfilters.ini";
3356 if (!PathFileExists(sIniPath))
3358 // ini file does not exist (yet), so create a default one
3359 HRSRC hRes = FindResource(NULL, MAKEINTRESOURCE(IDR_REGEXFILTERINI), L"config");
3360 if (hRes)
3362 HGLOBAL hResourceLoaded = LoadResource(NULL, hRes);
3363 if (hResourceLoaded)
3365 char * lpResLock = (char *) LockResource(hResourceLoaded);
3366 DWORD dwSizeRes = SizeofResource(NULL, hRes);
3367 if (lpResLock)
3369 HANDLE hFile = CreateFile(sIniPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
3370 if (hFile != INVALID_HANDLE_VALUE)
3372 DWORD dwWritten = 0;
3373 WriteFile(hFile, lpResLock, dwSizeRes, &dwWritten, NULL);
3374 CloseHandle(hFile);
3381 m_regexIni.LoadFile(sIniPath);
3382 CSimpleIni::TNamesDepend sections;
3383 m_regexIni.GetAllSections(sections);
3384 if (!sections.empty())
3385 pButton->AddSubItem(new CMFCRibbonSeparator(TRUE));
3386 int cmdIndex = 2;
3387 for (const auto& section : sections)
3389 pButton->AddSubItem(new CMFCRibbonButton(ID_REGEXFILTER+cmdIndex, section, 46));
3390 cmdIndex++;
3396 void CMainFrame::FillEncodingButton( CMFCRibbonButton * pButton, int start )
3398 pButton->SetDefaultCommand(FALSE);
3399 pButton->AddSubItem(new CMFCRibbonButton(start + CFileTextLines::UnicodeType::ASCII, L"ASCII" ));
3400 pButton->AddSubItem(new CMFCRibbonButton(start + CFileTextLines::UnicodeType::BINARY, L"BINARY" ));
3401 pButton->AddSubItem(new CMFCRibbonButton(start + CFileTextLines::UnicodeType::UTF16_LE, L"UTF-16LE" ));
3402 pButton->AddSubItem(new CMFCRibbonButton(start + CFileTextLines::UnicodeType::UTF16_LEBOM, L"UTF-16LE BOM"));
3403 pButton->AddSubItem(new CMFCRibbonButton(start + CFileTextLines::UnicodeType::UTF16_BE, L"UTF-16BE" ));
3404 pButton->AddSubItem(new CMFCRibbonButton(start + CFileTextLines::UnicodeType::UTF16_BEBOM, L"UTF-16BE BOM"));
3405 pButton->AddSubItem(new CMFCRibbonButton(start + CFileTextLines::UnicodeType::UTF32_LE, L"UTF-32LE" ));
3406 pButton->AddSubItem(new CMFCRibbonButton(start + CFileTextLines::UnicodeType::UTF32_BE, L"UTF-32BE" ));
3407 pButton->AddSubItem(new CMFCRibbonButton(start + CFileTextLines::UnicodeType::UTF8, L"UTF-8" ));
3408 pButton->AddSubItem(new CMFCRibbonButton(start + CFileTextLines::UnicodeType::UTF8BOM, L"UTF-8 BOM" ));
3411 void CMainFrame::FillEOLButton( CMFCRibbonButton * pButton, int start )
3413 pButton->SetDefaultCommand(FALSE);
3414 pButton->AddSubItem(new CMFCRibbonButton(start + EOL::EOL_LF , L"LF" ));
3415 pButton->AddSubItem(new CMFCRibbonButton(start + EOL::EOL_CRLF, L"CRLF"));
3416 pButton->AddSubItem(new CMFCRibbonButton(start + EOL::EOL_LFCR, L"LRCR"));
3417 pButton->AddSubItem(new CMFCRibbonButton(start + EOL::EOL_CR , L"CR" ));
3418 pButton->AddSubItem(new CMFCRibbonButton(start + EOL::EOL_VT , L"VT" ));
3419 pButton->AddSubItem(new CMFCRibbonButton(start + EOL::EOL_FF , L"FF" ));
3420 pButton->AddSubItem(new CMFCRibbonButton(start + EOL::EOL_NEL , L"NEL" ));
3421 pButton->AddSubItem(new CMFCRibbonButton(start + EOL::EOL_LS , L"LS" ));
3422 pButton->AddSubItem(new CMFCRibbonButton(start + EOL::EOL_PS , L"PS" ));
3425 void CMainFrame::FillTabModeButton(CMFCRibbonButton * pButton, int start)
3427 pButton->SetDefaultCommand(FALSE);
3428 pButton->AddSubItem(new CMFCRibbonButton(start + TABMODE_NONE , L"Tab"));
3429 pButton->AddSubItem(new CMFCRibbonButton(start + TABMODE_USESPACES , L"Space"));
3430 pButton->AddSubItem(new CMFCRibbonSeparator(TRUE));
3431 pButton->AddSubItem(new CMFCRibbonButton(start + TABMODE_SMARTINDENT , L"Smart tab char"));
3432 pButton->AddSubItem(new CMFCRibbonSeparator(TRUE));
3433 pButton->AddSubItem(new CMFCRibbonButton(start + TABSIZEBUTTON1, L"1"));
3434 pButton->AddSubItem(new CMFCRibbonButton(start + TABSIZEBUTTON2, L"2"));
3435 pButton->AddSubItem(new CMFCRibbonButton(start + TABSIZEBUTTON4, L"4"));
3436 pButton->AddSubItem(new CMFCRibbonButton(start + TABSIZEBUTTON8, L"8"));
3437 pButton->AddSubItem(new CMFCRibbonSeparator(TRUE));
3438 pButton->AddSubItem(new CMFCRibbonButton(start + ENABLEEDITORCONFIG, L"EditorConfig"));
3441 void CMainFrame::OnEncodingLeft( UINT cmd )
3443 if (m_pwndLeftView)
3445 m_pwndLeftView->SetTextType(CFileTextLines::UnicodeType(cmd-ID_INDICATOR_LEFTENCODINGSTART));
3446 m_pwndLeftView->RefreshViews();
3450 void CMainFrame::OnEncodingRight( UINT cmd )
3452 if (m_pwndRightView)
3454 m_pwndRightView->SetTextType(CFileTextLines::UnicodeType(cmd-ID_INDICATOR_RIGHTENCODINGSTART));
3455 m_pwndRightView->RefreshViews();
3459 void CMainFrame::OnEncodingBottom( UINT cmd )
3461 if (m_pwndBottomView)
3463 m_pwndBottomView->SetTextType(CFileTextLines::UnicodeType(cmd-ID_INDICATOR_BOTTOMENCODINGSTART));
3464 m_pwndBottomView->RefreshViews();
3468 void CMainFrame::OnEOLLeft( UINT cmd )
3470 if (m_pwndLeftView)
3472 m_pwndLeftView->ReplaceLineEndings(EOL(cmd-ID_INDICATOR_LEFTEOLSTART));
3473 m_pwndLeftView->RefreshViews();
3477 void CMainFrame::OnEOLRight( UINT cmd )
3479 if (m_pwndRightView)
3481 m_pwndRightView->ReplaceLineEndings(EOL(cmd-ID_INDICATOR_RIGHTEOLSTART));
3482 m_pwndRightView->RefreshViews();
3486 void CMainFrame::OnEOLBottom( UINT cmd )
3488 if (m_pwndBottomView)
3490 m_pwndBottomView->ReplaceLineEndings(EOL(cmd-ID_INDICATOR_BOTTOMEOLSTART));
3491 m_pwndBottomView->RefreshViews();
3495 void CMainFrame::OnTabModeLeft( UINT cmd )
3497 OnTabMode(m_pwndLeftView, (int)cmd - ID_INDICATOR_LEFTTABMODESTART);
3500 void CMainFrame::OnTabModeRight( UINT cmd )
3502 OnTabMode(m_pwndRightView, (int)cmd - ID_INDICATOR_RIGHTTABMODESTART);
3505 void CMainFrame::OnTabModeBottom( UINT cmd )
3507 OnTabMode(m_pwndBottomView, (int)cmd - ID_INDICATOR_BOTTOMTABMODESTART);
3510 void CMainFrame::OnTabMode(CBaseView *view, int cmd)
3512 if (!view)
3513 return;
3514 int nTabMode = view->GetTabMode();
3515 if (cmd == TABMODE_NONE || cmd == TABMODE_USESPACES)
3516 view->SetTabMode((nTabMode & (~TABMODE_USESPACES)) | (cmd & TABMODE_USESPACES));
3517 else if (cmd == TABMODE_SMARTINDENT) // Toggle
3518 view->SetTabMode((nTabMode & (~TABMODE_SMARTINDENT)) | ((nTabMode & TABMODE_SMARTINDENT) ? 0 : TABMODE_SMARTINDENT));
3519 else if (cmd == TABSIZEBUTTON1)
3520 view->SetTabSize(1);
3521 else if (cmd == TABSIZEBUTTON2)
3522 view->SetTabSize(2);
3523 else if (cmd == TABSIZEBUTTON4)
3524 view->SetTabSize(4);
3525 else if (cmd == TABSIZEBUTTON8)
3526 view->SetTabSize(8);
3527 else if (cmd == ENABLEEDITORCONFIG)
3528 view->SetEditorConfigEnabled(!view->GetEditorConfigEnabled());
3529 view->RefreshViews();
3532 void CMainFrame::OnUpdateEncodingLeft( CCmdUI *pCmdUI )
3534 if (m_pwndLeftView)
3536 pCmdUI->SetCheck(CFileTextLines::UnicodeType(pCmdUI->m_nID - ID_INDICATOR_LEFTENCODINGSTART) == m_pwndLeftView->GetTextType());
3537 pCmdUI->Enable(m_pwndLeftView->IsWritable());
3539 else
3540 pCmdUI->Enable(FALSE);
3543 void CMainFrame::OnUpdateEncodingRight( CCmdUI *pCmdUI )
3545 if (m_pwndRightView)
3547 pCmdUI->SetCheck(CFileTextLines::UnicodeType(pCmdUI->m_nID - ID_INDICATOR_RIGHTENCODINGSTART) == m_pwndRightView->GetTextType());
3548 pCmdUI->Enable(m_pwndRightView->IsWritable());
3550 else
3551 pCmdUI->Enable(FALSE);
3554 void CMainFrame::OnUpdateEncodingBottom( CCmdUI *pCmdUI )
3556 if (m_pwndBottomView)
3558 pCmdUI->SetCheck(CFileTextLines::UnicodeType(pCmdUI->m_nID - ID_INDICATOR_BOTTOMENCODINGSTART) == m_pwndBottomView->GetTextType());
3559 pCmdUI->Enable(m_pwndBottomView->IsWritable());
3561 else
3562 pCmdUI->Enable(FALSE);
3565 void CMainFrame::OnUpdateEOLLeft( CCmdUI *pCmdUI )
3567 if (m_pwndLeftView)
3569 pCmdUI->SetCheck(EOL(pCmdUI->m_nID - ID_INDICATOR_LEFTEOLSTART) == m_pwndLeftView->GetLineEndings());
3570 pCmdUI->Enable(m_pwndLeftView->IsWritable());
3572 else
3573 pCmdUI->Enable(FALSE);
3576 void CMainFrame::OnUpdateEOLRight( CCmdUI *pCmdUI )
3578 if (m_pwndRightView)
3580 pCmdUI->SetCheck(EOL(pCmdUI->m_nID - ID_INDICATOR_RIGHTEOLSTART) == m_pwndRightView->GetLineEndings());
3581 pCmdUI->Enable(m_pwndRightView->IsWritable());
3583 else
3584 pCmdUI->Enable(FALSE);
3587 void CMainFrame::OnUpdateEOLBottom( CCmdUI *pCmdUI )
3589 if (m_pwndBottomView)
3591 pCmdUI->SetCheck(EOL(pCmdUI->m_nID - ID_INDICATOR_BOTTOMEOLSTART) == m_pwndBottomView->GetLineEndings());
3592 pCmdUI->Enable(m_pwndBottomView->IsWritable());
3594 else
3595 pCmdUI->Enable(FALSE);
3598 void CMainFrame::OnUpdateTabModeLeft(CCmdUI *pCmdUI)
3600 OnUpdateTabMode(m_pwndLeftView, pCmdUI, ID_INDICATOR_LEFTTABMODESTART);
3603 void CMainFrame::OnUpdateTabModeRight(CCmdUI *pCmdUI)
3605 OnUpdateTabMode(m_pwndRightView, pCmdUI, ID_INDICATOR_RIGHTTABMODESTART);
3608 void CMainFrame::OnUpdateTabModeBottom(CCmdUI *pCmdUI)
3610 OnUpdateTabMode(m_pwndBottomView, pCmdUI, ID_INDICATOR_BOTTOMTABMODESTART);
3613 void CMainFrame::OnUpdateTabMode(CBaseView *view, CCmdUI *pCmdUI, int startid)
3615 if (view)
3617 int cmd = (int)pCmdUI->m_nID - startid;
3618 if (cmd == TABMODE_NONE)
3619 pCmdUI->SetCheck((view->GetTabMode() & TABMODE_USESPACES) == TABMODE_NONE);
3620 else if (cmd == TABMODE_USESPACES)
3621 pCmdUI->SetCheck(view->GetTabMode() & TABMODE_USESPACES);
3622 else if (cmd == TABMODE_SMARTINDENT)
3623 pCmdUI->SetCheck(view->GetTabMode() & TABMODE_SMARTINDENT);
3624 else if (cmd == TABSIZEBUTTON1)
3625 pCmdUI->SetCheck(view->GetTabSize() == 1);
3626 else if (cmd == TABSIZEBUTTON2)
3627 pCmdUI->SetCheck(view->GetTabSize() == 2);
3628 else if (cmd == TABSIZEBUTTON4)
3629 pCmdUI->SetCheck(view->GetTabSize() == 4);
3630 else if (cmd == TABSIZEBUTTON8)
3631 pCmdUI->SetCheck(view->GetTabSize() == 8);
3632 else if (cmd == ENABLEEDITORCONFIG)
3633 pCmdUI->SetCheck(view->GetEditorConfigEnabled());
3634 pCmdUI->Enable(view->IsWritable());
3635 if (cmd == ENABLEEDITORCONFIG)
3636 pCmdUI->Enable(view->IsWritable() && view->GetEditorConfigLoaded());
3638 else
3639 pCmdUI->Enable(FALSE);