1 // TortoiseGitMerge - a Diff/Patch program
3 // Copyright (C) 2008-2014 - TortoiseGit
4 // Copyright (C) 2004-2014 - 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.
22 #include "TortoiseMerge.h"
23 #include "CustomMFCRibbonButton.h"
25 #include "SysProgressDlg.h"
27 #include "MessageBox.h"
29 #include "PathUtils.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"
39 #include "SmartLibgit2Ref.h" // needs to be included after git2.h
40 #include "RegexFiltersDlg.h"
47 CCustomMFCRibbonButton button1
;
50 const UINT TaskBarButtonCreated
= RegisterWindowMessage(L
"TaskbarButtonCreated");
51 #define IDT_RELOADCHECKTIMER 123
53 IMPLEMENT_DYNCREATE(CMainFrame
, CFrameWndEx
)
55 BEGIN_MESSAGE_MAP(CMainFrame
, CFrameWndEx
)
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
)
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
)
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
)
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
)
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
)
179 static UINT indicators
[] =
181 ID_SEPARATOR
, // status line indicator
182 ID_INDICATOR_LEFTVIEW
,
183 ID_INDICATOR_RIGHTVIEW
,
184 ID_INDICATOR_BOTTOMVIEW
,
190 // CMainFrame construction/destruction
192 CMainFrame::CMainFrame()
193 : m_bInitSplitter(FALSE
)
194 , m_bReversedPatch(FALSE
)
195 , m_bHasConflicts(false)
196 , m_bInlineWordDiff(true)
198 , m_bLocatorBar(true)
199 , m_nMoveMovesToIgnore(0)
200 , m_pwndLeftView(NULL
)
201 , m_pwndRightView(NULL
)
202 , m_pwndBottomView(NULL
)
205 , m_bCheckReload(false)
206 , m_bSaveRequired(false)
207 , m_bSaveRequiredOnConflicts(false)
208 , m_bDeleteBaseTheirsMineOnClose(false)
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
)
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
;
230 if (SysInfo::Instance().IsXP())
231 m_bUseRibbons
= FALSE
;
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
);
248 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct
)
250 if (CFrameWndEx::OnCreate(lpCreateStruct
) == -1)
253 OnApplicationLook(theApp
.m_nAppLook
);
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);
264 CMFCRibbonPanel
* pPanel
= pMainCat
->GetPanel(3);
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
));
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
"");
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
);
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
);
389 BOOL
CMainFrame::PreCreateWindow(CREATESTRUCT
& cs
)
391 if( !CFrameWndEx::PreCreateWindow(cs
) )
396 void CMainFrame::OnApplicationLook(UINT id
)
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
);
409 case ID_VIEW_APPLOOK_OFF_XP
:
410 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOfficeXP
));
411 m_wndRibbonBar
.SetWindows7Look(FALSE
);
414 case ID_VIEW_APPLOOK_WIN_XP
:
415 CMFCVisualManagerWindows::m_b3DTabsXPTheme
= TRUE
;
416 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows
));
417 m_wndRibbonBar
.SetWindows7Look(FALSE
);
420 case ID_VIEW_APPLOOK_OFF_2003
:
421 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2003
));
422 CDockingManager::SetDockingMode(DT_SMART
);
423 m_wndRibbonBar
.SetWindows7Look(FALSE
);
426 case ID_VIEW_APPLOOK_VS_2005
:
427 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerVS2005
));
428 CDockingManager::SetDockingMode(DT_SMART
);
429 m_wndRibbonBar
.SetWindows7Look(FALSE
);
432 case ID_VIEW_APPLOOK_VS_2008
:
433 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerVS2008
));
434 CDockingManager::SetDockingMode(DT_SMART
);
435 m_wndRibbonBar
.SetWindows7Look(FALSE
);
438 case ID_VIEW_APPLOOK_WIN7
:
439 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows7
));
440 CDockingManager::SetDockingMode(DT_SMART
);
441 m_wndRibbonBar
.SetWindows7Look(TRUE
);
445 switch (theApp
.m_nAppLook
)
447 case ID_VIEW_APPLOOK_OFF_2007_BLUE
:
448 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_LunaBlue
);
451 case ID_VIEW_APPLOOK_OFF_2007_BLACK
:
452 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_ObsidianBlack
);
455 case ID_VIEW_APPLOOK_OFF_2007_SILVER
:
456 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_Silver
);
459 case ID_VIEW_APPLOOK_OFF_2007_AQUA
:
460 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_Aqua
);
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
)
477 pCmdUI
->SetRadio(theApp
.m_nAppLook
== pCmdUI
->m_nID
);
481 // CMainFrame diagnostics
484 void CMainFrame::AssertValid() const
486 CFrameWndEx::AssertValid();
489 void CMainFrame::Dump(CDumpContext
& dc
) const
491 CFrameWndEx::Dump(dc
);
497 // CMainFrame message handlers
500 BOOL
CMainFrame::OnCreateClient(LPCREATESTRUCT
/*lpcs*/, CCreateContext
* pContext
)
506 // split into three panes:
515 // create a splitter with 2 rows, 1 column
516 if (!m_wndSplitter
.CreateStatic(this, 2, 1))
518 TRACE0("Failed to CreateStaticSplitter\n");
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");
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");
541 m_pwndBottomView
= (CBottomView
*)m_wndSplitter
.GetPane(1,0);
542 m_pwndBottomView
->m_pwndLocator
= &m_wndLocatorBar
;
543 m_pwndBottomView
->m_pwndLineDiffBar
= &m_wndLineDiffBar
;
545 m_pwndBottomView
->m_pwndRibbonStatusBar
= &m_wndRibbonStatusBar
;
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");
558 m_pwndLeftView
= (CLeftView
*)m_wndSplitter2
.GetPane(0,0);
559 m_pwndLeftView
->m_pwndLocator
= &m_wndLocatorBar
;
560 m_pwndLeftView
->m_pwndLineDiffBar
= &m_wndLineDiffBar
;
562 m_pwndLeftView
->m_pwndRibbonStatusBar
= &m_wndRibbonStatusBar
;
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");
573 m_pwndRightView
= (CRightView
*)m_wndSplitter2
.GetPane(0,1);
574 m_pwndRightView
->m_pwndLocator
= &m_wndLocatorBar
;
575 m_pwndRightView
->m_pwndLineDiffBar
= &m_wndLineDiffBar
;
577 m_pwndRightView
->m_pwndRibbonStatusBar
= &m_wndRibbonStatusBar
;
579 m_pwndRightView
->m_pwndStatusBar
= &m_wndStatusBar
;
580 m_pwndRightView
->m_pMainFrame
= this;
581 m_bInitSplitter
= TRUE
;
583 m_dlgFilePatches
.Create(IDD_FILEPATCHES
, this);
589 BOOL
CMainFrame::PatchFile(CString sFilePath
, bool /*bContentMods*/, bool bPropMods
, CString sVersion
, BOOL bAutoPatch
)
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
);
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
);
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();
618 if ((!PathFileExists(sBasePath
))||(PathIsDirectory(sBasePath
)))
620 m_Data
.m_baseFile
.SetFileName(CTempFiles::Instance().GetTempFilePathString());
621 m_Data
.m_baseFile
.CreateEmptyFile();
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
);
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();
640 if (!PathFileExists(sFilePath
) || PathIsDirectory(sFilePath
))
642 m_Data
.m_yourFile
.SetFileName(CTempFiles::Instance().GetTempFilePathString());
643 m_Data
.m_yourFile
.CreateEmptyFile();
645 temp
.Format(_T("%s %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sFilePath
), CString(MAKEINTRESOURCE(IDS_NOTFOUNDVIEWTITLEINDICATOR
)));
646 m_Data
.m_yourFile
.SetDescriptiveName(temp
);
649 m_Data
.m_yourFile
.SetFileName(sFilePath
);
650 m_Data
.m_theirFile
.SetFileName(sTempFile
);
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
);
661 if (!sRejectedFile
.IsEmpty())
664 // start TortoiseUDiff with the rejected hunks
666 sTitle
.Format(IDS_TITLE_REJECTEDHUNKS
, (LPCTSTR
)CPathUtils::GetFileNameFromPath(sFilePath
));
667 CAppUtils::StartUnifiedDiffViewer(sRejectedFile
, sTitle
);
672 if (sBasePath
!= sFilePath
&& HasConflictsWontKeep())
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
));
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
))
704 sErrMsg
.Format(IDS_ERR_MAINFRAME_FILEVERSIONNOTFOUND
, (LPCTSTR
)sRev1
, (LPCTSTR
)sURL1
);
705 MessageBox(sErrMsg
, NULL
, MB_ICONERROR
);
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
))
716 sErrMsg
.Format(IDS_ERR_MAINFRAME_FILEVERSIONNOTFOUND
, (LPCTSTR
)sRev2
, (LPCTSTR
)sURL2
);
717 MessageBox(sErrMsg
, NULL
, MB_ICONERROR
);
720 progDlg
.SetProgress(100,100);
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
);
735 void CMainFrame::OnFileOpen()
737 if (CheckForSave(CHFSR_OPEN
)==IDCANCEL
)
739 return OnFileOpen(false);
742 void CMainFrame::OnFileOpen(bool fillyours
)
746 dlg
.m_sBaseFile
= m_Data
.m_yourFile
.GetFilename();
747 if (dlg
.DoModal() != IDOK
)
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;
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;
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();
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
));
826 m_Data
.SetCommentTokens(L
"", L
"", L
"");
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;
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
)))
868 ClearViewNamesAndPaths();
869 MessageBox(m_Patch
.GetErrorMessage(), NULL
, MB_ICONERROR
);
870 m_bSaveRequired
= false;
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)
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
)),
887 TDF_ENABLE_HYPERLINKS
|TDF_USE_COMMAND_LINKS
|TDF_ALLOW_DIALOG_CANCELLATION
|TDF_POSITION_RELATIVE_TO_WINDOW
);
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
);
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
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
);
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
;
1021 sWarning
+= m_Data
.m_arBaseFile
.GetEncodingName(m_Data
.m_arBaseFile
.GetUnicodeType());
1023 sWarning
+= m_Data
.m_arYourFile
.GetEncodingName(m_Data
.m_arYourFile
.GetUnicodeType());
1028 sWarning
+= L
"\r\n";
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();
1094 SetActiveView(pwndActiveView
);
1096 if ((line
>= -1) && m_pwndRightView
->m_pViewData
)
1098 int n
= line
== -1 ? min( nOldLineNumber
, nOldLine
) : line
;
1100 n
= m_pwndRightView
->m_pViewData
->FindLineNumber(n
);
1104 m_pwndRightView
->ScrollAllToLine(n
);
1108 if ((ptOldCaretPos
.x
>= 0) || (ptOldCaretPos
.y
>= 0))
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);
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
;
1139 // Avoid incorrect rendering of active pane.
1140 m_pwndBottomView
->ScrollToChar(0);
1141 m_pwndLeftView
->ScrollToChar(0);
1142 m_pwndRightView
->ScrollToChar(0);
1146 if (m_bHasConflicts
&& !m_bSaveRequiredOnConflicts
)
1147 m_bSaveRequired
= false;
1148 CUndo::GetInstance().Clear();
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);
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);
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;
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
);
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
);
1224 ::SystemParametersInfo(SPI_GETWORKAREA
, 0, &rect
, 0);
1229 GetWindowPlacement(&wp
);
1230 if (wp
.ptMaxPosition
.x
|| wp
.ptMaxPosition
.y
)
1232 wp
.ptMaxPosition
.x
= wp
.ptMaxPosition
.y
= 0;
1233 SetWindowPlacement(&wp
);
1244 void CMainFrame::OnViewWhitespaces()
1246 CRegDWORD regViewWhitespaces
= CRegDWORD(_T("Software\\TortoiseGitMerge\\ViewWhitespaces"), 1);
1247 BOOL bViewWhitespaces
= regViewWhitespaces
;
1249 bViewWhitespaces
= m_pwndLeftView
->m_bViewWhitespace
;
1251 bViewWhitespaces
= !bViewWhitespaces
;
1252 regViewWhitespaces
= bViewWhitespaces
;
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
)
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
)
1313 view
->BuildAllScreen2ViewVector();
1314 view
->UpdateCaret();
1316 view
->EnsureCaretVisible();
1319 void CMainFrame::OnUpdateViewWraplonglines(CCmdUI
*pCmdUI
)
1321 pCmdUI
->SetCheck(m_bWrapLines
);
1324 void CMainFrame::OnViewOnewaydiff()
1326 if (CheckForSave(CHFSR_RELOAD
)==IDCANCEL
)
1328 m_bOneWay
= !m_bOneWay
;
1329 ShowDiffBar(!m_bOneWay
);
1333 void CMainFrame::ShowDiffBar(bool 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();
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
;
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
))
1368 m_bHasConflicts
= false;
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
;
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
);
1411 case DIFFSTATE_CONFLICTED
:
1412 case DIFFSTATE_CONFLICTED_IGNORED
:
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());
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
1451 file
.Add(pViewData
->GetLine(i
), pViewData
->GetLineEnding(i
));
1455 if (!file
.Save(sFilePath
, false, false))
1457 CMessageBox::Show(m_hWnd
, file
.GetErrorString(), _T("TortoiseGitMerge"), MB_ICONERROR
);
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();
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(
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
)
1487 return file
.GetCount();
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
);
1515 else if (nModifiedViewCount
>0)
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
);
1527 if (m_pwndLeftView
->m_pWorkingFile
->InUse() && !m_pwndLeftView
->m_pWorkingFile
->IsReadonly())
1528 sTaskTemp
.Format(IDS_ASKFORSAVE_SAVELEFT
, (LPCTSTR
)m_pwndLeftView
->m_pWorkingFile
->GetFilename());
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());
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
);
1553 m_pwndLeftView
->SaveFile(SAVE_REMOVEDLINES
);
1556 m_pwndLeftView
->SaveFile(SAVE_REMOVEDLINES
);
1558 m_pwndRightView
->SaveFile();
1566 // only target view was modified
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());
1583 // file was saved with 0 lines, remove it.
1584 m_Patch
.RemoveFile(m_Data
.m_mergedFile
.GetFilename());
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
,
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
);
1624 m_pwndRightView
->LeaveOnlyMarkedBlocks();
1626 m_pwndRightView
->UseViewFileOfMarked();
1628 m_pwndRightView
->UseViewFileExceptEdited();
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
);
1644 m_pwndRightView
->LeaveOnlyMarkedBlocks();
1645 else if (ret
== IDNO
)
1646 m_pwndRightView
->UseViewFileOfMarked();
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())
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());
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
)
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);
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
);
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
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 (g_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);
1728 subpath
= subpath
.Right(subpath
.GetLength() - projectRoot
.GetLength());
1731 CAutoRepository
repository(projectRoot
);
1732 bool hasConflictInIndex
= false;
1739 if (git_repository_index(index
.GetPointer(), repository
))
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;
1747 if (hasConflictInIndex
)
1749 bool bResolve
= false;
1750 if (m_bUseTaskDialog
)
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);
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
);
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
))
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);
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
);
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);
1841 if (TryGetFileName(sFileName
))
1843 m_pwndRightView
->SaveFileTo(sFileName
);
1849 case 204: // continue resolving
1850 if (m_pwndBottomView
)
1852 m_pwndBottomView
->GoToLine(CheckResolved());
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
)
1877 if (TryGetFileName(sFileName
))
1879 m_pwndLeftView
->SaveFileTo(sFileName
);
1889 if (TryGetFileName(sFileName
))
1891 m_pwndLeftView
->SaveFileTo(sFileName
);
1898 bool CMainFrame::FileSaveAs(bool bCheckResolved
/*=true*/)
1900 if (bCheckResolved
&& HasConflictsWontKeep())
1904 if(!TryGetFileName(fileName
))
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
))
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)) )
1921 else if (IsViewGood(m_pwndLeftView
)
1922 && (m_pwndLeftView
->m_pViewData
)
1923 && (m_pwndLeftView
->IsModified()))
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
))
1935 else if (IsViewGood(m_pwndRightView
)&&(m_pwndRightView
->m_pViewData
))
1937 else if (IsViewGood(m_pwndLeftView
)&&(m_pwndLeftView
->m_pViewData
))
1939 pCmdUI
->Enable(bEnable
);
1942 void CMainFrame::OnUpdateViewOnewaydiff(CCmdUI
*pCmdUI
)
1944 pCmdUI
->SetCheck(!m_bOneWay
);
1945 BOOL bEnable
= TRUE
;
1946 if (IsViewGood(m_pwndBottomView
))
1950 pCmdUI
->Enable(bEnable
);
1953 void CMainFrame::OnViewOptions()
1956 sTemp
.LoadString(IDS_SETTINGSTITLE
);
1957 CSettings
dlg(sTemp
);
1959 if (dlg
.IsReloadNeeded())
1961 if (CheckForSave(CHFSR_OPTIONS
)==IDCANCEL
)
1963 CDiffColors::GetInstance().LoadRegistry();
1967 CDiffColors::GetInstance().LoadRegistry();
1968 if (m_pwndBottomView
)
1969 m_pwndBottomView
->Invalidate();
1971 m_pwndLeftView
->Invalidate();
1972 if (m_pwndRightView
)
1973 m_pwndRightView
->Invalidate();
1976 void CMainFrame::OnClose()
1978 if (CheckForSave(CHFSR_CLOSE
)!=IDCANCEL
)
1982 // before it is destroyed, save the position of the window
1983 wp
.length
= sizeof wp
;
1985 if (GetWindowPlacement(&wp
))
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
;
1997 WriteWindowPlacement(&wp
);
2003 void CMainFrame::OnActivate(UINT nValue
, CWnd
* /*pwnd*/, BOOL
/*bActivated?*/)
2005 if (nValue
!= 0) // activated
2009 m_bCheckReload
= TRUE
;
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
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
)
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
)
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();
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();
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
)
2164 CDiffColors::GetInstance().LoadRegistry();
2168 void CMainFrame::ActivateFrame(int nCmdShow
)
2170 // nCmdShow is the normal show mode this frame should be in
2171 // translate default 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
);
2185 // show the window as specified
2188 if ( !ReadWindowPlacement(&wp
) )
2190 ShowWindow(nCmdShow
);
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())
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
);
2219 pwp
->length
= sizeof(WINDOWPLACEMENT
);
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
)
2242 BOOL bEnable
= FALSE
;
2243 if ((!m_bReadOnly
)&&(m_Data
.m_mergedFile
.InUse()))
2245 if (IsViewGood(m_pwndBottomView
)&&(m_pwndBottomView
->m_pViewData
))
2250 pCmdUI
->Enable(bEnable
);
2253 void CMainFrame::OnMergeMarkasresolved()
2255 if(HasConflictsWontKeep())
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
))
2264 m_bSaveRequired
= false;
2270 BOOL
CMainFrame::MarkAsResolved()
2274 if (!IsViewGood(m_pwndBottomView
))
2277 CString cmd
= _T("/command:resolve /path:\"");
2278 cmd
+= m_Data
.m_mergedFile
.GetFilename();
2279 cmd
+= _T("\" /closeonend:1 /noquestion /skipcheck /silent");
2283 s
.Format(L
" /resolvemsghwnd:%I64d /resolvemsgwparam:%I64d /resolvemsglparam:%I64d", (__int64
)resolveMsgWnd
, (__int64
)resolveMsgWParam
, (__int64
)resolveMsgLParam
);
2286 if(!CAppUtils::RunTortoiseGitProc(cmd
))
2288 m_bSaveRequired
= false;
2292 void CMainFrame::OnUpdateMergeNextconflict(CCmdUI
*pCmdUI
)
2295 if (HasNextConflict(m_pwndBottomView
))
2297 else if (HasNextConflict(m_pwndRightView
))
2299 else if (HasNextConflict(m_pwndLeftView
))
2301 pCmdUI
->Enable(bShow
);
2304 bool CMainFrame::HasNextConflict(CBaseView
* view
)
2308 if (!view
->IsTarget())
2310 return view
->HasNextConflict();
2313 void CMainFrame::OnUpdateMergePreviousconflict(CCmdUI
*pCmdUI
)
2316 if (HasPrevConflict(m_pwndBottomView
))
2318 else if (HasPrevConflict(m_pwndRightView
))
2320 else if (HasPrevConflict(m_pwndLeftView
))
2322 pCmdUI
->Enable(bShow
);
2325 bool CMainFrame::HasPrevConflict(CBaseView
* view
)
2329 if (!view
->IsTarget())
2331 return view
->HasPrevConflict();
2334 void CMainFrame::OnUpdateNavigateNextdifference(CCmdUI
*pCmdUI
)
2336 CBaseView
* baseView
= GetActiveBaseView();
2339 bShow
= baseView
->HasNextDiff();
2340 pCmdUI
->Enable(bShow
);
2343 void CMainFrame::OnUpdateNavigatePreviousdifference(CCmdUI
*pCmdUI
)
2345 CBaseView
* baseView
= GetActiveBaseView();
2348 bShow
= baseView
->HasPrevDiff();
2349 pCmdUI
->Enable(bShow
);
2352 void CMainFrame::OnUpdateNavigateNextinlinediff(CCmdUI
*pCmdUI
)
2355 if (HasNextInlineDiff(m_pwndBottomView
))
2357 else if (HasNextInlineDiff(m_pwndRightView
))
2359 else if (HasNextInlineDiff(m_pwndLeftView
))
2361 pCmdUI
->Enable(bShow
);
2364 bool CMainFrame::HasNextInlineDiff(CBaseView
* view
)
2368 if (!view
->IsTarget())
2370 return view
->HasNextInlineDiff();
2373 void CMainFrame::OnUpdateNavigatePrevinlinediff(CCmdUI
*pCmdUI
)
2376 if (HasPrevInlineDiff(m_pwndBottomView
))
2378 else if (HasPrevInlineDiff(m_pwndRightView
))
2380 else if (HasPrevInlineDiff(m_pwndLeftView
))
2382 pCmdUI
->Enable(bShow
);
2385 bool CMainFrame::HasPrevInlineDiff(CBaseView
* view
)
2389 if (!view
->IsTarget())
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
))
2401 m_dlgFilePatches
.GetWindowRect(&patchrect
);
2402 if (::IsWindow(m_hWnd
))
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
)
2419 if ((m_pwndBottomView
)&&(m_pwndBottomView
->HasSelection()))
2421 else if ((m_pwndRightView
)&&(m_pwndRightView
->HasSelection()))
2423 else if ((m_pwndLeftView
)&&(m_pwndLeftView
->HasSelection()))
2425 pCmdUI
->Enable(bShow
);
2428 void CMainFrame::OnUpdateEditPaste(CCmdUI
*pCmdUI
)
2430 BOOL bWritable
= FALSE
;
2431 if ((m_pwndBottomView
)&&(m_pwndBottomView
->IsWritable()))
2433 else if ((m_pwndRightView
)&&(m_pwndRightView
->IsWritable()))
2435 else if ((m_pwndLeftView
)&&(m_pwndLeftView
->IsWritable()))
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
;
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();
2505 pCmdUI
->Enable(pView
->IsReadonlyChangable() || !pView
->IsReadonly());
2506 pCmdUI
->SetCheck(!pView
->IsReadonly());
2510 pCmdUI
->Enable(FALSE
);
2514 void CMainFrame::OnIndicatorLeftview()
2518 if (IsViewGood(m_pwndLeftView
))
2520 m_pwndLeftView
->AskUserForNewLineEndingsAndTextType(IDS_STATUSBAR_LEFTVIEW
);
2524 void CMainFrame::OnIndicatorRightview()
2528 if (IsViewGood(m_pwndRightView
))
2530 m_pwndRightView
->AskUserForNewLineEndingsAndTextType(IDS_STATUSBAR_RIGHTVIEW
);
2534 void CMainFrame::OnIndicatorBottomview()
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
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
)
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
);
2573 if (HasUnsavedEdits())
2574 sTask3
.LoadString(IDS_WARNMODIFIEDOUTSIDE_TASK3
);
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
);
2586 int idsMessage
= HasUnsavedEdits() ? IDS_WARNMODIFIEDOUTSIDELOOSECHANGES
: IDS_WARNMODIFIEDOUTSIDE
;
2587 ret
= CMessageBox::Show(m_hWnd
, idsMessage
, IDS_APPNAME
, MB_YESNO
| MB_ICONQUESTION
);
2592 CDiffColors::GetInstance().LoadRegistry();
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();
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();
2631 int CMainFrame::CheckForSave(ECheckForSaveReason eReason
)
2633 int idTitle
= IDS_WARNMODIFIEDLOOSECHANGES
;
2634 int idNoSave
= IDS_ASKFORSAVE_TASK7
;
2635 int idCancelAction
= IDS_ASKFORSAVE_CANCEL_OPEN
;
2639 //idTitle = IDS_WARNMODIFIEDLOOSECHANGES;
2640 idNoSave
= IDS_ASKFORSAVE_TASK4
;
2641 idCancelAction
= IDS_ASKFORSAVE_TASK5
;
2644 //idTitle = IDS_WARNMODIFIEDLOOSECHANGES;
2645 //idNoSave = IDS_ASKFORSAVE_TASK7;
2646 idCancelAction
= IDS_ASKFORSAVE_TASK8
;
2649 //idTitle = IDS_WARNMODIFIEDLOOSECHANGES;
2650 //idNoSave = IDS_ASKFORSAVE_TASK7;
2651 idCancelAction
= IDS_ASKFORSAVE_CANCEL_OPEN
;
2654 idTitle
= IDS_WARNMODIFIEDLOOSECHANGESOPTIONS
;
2655 //idNoSave = IDS_ASKFORSAVE_TASK7;
2656 idCancelAction
= IDS_ASKFORSAVE_CANCEL_OPTIONS
;
2659 //idTitle = IDS_WARNMODIFIEDLOOSECHANGES;
2660 idNoSave
= IDS_ASKFORSAVE_NOSAVE_OPEN
;
2661 idCancelAction
= IDS_ASKFORSAVE_CANCEL_OPEN
;
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
))
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
))
2685 if (m_bUseTaskDialog
)
2687 CTaskDialog
taskdlg(sTitle
,
2691 TDF_ENABLE_HYPERLINKS
|TDF_USE_COMMAND_LINKS
|TDF_ALLOW_DIALOG_CANCELLATION
|TDF_POSITION_RELATIVE_TO_WINDOW
);
2693 if (m_pwndLeftView
->m_pWorkingFile
->InUse() && !m_pwndLeftView
->m_pWorkingFile
->IsReadonly())
2694 sTaskTemp
.Format(IDS_ASKFORSAVE_SAVELEFT
, (LPCTSTR
)m_pwndLeftView
->m_pWorkingFile
->GetFilename());
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());
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
);
2717 m_pwndLeftView
->SaveFile(SAVE_REMOVEDLINES
);
2720 m_pwndLeftView
->SaveFile(SAVE_REMOVEDLINES
);
2722 m_pwndRightView
->SaveFile();
2725 if (ret
!= IDCANCEL
&& (eReason
== CHFSR_CLOSE
|| eReason
== CHFSR_OPEN
))
2726 DeleteBaseTheirsMineOnClose();
2731 // show separate questions
2732 // first show question for left view
2733 ret
= MessageBox(sTitle
, 0, MB_YESNOCANCEL
| MB_ICONQUESTION
);
2734 if (ret
== IDCANCEL
)
2740 if (m_pwndLeftView
->SaveFile(SAVE_REMOVEDLINES
)<0)
2745 // right file is handled old way
2746 if (eReason
== CHFSR_CLOSE
|| eReason
== CHFSR_OPEN
)
2747 DeleteBaseTheirsMineOnClose();
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
))
2763 if (m_bUseTaskDialog
)
2765 CTaskDialog
taskdlg(sTitle
,
2769 TDF_ENABLE_HYPERLINKS
|TDF_USE_COMMAND_LINKS
|TDF_ALLOW_DIALOG_CANCELLATION
|TDF_POSITION_RELATIVE_TO_WINDOW
);
2771 if (m_Data
.m_mergedFile
.InUse())
2772 sTask3
.Format(IDS_ASKFORSAVE_TASK3
, (LPCTSTR
)m_Data
.m_mergedFile
.GetFilename());
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
);
2785 ret
= MessageBox(sTitle
, 0, MB_YESNOCANCEL
| MB_ICONQUESTION
);
2790 if (m_pwndLeftView
->SaveFile()<0)
2794 if (eReason
== CHFSR_CLOSE
|| eReason
== CHFSR_OPEN
)
2795 DeleteBaseTheirsMineOnClose();
2800 if (eReason
== CHFSR_CLOSE
|| eReason
== CHFSR_OPEN
)
2801 DeleteBaseTheirsMineOnClose();
2802 return IDNO
; // nothing to save
2805 // 1.7 implementation
2807 if (HasUnsavedEdits())
2809 if (m_bUseTaskDialog
)
2811 CTaskDialog
taskdlg(sTitle
,
2815 TDF_ENABLE_HYPERLINKS
|TDF_USE_COMMAND_LINKS
|TDF_ALLOW_DIALOG_CANCELLATION
|TDF_POSITION_RELATIVE_TO_WINDOW
);
2817 if (m_Data
.m_mergedFile
.InUse())
2818 sTask3
.Format(IDS_ASKFORSAVE_TASK3
, (LPCTSTR
)m_Data
.m_mergedFile
.GetFilename());
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
);
2831 ret
= MessageBox(sTitle
, 0, MB_YESNOCANCEL
| MB_ICONQUESTION
);
2841 if (ret
!= IDCANCEL
&& (eReason
== CHFSR_CLOSE
|| eReason
== CHFSR_OPEN
))
2842 DeleteBaseTheirsMineOnClose();
2847 void CMainFrame::DeleteBaseTheirsMineOnClose()
2849 if (!m_bDeleteBaseTheirsMineOnClose
)
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
))
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
;
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
;
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
))
2948 else if (!IsViewGood(m_pwndRightView
))
2950 else if (IsViewGood(m_pwndBottomView
)) //no negation here
2952 pCmdUI
->Enable(bEnabled
);
2955 void CMainFrame::OnEditCreateunifieddifffile()
2957 CString origFile
, modifiedFile
;
2958 // the original file is the one on the left
2960 origFile
= m_pwndLeftView
->m_sFullFilePath
;
2961 if (m_pwndRightView
)
2962 modifiedFile
= m_pwndRightView
->m_sFullFilePath
;
2963 if (origFile
.IsEmpty() || modifiedFile
.IsEmpty())
2967 if(!TryGetFileName(outputFile
))
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
);
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
);
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
)
3008 CRegDWORD
regIgnoreWS(L
"Software\\TortoiseGitMerge\\IgnoreWS");
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
)
3024 CRegDWORD
regIgnoreWS(L
"Software\\TortoiseGitMerge\\IgnoreWS");
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
)
3040 CRegDWORD
regIgnoreWS(L
"Software\\TortoiseGitMerge\\IgnoreWS");
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
;
3059 void CMainFrame::OnUpdateViewMovedBlocks(CCmdUI
*pCmdUI
)
3061 pCmdUI
->SetCheck(m_bViewMovedBlocks
);
3062 BOOL bEnable
= TRUE
;
3063 if (IsViewGood(m_pwndBottomView
))
3067 pCmdUI
->Enable(bEnable
);
3070 bool CMainFrame::HasConflictsWontKeep()
3072 const int nConflictLine
= CheckResolved();
3073 if (nConflictLine
< 0)
3075 if (m_pwndBottomView
== nullptr)
3079 sTemp
.Format(IDS_ERR_MAINFRAME_FILEHASCONFLICTS
, m_pwndBottomView
->m_pViewData
->GetLineNumber(nConflictLine
)+1);
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);
3097 bSave
= (MessageBox(sTemp
, 0, MB_ICONERROR
| MB_YESNO
)==IDYES
);
3103 m_pwndBottomView
->GoToLine(nConflictLine
);
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
);
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"));
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"));
3156 SetWindowText(L
"TortoiseGitMerge");
3159 void CMainFrame::OnTimer(UINT_PTR nIDEvent
)
3163 case IDT_RELOADCHECKTIMER
:
3164 KillTimer(nIDEvent
);
3169 __super::OnTimer(nIDEvent
);
3172 void CMainFrame::LoadIgnoreCommentData()
3174 static bool bLoaded
= false;
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");
3184 HGLOBAL hResourceLoaded
= LoadResource(NULL
, hRes
);
3185 if (hResourceLoaded
)
3187 char * lpResLock
= (char *) LockResource(hResourceLoaded
);
3188 DWORD dwSizeRes
= SizeofResource(NULL
, hRes
);
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
);
3206 if (file
.Open(sPath
, CFile::modeRead
))
3209 while (file
.ReadString(sLine
))
3211 int eqpos
= sLine
.Find('=');
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
);
3230 temp
= sExts
.Tokenize(_T(","),pos
);
3235 ASSERT(m_IgnoreCommentsMap
.find(temp
) == m_IgnoreCommentsMap
.end());
3236 m_IgnoreCommentsMap
[temp
] = commentTuple
;
3242 catch (CFileException
* e
)
3249 void CMainFrame::OnViewIgnorecomments()
3251 if (CheckForSave(CHFSR_OPTIONS
)==IDCANCEL
)
3253 m_regIgnoreComments
= !DWORD(m_regIgnoreComments
);
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
);
3294 BuildRegexSubitems();
3298 if (cmd
== (UINT
)m_regexIndex
)
3300 if (CheckForSave(CHFSR_OPTIONS
)==IDCANCEL
)
3302 m_Data
.SetRegexTokens(std::wregex(), L
"");
3308 CSimpleIni::TNamesDepend sections
;
3309 m_regexIni
.GetAllSections(sections
);
3310 int index
= ID_REGEXFILTER
+ 2;
3312 for (const auto& section
: sections
)
3314 if (cmd
== (UINT
)index
)
3316 if (CheckForSave(CHFSR_OPTIONS
)==IDCANCEL
)
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
;
3337 void CMainFrame::OnUpdateViewRegexFilter( CCmdUI
*pCmdUI
)
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);
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");
3362 HGLOBAL hResourceLoaded
= LoadResource(NULL
, hRes
);
3363 if (hResourceLoaded
)
3365 char * lpResLock
= (char *) LockResource(hResourceLoaded
);
3366 DWORD dwSizeRes
= SizeofResource(NULL
, hRes
);
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
);
3381 m_regexIni
.LoadFile(sIniPath
);
3382 CSimpleIni::TNamesDepend sections
;
3383 m_regexIni
.GetAllSections(sections
);
3384 if (!sections
.empty())
3385 pButton
->AddSubItem(new CMFCRibbonSeparator(TRUE
));
3387 for (const auto& section
: sections
)
3389 pButton
->AddSubItem(new CMFCRibbonButton(ID_REGEXFILTER
+cmdIndex
, section
, 46));
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
)
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
)
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
)
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
)
3536 pCmdUI
->SetCheck(CFileTextLines::UnicodeType(pCmdUI
->m_nID
- ID_INDICATOR_LEFTENCODINGSTART
) == m_pwndLeftView
->GetTextType());
3537 pCmdUI
->Enable(m_pwndLeftView
->IsWritable());
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());
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());
3562 pCmdUI
->Enable(FALSE
);
3565 void CMainFrame::OnUpdateEOLLeft( CCmdUI
*pCmdUI
)
3569 pCmdUI
->SetCheck(EOL(pCmdUI
->m_nID
- ID_INDICATOR_LEFTEOLSTART
) == m_pwndLeftView
->GetLineEndings());
3570 pCmdUI
->Enable(m_pwndLeftView
->IsWritable());
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());
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());
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
)
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());
3639 pCmdUI
->Enable(FALSE
);