1 // TortoiseGitMerge - a Diff/Patch program
3 // Copyright (C) 2008-2016 - TortoiseGit
4 // Copyright (C) 2004-2015 - TortoiseSVN
5 // Copyright (C) 2012-2014 - Sven Strickroth <email@cs-ware.de>
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 2
10 // of the License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software Foundation,
19 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
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"
38 #include "RegexFiltersDlg.h"
44 CCustomMFCRibbonButton button1
;
47 #define IDT_RELOADCHECKTIMER 123
49 IMPLEMENT_DYNCREATE(CMainFrame
, CFrameWndEx
)
51 BEGIN_MESSAGE_MAP(CMainFrame
, CFrameWndEx
)
53 ON_COMMAND_RANGE(ID_VIEW_APPLOOK_WIN7
, ID_VIEW_APPLOOK_OFF_2007_AQUA
, &CMainFrame::OnApplicationLook
)
54 ON_UPDATE_COMMAND_UI_RANGE(IDC_STYLEBUTTON
, ID_VIEW_APPLOOK_OFF_2007_AQUA
, &CMainFrame::OnUpdateApplicationLook
)
55 // Global help commands
56 ON_COMMAND(ID_HELP_FINDER
, CFrameWndEx::OnHelpFinder
)
57 ON_COMMAND(ID_HELP
, CFrameWndEx::OnHelp
)
58 ON_COMMAND(ID_CONTEXT_HELP
, CFrameWndEx::OnContextHelp
)
59 ON_COMMAND(ID_DEFAULT_HELP
, CFrameWndEx::OnHelpFinder
)
60 ON_COMMAND(ID_FILE_OPEN
, OnFileOpen
)
61 ON_COMMAND(ID_VIEW_WHITESPACES
, OnViewWhitespaces
)
63 ON_COMMAND(ID_FILE_SAVE
, OnFileSave
)
64 ON_COMMAND(ID_FILE_SAVE_AS
, OnFileSaveAs
)
65 ON_UPDATE_COMMAND_UI(ID_FILE_SAVE
, OnUpdateFileSave
)
66 ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_AS
, OnUpdateFileSaveAs
)
67 ON_COMMAND(ID_VIEW_ONEWAYDIFF
, OnViewOnewaydiff
)
68 ON_UPDATE_COMMAND_UI(ID_VIEW_ONEWAYDIFF
, OnUpdateViewOnewaydiff
)
69 ON_UPDATE_COMMAND_UI(ID_VIEW_WHITESPACES
, OnUpdateViewWhitespaces
)
70 ON_COMMAND(ID_VIEW_OPTIONS
, OnViewOptions
)
73 ON_COMMAND(ID_FILE_RELOAD
, OnFileReload
)
74 ON_COMMAND(ID_VIEW_LINEDOWN
, OnViewLinedown
)
75 ON_COMMAND(ID_VIEW_LINEUP
, OnViewLineup
)
76 ON_COMMAND(ID_VIEW_MOVEDBLOCKS
, OnViewMovedBlocks
)
77 ON_UPDATE_COMMAND_UI(ID_VIEW_MOVEDBLOCKS
, OnUpdateViewMovedBlocks
)
78 ON_UPDATE_COMMAND_UI(ID_EDIT_MARKASRESOLVED
, OnUpdateMergeMarkasresolved
)
79 ON_COMMAND(ID_EDIT_MARKASRESOLVED
, OnMergeMarkasresolved
)
80 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_NEXTCONFLICT
, OnUpdateMergeNextconflict
)
81 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_PREVIOUSCONFLICT
, OnUpdateMergePreviousconflict
)
84 ON_UPDATE_COMMAND_UI(ID_EDIT_COPY
, OnUpdateEditCopy
)
85 ON_COMMAND(ID_VIEW_SWITCHLEFT
, OnViewSwitchleft
)
86 ON_UPDATE_COMMAND_UI(ID_VIEW_SWITCHLEFT
, OnUpdateViewSwitchleft
)
87 ON_COMMAND(ID_VIEW_LINELEFT
, &CMainFrame::OnViewLineleft
)
88 ON_COMMAND(ID_VIEW_LINERIGHT
, &CMainFrame::OnViewLineright
)
89 ON_UPDATE_COMMAND_UI(ID_VIEW_SHOWFILELIST
, &CMainFrame::OnUpdateViewShowfilelist
)
90 ON_COMMAND(ID_VIEW_SHOWFILELIST
, &CMainFrame::OnViewShowfilelist
)
91 ON_COMMAND(ID_EDIT_USETHEIRBLOCK
, &CMainFrame::OnEditUseTheirs
)
92 ON_COMMAND(ID_EDIT_USEMYBLOCK
, &CMainFrame::OnEditUseMine
)
93 ON_COMMAND(ID_EDIT_USETHEIRTHENMYBLOCK
, &CMainFrame::OnEditUseTheirsThenMine
)
94 ON_COMMAND(ID_EDIT_USEMINETHENTHEIRBLOCK
, &CMainFrame::OnEditUseMineThenTheirs
)
95 ON_COMMAND(ID_EDIT_UNDO
, &CMainFrame::OnEditUndo
)
96 ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO
, &CMainFrame::OnUpdateEditUndo
)
97 ON_COMMAND(ID_EDIT_REDO
, &CMainFrame::OnEditRedo
)
98 ON_UPDATE_COMMAND_UI(ID_EDIT_REDO
, &CMainFrame::OnUpdateEditRedo
)
99 ON_COMMAND(ID_EDIT_ENABLE
, &CMainFrame::OnEditEnable
)
100 ON_UPDATE_COMMAND_UI(ID_EDIT_ENABLE
, &CMainFrame::OnUpdateEditEnable
)
101 ON_UPDATE_COMMAND_UI(ID_EDIT_USEMINETHENTHEIRBLOCK
, &CMainFrame::OnUpdateEditUseminethentheirblock
)
102 ON_UPDATE_COMMAND_UI(ID_EDIT_USEMYBLOCK
, &CMainFrame::OnUpdateEditUsemyblock
)
103 ON_UPDATE_COMMAND_UI(ID_EDIT_USETHEIRBLOCK
, &CMainFrame::OnUpdateEditUsetheirblock
)
104 ON_UPDATE_COMMAND_UI(ID_EDIT_USETHEIRTHENMYBLOCK
, &CMainFrame::OnUpdateEditUsetheirthenmyblock
)
105 ON_COMMAND(ID_VIEW_INLINEDIFFWORD
, &CMainFrame::OnViewInlinediffword
)
106 ON_UPDATE_COMMAND_UI(ID_VIEW_INLINEDIFFWORD
, &CMainFrame::OnUpdateViewInlinediffword
)
107 ON_COMMAND(ID_VIEW_INLINEDIFF
, &CMainFrame::OnViewInlinediff
)
108 ON_UPDATE_COMMAND_UI(ID_VIEW_INLINEDIFF
, &CMainFrame::OnUpdateViewInlinediff
)
109 ON_UPDATE_COMMAND_UI(ID_EDIT_CREATEUNIFIEDDIFFFILE
, &CMainFrame::OnUpdateEditCreateunifieddifffile
)
110 ON_COMMAND(ID_EDIT_CREATEUNIFIEDDIFFFILE
, &CMainFrame::OnEditCreateunifieddifffile
)
111 ON_UPDATE_COMMAND_UI(ID_VIEW_LINEDIFFBAR
, &CMainFrame::OnUpdateViewLinediffbar
)
112 ON_COMMAND(ID_VIEW_LINEDIFFBAR
, &CMainFrame::OnViewLinediffbar
)
113 ON_UPDATE_COMMAND_UI(ID_VIEW_BARS
, &CMainFrame::OnUpdateViewBars
)
114 ON_UPDATE_COMMAND_UI(ID_VIEW_LOCATORBAR
, &CMainFrame::OnUpdateViewLocatorbar
)
115 ON_COMMAND(ID_VIEW_LOCATORBAR
, &CMainFrame::OnViewLocatorbar
)
116 ON_COMMAND(ID_EDIT_USELEFTBLOCK
, &CMainFrame::OnEditUseleftblock
)
117 ON_UPDATE_COMMAND_UI(ID_USEBLOCKS
, &CMainFrame::OnUpdateUseBlock
)
118 ON_UPDATE_COMMAND_UI(ID_EDIT_USELEFTBLOCK
, &CMainFrame::OnUpdateEditUseleftblock
)
119 ON_COMMAND(ID_EDIT_USELEFTFILE
, &CMainFrame::OnEditUseleftfile
)
120 ON_UPDATE_COMMAND_UI(ID_EDIT_USELEFTFILE
, &CMainFrame::OnUpdateEditUseleftfile
)
121 ON_COMMAND(ID_EDIT_USEBLOCKFROMLEFTBEFORERIGHT
, &CMainFrame::OnEditUseblockfromleftbeforeright
)
122 ON_UPDATE_COMMAND_UI(ID_EDIT_USEBLOCKFROMLEFTBEFORERIGHT
, &CMainFrame::OnUpdateEditUseblockfromleftbeforeright
)
123 ON_COMMAND(ID_EDIT_USEBLOCKFROMRIGHTBEFORELEFT
, &CMainFrame::OnEditUseblockfromrightbeforeleft
)
124 ON_UPDATE_COMMAND_UI(ID_EDIT_USEBLOCKFROMRIGHTBEFORELEFT
, &CMainFrame::OnUpdateEditUseblockfromrightbeforeleft
)
125 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_NEXTDIFFERENCE
, &CMainFrame::OnUpdateNavigateNextdifference
)
126 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_PREVIOUSDIFFERENCE
, &CMainFrame::OnUpdateNavigatePreviousdifference
)
127 ON_COMMAND(ID_VIEW_COLLAPSED
, &CMainFrame::OnViewCollapsed
)
128 ON_UPDATE_COMMAND_UI(ID_VIEW_COLLAPSED
, &CMainFrame::OnUpdateViewCollapsed
)
129 ON_COMMAND(ID_VIEW_COMPAREWHITESPACES
, &CMainFrame::OnViewComparewhitespaces
)
130 ON_UPDATE_COMMAND_UI(ID_VIEW_COMPAREWHITESPACES
, &CMainFrame::OnUpdateViewComparewhitespaces
)
131 ON_COMMAND(ID_VIEW_IGNOREWHITESPACECHANGES
, &CMainFrame::OnViewIgnorewhitespacechanges
)
132 ON_UPDATE_COMMAND_UI(ID_VIEW_IGNOREWHITESPACECHANGES
, &CMainFrame::OnUpdateViewIgnorewhitespacechanges
)
133 ON_COMMAND(ID_VIEW_IGNOREALLWHITESPACECHANGES
, &CMainFrame::OnViewIgnoreallwhitespacechanges
)
134 ON_UPDATE_COMMAND_UI(ID_VIEW_IGNOREALLWHITESPACECHANGES
, &CMainFrame::OnUpdateViewIgnoreallwhitespacechanges
)
135 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_NEXTINLINEDIFF
, &CMainFrame::OnUpdateNavigateNextinlinediff
)
136 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_PREVINLINEDIFF
, &CMainFrame::OnUpdateNavigatePrevinlinediff
)
137 ON_COMMAND(ID_VIEW_WRAPLONGLINES
, &CMainFrame::OnViewWraplonglines
)
138 ON_UPDATE_COMMAND_UI(ID_VIEW_WRAPLONGLINES
, &CMainFrame::OnUpdateViewWraplonglines
)
139 ON_REGISTERED_MESSAGE( TaskBarButtonCreated
, CMainFrame::OnTaskbarButtonCreated
)
140 ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE
, &CMainFrame::OnUpdateEditPaste
)
141 ON_COMMAND(ID_INDICATOR_LEFTVIEW
, &CMainFrame::OnIndicatorLeftview
)
142 ON_COMMAND(ID_INDICATOR_RIGHTVIEW
, &CMainFrame::OnIndicatorRightview
)
143 ON_COMMAND(ID_INDICATOR_BOTTOMVIEW
, &CMainFrame::OnIndicatorBottomview
)
145 ON_COMMAND(ID_VIEW_IGNORECOMMENTS
, &CMainFrame::OnViewIgnorecomments
)
146 ON_UPDATE_COMMAND_UI(ID_VIEW_IGNORECOMMENTS
, &CMainFrame::OnUpdateViewIgnorecomments
)
147 ON_COMMAND_RANGE(ID_REGEXFILTER
, ID_REGEXFILTER
+400, &CMainFrame::OnRegexfilter
)
148 ON_UPDATE_COMMAND_UI_RANGE(ID_REGEXFILTER
, ID_REGEXFILTER
+400, &CMainFrame::OnUpdateViewRegexFilter
)
149 ON_COMMAND(ID_INDICATOR_LEFTVIEWCOMBOENCODING
, &CMainFrame::OnDummyEnabled
)
150 ON_COMMAND(ID_INDICATOR_RIGHTVIEWCOMBOENCODING
, &CMainFrame::OnDummyEnabled
)
151 ON_COMMAND(ID_INDICATOR_BOTTOMVIEWCOMBOENCODING
, &CMainFrame::OnDummyEnabled
)
152 ON_COMMAND(ID_INDICATOR_LEFTVIEWCOMBOEOL
, &CMainFrame::OnDummyEnabled
)
153 ON_COMMAND(ID_INDICATOR_RIGHTVIEWCOMBOEOL
, &CMainFrame::OnDummyEnabled
)
154 ON_COMMAND(ID_INDICATOR_BOTTOMVIEWCOMBOEOL
, &CMainFrame::OnDummyEnabled
)
155 ON_COMMAND(ID_INDICATOR_LEFTVIEWCOMBOTABMODE
, &CMainFrame::OnDummyEnabled
)
156 ON_COMMAND(ID_INDICATOR_RIGHTVIEWCOMBOTABMODE
, &CMainFrame::OnDummyEnabled
)
157 ON_COMMAND(ID_INDICATOR_BOTTOMVIEWCOMBOTABMODE
, &CMainFrame::OnDummyEnabled
)
158 ON_COMMAND_RANGE(ID_INDICATOR_LEFTENCODINGSTART
, ID_INDICATOR_LEFTENCODINGSTART
+19, &CMainFrame::OnEncodingLeft
)
159 ON_COMMAND_RANGE(ID_INDICATOR_RIGHTENCODINGSTART
, ID_INDICATOR_RIGHTENCODINGSTART
+19, &CMainFrame::OnEncodingRight
)
160 ON_COMMAND_RANGE(ID_INDICATOR_BOTTOMENCODINGSTART
, ID_INDICATOR_BOTTOMENCODINGSTART
+19, &CMainFrame::OnEncodingBottom
)
161 ON_COMMAND_RANGE(ID_INDICATOR_LEFTEOLSTART
, ID_INDICATOR_LEFTEOLSTART
+19, &CMainFrame::OnEOLLeft
)
162 ON_COMMAND_RANGE(ID_INDICATOR_RIGHTEOLSTART
, ID_INDICATOR_RIGHTEOLSTART
+19, &CMainFrame::OnEOLRight
)
163 ON_COMMAND_RANGE(ID_INDICATOR_BOTTOMEOLSTART
, ID_INDICATOR_BOTTOMEOLSTART
+19, &CMainFrame::OnEOLBottom
)
164 ON_COMMAND_RANGE(ID_INDICATOR_LEFTTABMODESTART
, ID_INDICATOR_LEFTTABMODESTART
+19, &CMainFrame::OnTabModeLeft
)
165 ON_COMMAND_RANGE(ID_INDICATOR_RIGHTTABMODESTART
, ID_INDICATOR_RIGHTTABMODESTART
+19, &CMainFrame::OnTabModeRight
)
166 ON_COMMAND_RANGE(ID_INDICATOR_BOTTOMTABMODESTART
, ID_INDICATOR_BOTTOMTABMODESTART
+19, &CMainFrame::OnTabModeBottom
)
167 ON_UPDATE_COMMAND_UI_RANGE(ID_INDICATOR_LEFTENCODINGSTART
, ID_INDICATOR_LEFTENCODINGSTART
+19, &CMainFrame::OnUpdateEncodingLeft
)
168 ON_UPDATE_COMMAND_UI_RANGE(ID_INDICATOR_RIGHTENCODINGSTART
, ID_INDICATOR_RIGHTENCODINGSTART
+19, &CMainFrame::OnUpdateEncodingRight
)
169 ON_UPDATE_COMMAND_UI_RANGE(ID_INDICATOR_BOTTOMENCODINGSTART
, ID_INDICATOR_BOTTOMENCODINGSTART
+19, &CMainFrame::OnUpdateEncodingBottom
)
170 ON_UPDATE_COMMAND_UI_RANGE(ID_INDICATOR_LEFTEOLSTART
, ID_INDICATOR_LEFTEOLSTART
+19, &CMainFrame::OnUpdateEOLLeft
)
171 ON_UPDATE_COMMAND_UI_RANGE(ID_INDICATOR_RIGHTEOLSTART
, ID_INDICATOR_RIGHTEOLSTART
+19, &CMainFrame::OnUpdateEOLRight
)
172 ON_UPDATE_COMMAND_UI_RANGE(ID_INDICATOR_BOTTOMEOLSTART
, ID_INDICATOR_BOTTOMEOLSTART
+19, &CMainFrame::OnUpdateEOLBottom
)
173 ON_UPDATE_COMMAND_UI_RANGE(ID_INDICATOR_LEFTTABMODESTART
, ID_INDICATOR_LEFTTABMODESTART
+19, &CMainFrame::OnUpdateTabModeLeft
)
174 ON_UPDATE_COMMAND_UI_RANGE(ID_INDICATOR_RIGHTTABMODESTART
, ID_INDICATOR_RIGHTTABMODESTART
+19, &CMainFrame::OnUpdateTabModeRight
)
175 ON_UPDATE_COMMAND_UI_RANGE(ID_INDICATOR_BOTTOMTABMODESTART
, ID_INDICATOR_BOTTOMTABMODESTART
+19, &CMainFrame::OnUpdateTabModeBottom
)
178 static UINT indicators
[] =
180 ID_SEPARATOR
, // status line indicator
181 ID_INDICATOR_LEFTVIEW
,
182 ID_INDICATOR_RIGHTVIEW
,
183 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_regIgnoreComments(_T("Software\\TortoiseGitMerge\\IgnoreComments"), FALSE
)
221 m_bOneWay
= (0 != ((DWORD
)m_regOneWay
));
222 theApp
.m_nAppLook
= theApp
.GetInt(_T("ApplicationLook"), ID_VIEW_APPLOOK_VS_2005
);
223 m_bCollapsed
= !!(DWORD
)m_regCollapsed
;
224 m_bViewMovedBlocks
= !!(DWORD
)m_regViewModedBlocks
;
225 m_bWrapLines
= !!(DWORD
)m_regWrapLines
;
226 m_bInlineDiff
= !!m_regInlineDiff
;
227 m_bUseRibbons
= !!m_regUseRibbons
;
228 CMFCVisualManagerWindows::m_b3DTabsXPTheme
= TRUE
;
231 CMainFrame::~CMainFrame()
235 LRESULT
CMainFrame::OnTaskbarButtonCreated(WPARAM
/*wParam*/, LPARAM
/*lParam*/)
237 SetUUIDOverlayIcon(m_hWnd
);
242 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct
)
244 if (CFrameWndEx::OnCreate(lpCreateStruct
) == -1)
247 OnApplicationLook(theApp
.m_nAppLook
);
251 m_wndRibbonBar
.Create(this);
252 m_wndRibbonBar
.LoadFromResource(IDR_RIBBON
);
254 // enable the dialog launch button on the view panel
255 CMFCRibbonCategory
* pMainCat
= m_wndRibbonBar
.GetCategory(1);
258 CMFCRibbonPanel
* pPanel
= pMainCat
->GetPanel(0);
260 pPanel
->EnableLaunchButton(ID_VIEW_OPTIONS
);
262 // now replace all buttons with our custom button class
263 for (int i
= 0; i
< m_wndRibbonBar
.GetCategoryCount(); ++i
)
265 CMFCRibbonCategory
* pCat
= m_wndRibbonBar
.GetCategory(i
);
266 for (int j
= 0; j
< pCat
->GetPanelCount(); ++j
)
268 CMFCRibbonPanel
* pPanel
= pCat
->GetPanel(j
);
269 CList
<UINT
, UINT
> lstItems
;
270 pPanel
->GetItemIDsList(lstItems
);
271 while (!lstItems
.IsEmpty())
273 UINT id
= lstItems
.GetHead();
274 lstItems
.RemoveHead();
275 CMFCRibbonButton
* pButton
= dynamic_cast<CMFCRibbonButton
*>(pPanel
->FindByID(id
));
278 CCustomMFCRibbonButton
* c
= new CCustomMFCRibbonButton(id
, pButton
->GetText());
279 pPanel
->ReplaceByID(id
, c
);
284 BuildRegexSubitems();
285 if (!m_wndRibbonStatusBar
.Create(this))
287 TRACE0("Failed to create ribbon status bar\n");
288 return -1; // fail to create
290 m_wndRibbonStatusBar
.AddElement(new CMFCRibbonStatusBarPane(ID_SEPARATOR
, CString(MAKEINTRESOURCE(AFX_IDS_IDLEMESSAGE
)), TRUE
), L
"");
292 CString
sTooltip(MAKEINTRESOURCE(IDS_ENCODING_COMBO_TOOLTIP
));
293 auto apBtnGroupLeft
= std::make_unique
<CMFCRibbonButtonsGroup
>();
294 apBtnGroupLeft
->SetID(ID_INDICATOR_LEFTVIEW
);
295 apBtnGroupLeft
->AddButton(new CMFCRibbonStatusBarPane(ID_SEPARATOR
, CString(MAKEINTRESOURCE(IDS_STATUSBAR_LEFTVIEW
)), TRUE
));
296 CMFCRibbonButton
* pButton
= new CMFCRibbonButton(ID_INDICATOR_LEFTVIEWCOMBOENCODING
, L
"");
297 pButton
->SetToolTipText(sTooltip
);
298 FillEncodingButton(pButton
, ID_INDICATOR_LEFTENCODINGSTART
);
299 apBtnGroupLeft
->AddButton(pButton
);
300 pButton
= new CMFCRibbonButton(ID_INDICATOR_LEFTVIEWCOMBOEOL
, L
"");
301 FillEOLButton(pButton
, ID_INDICATOR_LEFTEOLSTART
);
302 apBtnGroupLeft
->AddButton(pButton
);
303 pButton
= new CMFCRibbonButton(ID_INDICATOR_LEFTVIEWCOMBOTABMODE
, L
"");
304 FillTabModeButton(pButton
, ID_INDICATOR_LEFTTABMODESTART
);
305 apBtnGroupLeft
->AddButton(pButton
);
306 apBtnGroupLeft
->AddButton(new CMFCRibbonStatusBarPane(ID_INDICATOR_LEFTVIEW
, L
"", TRUE
));
307 m_wndRibbonStatusBar
.AddExtendedElement(apBtnGroupLeft
.release(), L
"");
309 auto apBtnGroupRight
= std::make_unique
<CMFCRibbonButtonsGroup
>();
310 apBtnGroupRight
->SetID(ID_INDICATOR_RIGHTVIEW
);
311 apBtnGroupRight
->AddButton(new CMFCRibbonStatusBarPane(ID_SEPARATOR
, CString(MAKEINTRESOURCE(IDS_STATUSBAR_RIGHTVIEW
)), TRUE
));
312 pButton
= new CMFCRibbonButton(ID_INDICATOR_RIGHTVIEWCOMBOENCODING
, L
"");
313 pButton
->SetToolTipText(sTooltip
);
314 FillEncodingButton(pButton
, ID_INDICATOR_RIGHTENCODINGSTART
);
315 apBtnGroupRight
->AddButton(pButton
);
316 pButton
= new CMFCRibbonButton(ID_INDICATOR_RIGHTVIEWCOMBOEOL
, L
"");
317 FillEOLButton(pButton
, ID_INDICATOR_RIGHTEOLSTART
);
318 apBtnGroupRight
->AddButton(pButton
);
319 pButton
= new CMFCRibbonButton(ID_INDICATOR_RIGHTVIEWCOMBOTABMODE
, L
"");
320 FillTabModeButton(pButton
, ID_INDICATOR_RIGHTTABMODESTART
);
321 apBtnGroupRight
->AddButton(pButton
);
322 apBtnGroupRight
->AddButton(new CMFCRibbonStatusBarPane(ID_INDICATOR_RIGHTVIEW
, L
"", TRUE
));
323 m_wndRibbonStatusBar
.AddExtendedElement(apBtnGroupRight
.release(), L
"");
327 if (!m_wndMenuBar
.Create(this))
329 TRACE0("Failed to create menubar\n");
330 return -1; // fail to create
332 m_wndMenuBar
.SetPaneStyle(m_wndMenuBar
.GetPaneStyle() | CBRS_SIZE_DYNAMIC
| CBRS_TOOLTIPS
| CBRS_FLYBY
);
334 // prevent the menu bar from taking the focus on activation
335 CMFCPopupMenu::SetForceMenuFocus(FALSE
);
336 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
))
338 TRACE0("Failed to create toolbar\n");
339 return -1; // fail to create
341 m_wndToolBar
.SetWindowText(_T("Main"));
342 if (!m_wndStatusBar
.Create(this) ||
343 !m_wndStatusBar
.SetIndicators(indicators
,
344 _countof(indicators
)))
346 TRACE0("Failed to create status bar\n");
347 return -1; // fail to create
349 m_wndStatusBar
.EnablePaneDoubleClick();
352 if (!m_wndLocatorBar
.Create(this, IDD_DIFFLOCATOR
,
353 CBRS_ALIGN_LEFT
| CBRS_SIZE_FIXED
, ID_VIEW_LOCATORBAR
))
355 TRACE0("Failed to create dialogbar\n");
356 return -1; // fail to create
358 if (!m_wndLineDiffBar
.Create(this, IDD_LINEDIFF
,
359 CBRS_ALIGN_BOTTOM
| CBRS_SIZE_FIXED
, ID_VIEW_LINEDIFFBAR
))
361 TRACE0("Failed to create dialogbar\n");
362 return -1; // fail to create
364 m_wndLocatorBar
.m_pMainFrm
= this;
365 m_wndLineDiffBar
.m_pMainFrm
= this;
367 EnableDocking(CBRS_ALIGN_ANY
);
370 m_wndMenuBar
.EnableDocking(CBRS_ALIGN_TOP
);
371 m_wndToolBar
.EnableDocking(CBRS_ALIGN_TOP
);
372 DockPane(&m_wndMenuBar
);
373 DockPane(&m_wndToolBar
);
375 DockPane(&m_wndLocatorBar
);
376 DockPane(&m_wndLineDiffBar
);
377 ShowPane(&m_wndLocatorBar
, true, false, true);
378 ShowPane(&m_wndLineDiffBar
, true, false, true);
380 m_wndLocatorBar
.EnableGripper(FALSE
);
381 m_wndLineDiffBar
.EnableGripper(FALSE
);
386 BOOL
CMainFrame::PreCreateWindow(CREATESTRUCT
& cs
)
388 if( !CFrameWndEx::PreCreateWindow(cs
) )
393 void CMainFrame::OnApplicationLook(UINT id
)
397 theApp
.m_nAppLook
= id
;
399 switch (theApp
.m_nAppLook
)
401 case ID_VIEW_APPLOOK_WIN_2000
:
402 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManager
));
403 m_wndRibbonBar
.SetWindows7Look(FALSE
);
406 case ID_VIEW_APPLOOK_OFF_XP
:
407 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOfficeXP
));
408 m_wndRibbonBar
.SetWindows7Look(FALSE
);
411 case ID_VIEW_APPLOOK_WIN_XP
:
412 CMFCVisualManagerWindows::m_b3DTabsXPTheme
= TRUE
;
413 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows
));
414 m_wndRibbonBar
.SetWindows7Look(FALSE
);
417 case ID_VIEW_APPLOOK_OFF_2003
:
418 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2003
));
419 CDockingManager::SetDockingMode(DT_SMART
);
420 m_wndRibbonBar
.SetWindows7Look(FALSE
);
423 case ID_VIEW_APPLOOK_VS_2005
:
424 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerVS2005
));
425 CDockingManager::SetDockingMode(DT_SMART
);
426 m_wndRibbonBar
.SetWindows7Look(FALSE
);
429 case ID_VIEW_APPLOOK_VS_2008
:
430 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerVS2008
));
431 CDockingManager::SetDockingMode(DT_SMART
);
432 m_wndRibbonBar
.SetWindows7Look(FALSE
);
435 case ID_VIEW_APPLOOK_WIN7
:
436 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows7
));
437 CDockingManager::SetDockingMode(DT_SMART
);
438 m_wndRibbonBar
.SetWindows7Look(TRUE
);
442 switch (theApp
.m_nAppLook
)
444 case ID_VIEW_APPLOOK_OFF_2007_BLUE
:
445 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_LunaBlue
);
448 case ID_VIEW_APPLOOK_OFF_2007_BLACK
:
449 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_ObsidianBlack
);
452 case ID_VIEW_APPLOOK_OFF_2007_SILVER
:
453 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_Silver
);
456 case ID_VIEW_APPLOOK_OFF_2007_AQUA
:
457 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_Aqua
);
461 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2007
));
462 CDockingManager::SetDockingMode(DT_SMART
);
463 m_wndRibbonBar
.SetWindows7Look(FALSE
);
466 RedrawWindow(NULL
, NULL
, RDW_ALLCHILDREN
| RDW_INVALIDATE
| RDW_UPDATENOW
| RDW_FRAME
| RDW_ERASE
);
468 theApp
.WriteInt(_T("ApplicationLook"), theApp
.m_nAppLook
);
471 void CMainFrame::OnUpdateApplicationLook(CCmdUI
* pCmdUI
)
474 pCmdUI
->SetRadio(theApp
.m_nAppLook
== pCmdUI
->m_nID
);
478 // CMainFrame diagnostics
481 void CMainFrame::AssertValid() const
483 CFrameWndEx::AssertValid();
486 void CMainFrame::Dump(CDumpContext
& dc
) const
488 CFrameWndEx::Dump(dc
);
494 // CMainFrame message handlers
497 BOOL
CMainFrame::OnCreateClient(LPCREATESTRUCT
/*lpcs*/, CCreateContext
* pContext
)
503 // split into three panes:
512 // create a splitter with 2 rows, 1 column
513 if (!m_wndSplitter
.CreateStatic(this, 2, 1))
515 TRACE0("Failed to CreateStaticSplitter\n");
519 // add the second splitter pane - which is a nested splitter with 2 columns
520 if (!m_wndSplitter2
.CreateStatic(
521 &m_wndSplitter
, // our parent window is the first splitter
522 1, 2, // the new splitter is 1 row, 2 columns
523 WS_CHILD
| WS_VISIBLE
| WS_BORDER
, // style, WS_BORDER is needed
524 m_wndSplitter
.IdFromRowCol(0, 0)
525 // new splitter is in the first row, 1st column of first splitter
528 TRACE0("Failed to create nested splitter\n");
531 // add the first splitter pane - the default view in row 0
532 if (!m_wndSplitter
.CreateView(1, 0,
533 RUNTIME_CLASS(CBottomView
), CSize(cr
.Width(), cr
.Height()), pContext
))
535 TRACE0("Failed to create first pane\n");
538 m_pwndBottomView
= static_cast<CBottomView
*>(m_wndSplitter
.GetPane(1, 0));
539 m_pwndBottomView
->m_pwndLocator
= &m_wndLocatorBar
;
540 m_pwndBottomView
->m_pwndLineDiffBar
= &m_wndLineDiffBar
;
542 m_pwndBottomView
->m_pwndRibbonStatusBar
= &m_wndRibbonStatusBar
;
544 m_pwndBottomView
->m_pwndStatusBar
= &m_wndStatusBar
;
545 m_pwndBottomView
->m_pMainFrame
= this;
547 // now create the two views inside the nested splitter
549 if (!m_wndSplitter2
.CreateView(0, 0,
550 RUNTIME_CLASS(CLeftView
), CSize(cr
.Width()/2, cr
.Height()/2), pContext
))
552 TRACE0("Failed to create second pane\n");
555 m_pwndLeftView
= static_cast<CLeftView
*>(m_wndSplitter2
.GetPane(0, 0));
556 m_pwndLeftView
->m_pwndLocator
= &m_wndLocatorBar
;
557 m_pwndLeftView
->m_pwndLineDiffBar
= &m_wndLineDiffBar
;
559 m_pwndLeftView
->m_pwndRibbonStatusBar
= &m_wndRibbonStatusBar
;
561 m_pwndLeftView
->m_pwndStatusBar
= &m_wndStatusBar
;
562 m_pwndLeftView
->m_pMainFrame
= this;
564 if (!m_wndSplitter2
.CreateView(0, 1,
565 RUNTIME_CLASS(CRightView
), CSize(cr
.Width()/2, cr
.Height()/2), pContext
))
567 TRACE0("Failed to create third pane\n");
570 m_pwndRightView
= static_cast<CRightView
*>(m_wndSplitter2
.GetPane(0, 1));
571 m_pwndRightView
->m_pwndLocator
= &m_wndLocatorBar
;
572 m_pwndRightView
->m_pwndLineDiffBar
= &m_wndLineDiffBar
;
574 m_pwndRightView
->m_pwndRibbonStatusBar
= &m_wndRibbonStatusBar
;
576 m_pwndRightView
->m_pwndStatusBar
= &m_wndStatusBar
;
577 m_pwndRightView
->m_pMainFrame
= this;
578 m_bInitSplitter
= TRUE
;
580 m_dlgFilePatches
.Create(IDD_FILEPATCHES
, this);
586 BOOL
CMainFrame::PatchFile(CString sFilePath
, bool /*bContentMods*/, bool bPropMods
, CString sVersion
, BOOL bAutoPatch
)
589 //"dry run" was successful, so save the patched file somewhere...
590 CString sTempFile
= CTempFiles::Instance().GetTempFilePathString();
591 CString sRejectedFile
, sBasePath
;
592 if (m_Patch
.GetPatchResult(sFilePath
, sTempFile
, sRejectedFile
, sBasePath
) < 0)
594 MessageBox(m_Patch
.GetErrorMessage(), NULL
, MB_ICONERROR
);
597 sFilePath
= m_Patch
.GetTargetPath() + _T("\\") + sFilePath
;
598 sFilePath
.Replace('/', '\\');
599 if (sBasePath
.IsEmpty())
600 sBasePath
= sFilePath
;
601 if (m_bReversedPatch
)
603 m_Data
.m_baseFile
.SetFileName(sTempFile
);
605 temp
.Format(_T("%s %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sFilePath
), (LPCTSTR
)m_Data
.m_sPatchPatched
);
606 m_Data
.m_baseFile
.SetDescriptiveName(temp
);
607 m_Data
.m_yourFile
.SetFileName(sFilePath
);
608 temp
.Format(_T("%s %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sFilePath
), (LPCTSTR
)m_Data
.m_sPatchOriginal
);
609 m_Data
.m_yourFile
.SetDescriptiveName(temp
);
610 m_Data
.m_theirFile
.SetOutOfUse();
611 m_Data
.m_mergedFile
.SetOutOfUse();
615 if ((!PathFileExists(sBasePath
))||(PathIsDirectory(sBasePath
)))
617 m_Data
.m_baseFile
.SetFileName(CTempFiles::Instance().GetTempFilePathString());
618 m_Data
.m_baseFile
.CreateEmptyFile();
622 m_Data
.m_baseFile
.SetFileName(sBasePath
);
624 CString sDescription
;
625 sDescription
.Format(_T("%s %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sBasePath
), (LPCTSTR
)m_Data
.m_sPatchOriginal
);
626 m_Data
.m_baseFile
.SetDescriptiveName(sDescription
);
627 if (sBasePath
== sFilePath
)
629 m_Data
.m_yourFile
.SetFileName(sTempFile
);
631 temp
.Format(_T("%s %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sBasePath
), (LPCTSTR
)m_Data
.m_sPatchPatched
);
632 m_Data
.m_yourFile
.SetDescriptiveName(temp
);
633 m_Data
.m_theirFile
.SetOutOfUse();
637 if (!PathFileExists(sFilePath
) || PathIsDirectory(sFilePath
))
639 m_Data
.m_yourFile
.SetFileName(CTempFiles::Instance().GetTempFilePathString());
640 m_Data
.m_yourFile
.CreateEmptyFile();
642 temp
.Format(_T("%s %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sFilePath
), (LPCTSTR
)CString(MAKEINTRESOURCE(IDS_NOTFOUNDVIEWTITLEINDICATOR
)));
643 m_Data
.m_yourFile
.SetDescriptiveName(temp
);
646 m_Data
.m_yourFile
.SetFileName(sFilePath
);
647 m_Data
.m_theirFile
.SetFileName(sTempFile
);
649 temp
.Format(_T("%s %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sFilePath
), (LPCTSTR
)m_Data
.m_sPatchPatched
);
650 m_Data
.m_theirFile
.SetDescriptiveName(temp
);
652 m_Data
.m_mergedFile
.SetFileName(sFilePath
);
653 m_Data
.m_bPatchRequired
= bPropMods
;
655 TRACE(_T("comparing %s\nwith the patched result %s\n"), (LPCTSTR
)sFilePath
, (LPCTSTR
)sTempFile
);
658 if (!sRejectedFile
.IsEmpty())
661 // start TortoiseUDiff with the rejected hunks
663 sTitle
.Format(IDS_TITLE_REJECTEDHUNKS
, (LPCTSTR
)CPathUtils::GetFileNameFromPath(sFilePath
));
664 CAppUtils::StartUnifiedDiffViewer(sRejectedFile
, sTitle
);
669 if (sBasePath
!= sFilePath
&& HasConflictsWontKeep())
678 BOOL
CMainFrame::DiffFiles(CString sURL1
, CString sRev1
, CString sURL2
, CString sRev2
)
680 CString tempfile1
= CTempFiles::Instance().GetTempFilePathString();
681 CString tempfile2
= CTempFiles::Instance().GetTempFilePathString();
683 ASSERT(tempfile1
.Compare(tempfile2
));
686 CSysProgressDlg progDlg
;
687 sTemp
.Format(IDS_GETVERSIONOFFILE
, (LPCTSTR
)sRev1
);
688 progDlg
.SetLine(1, sTemp
, true);
689 progDlg
.SetLine(2, sURL1
, true);
690 sTemp
.LoadString(IDS_GETVERSIONOFFILETITLE
);
691 progDlg
.SetTitle(sTemp
);
692 progDlg
.SetShowProgressBar(true);
693 progDlg
.SetAnimation(IDR_DOWNLOAD
);
694 progDlg
.SetTime(FALSE
);
695 progDlg
.SetProgress(1,100);
696 progDlg
.ShowModeless(this);
697 if (!CAppUtils::GetVersionedFile(sURL1
, sRev1
, tempfile1
, &progDlg
, m_hWnd
))
701 sErrMsg
.Format(IDS_ERR_MAINFRAME_FILEVERSIONNOTFOUND
, (LPCTSTR
)sRev1
, (LPCTSTR
)sURL1
);
702 MessageBox(sErrMsg
, NULL
, MB_ICONERROR
);
705 sTemp
.Format(IDS_GETVERSIONOFFILE
, (LPCTSTR
)sRev2
);
706 progDlg
.SetLine(1, sTemp
, true);
707 progDlg
.SetLine(2, sURL2
, true);
708 progDlg
.SetProgress(50, 100);
709 if (!CAppUtils::GetVersionedFile(sURL2
, sRev2
, tempfile2
, &progDlg
, m_hWnd
))
713 sErrMsg
.Format(IDS_ERR_MAINFRAME_FILEVERSIONNOTFOUND
, (LPCTSTR
)sRev2
, (LPCTSTR
)sURL2
);
714 MessageBox(sErrMsg
, NULL
, MB_ICONERROR
);
717 progDlg
.SetProgress(100,100);
720 temp
.Format(_T("%s Revision %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sURL1
), (LPCTSTR
)sRev1
);
721 m_Data
.m_baseFile
.SetFileName(tempfile1
);
722 m_Data
.m_baseFile
.SetDescriptiveName(temp
);
723 temp
.Format(_T("%s Revision %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sURL2
), (LPCTSTR
)sRev2
);
724 m_Data
.m_yourFile
.SetFileName(tempfile2
);
725 m_Data
.m_yourFile
.SetDescriptiveName(temp
);
732 void CMainFrame::OnFileOpen()
734 if (CheckForSave(CHFSR_OPEN
)==IDCANCEL
)
736 return OnFileOpen(false);
739 void CMainFrame::OnFileOpen(bool fillyours
)
743 dlg
.m_sBaseFile
= m_Data
.m_yourFile
.GetFilename();
744 if (dlg
.DoModal() != IDOK
)
748 m_dlgFilePatches
.ShowWindow(SW_HIDE
);
749 m_dlgFilePatches
.Init(NULL
, NULL
, CString(), NULL
);
750 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
,
751 (LPCTSTR
)dlg
.m_sUnifiedDiffFile
, (LPCTSTR
)dlg
.m_sPatchDirectory
);
752 m_Data
.m_baseFile
.SetFileName(dlg
.m_sBaseFile
);
753 m_Data
.m_theirFile
.SetFileName(dlg
.m_sTheirFile
);
754 m_Data
.m_yourFile
.SetFileName(dlg
.m_sYourFile
);
755 m_Data
.m_sDiffFile
= dlg
.m_sUnifiedDiffFile
;
756 m_Data
.m_sPatchPath
= dlg
.m_sPatchDirectory
;
757 m_Data
.m_mergedFile
.SetOutOfUse();
758 CCrashReport::Instance().AddFile2(dlg
.m_sBaseFile
, NULL
, _T("Basefile"), CR_AF_MAKE_FILE_COPY
);
759 CCrashReport::Instance().AddFile2(dlg
.m_sTheirFile
, NULL
, _T("Theirfile"), CR_AF_MAKE_FILE_COPY
);
760 CCrashReport::Instance().AddFile2(dlg
.m_sYourFile
, NULL
, _T("Yourfile"), CR_AF_MAKE_FILE_COPY
);
761 CCrashReport::Instance().AddFile2(dlg
.m_sUnifiedDiffFile
, NULL
, _T("Difffile"), CR_AF_MAKE_FILE_COPY
);
763 if (!m_Data
.IsBaseFileInUse() && m_Data
.IsTheirFileInUse() && m_Data
.IsYourFileInUse())
765 // a diff between two files means "Yours" against "Base", not "Theirs" against "Yours"
766 m_Data
.m_baseFile
.TransferDetailsFrom(m_Data
.m_theirFile
);
768 if (m_Data
.IsBaseFileInUse() && m_Data
.IsTheirFileInUse() && !m_Data
.IsYourFileInUse())
770 // a diff between two files means "Yours" against "Base", not "Theirs" against "Base"
771 m_Data
.m_yourFile
.TransferDetailsFrom(m_Data
.m_theirFile
);
773 m_bSaveRequired
= false;
778 void CMainFrame::ClearViewNamesAndPaths()
780 m_pwndLeftView
->m_sWindowName
.Empty();
781 m_pwndLeftView
->m_sFullFilePath
.Empty();
782 m_pwndLeftView
->m_sReflectedName
.Empty();
783 m_pwndRightView
->m_sWindowName
.Empty();
784 m_pwndRightView
->m_sFullFilePath
.Empty();
785 m_pwndRightView
->m_sReflectedName
.Empty();
786 m_pwndBottomView
->m_sWindowName
.Empty();
787 m_pwndBottomView
->m_sFullFilePath
.Empty();
788 m_pwndBottomView
->m_sReflectedName
.Empty();
791 bool CMainFrame::LoadViews(int line
)
793 LoadIgnoreCommentData();
794 m_Data
.SetBlame(m_bBlame
);
795 m_Data
.SetMovedBlocks(m_bViewMovedBlocks
);
796 m_bHasConflicts
= false;
797 CBaseView
* pwndActiveView
= m_pwndLeftView
;
798 int nOldLine
= m_pwndRightView
? m_pwndRightView
->m_nTopLine
: -1;
800 m_pwndRightView
&& m_pwndRightView
->m_pViewData
?
801 m_pwndRightView
->m_pViewData
->GetLineNumber(m_pwndRightView
->m_nTopLine
) : -1;
802 POINT ptOldCaretPos
= {-1, -1};
803 if (m_pwndRightView
&& m_pwndRightView
->IsTarget())
804 ptOldCaretPos
= m_pwndRightView
->GetCaretPosition();
805 if (m_pwndBottomView
&& m_pwndBottomView
->IsTarget())
806 ptOldCaretPos
= m_pwndBottomView
->GetCaretPosition();
807 CString sExt
= CPathUtils::GetFileExtFromPath(m_Data
.m_baseFile
.GetFilename()).MakeLower();
809 auto sC
= m_IgnoreCommentsMap
.find(sExt
);
810 if (sC
== m_IgnoreCommentsMap
.end())
812 sExt
= CPathUtils::GetFileExtFromPath(m_Data
.m_yourFile
.GetFilename()).MakeLower();
813 sC
= m_IgnoreCommentsMap
.find(sExt
);
814 if (sC
== m_IgnoreCommentsMap
.end())
816 sExt
= CPathUtils::GetFileExtFromPath(m_Data
.m_theirFile
.GetFilename()).MakeLower();
817 sC
= m_IgnoreCommentsMap
.find(sExt
);
820 if (sC
!= m_IgnoreCommentsMap
.end())
821 m_Data
.SetCommentTokens(std::get
<0>(sC
->second
), std::get
<1>(sC
->second
), std::get
<2>(sC
->second
));
823 m_Data
.SetCommentTokens(L
"", L
"", L
"");
826 m_pwndLeftView
->BuildAllScreen2ViewVector();
827 m_pwndLeftView
->DocumentUpdated();
828 m_pwndRightView
->DocumentUpdated();
829 m_pwndBottomView
->DocumentUpdated();
830 m_wndLocatorBar
.DocumentUpdated();
831 m_wndLineDiffBar
.DocumentUpdated();
832 ::MessageBox(m_hWnd
, m_Data
.GetError(), _T("TortoiseGitMerge"), MB_ICONERROR
);
833 m_Data
.m_mergedFile
.SetOutOfUse();
834 m_bSaveRequired
= false;
838 m_pwndLeftView
->BuildAllScreen2ViewVector();
839 m_pwndLeftView
->DocumentUpdated();
840 m_pwndRightView
->DocumentUpdated();
841 m_pwndBottomView
->DocumentUpdated();
842 m_wndLocatorBar
.DocumentUpdated();
843 m_wndLineDiffBar
.DocumentUpdated();
845 m_pwndLeftView
->SetWritable(false);
846 m_pwndLeftView
->SetWritableIsChangable(false);
847 m_pwndLeftView
->SetTarget(false);
848 m_pwndRightView
->SetWritable(false);
849 m_pwndRightView
->SetWritableIsChangable(false);
850 m_pwndRightView
->SetTarget(false);
851 m_pwndBottomView
->SetWritable(false);
852 m_pwndBottomView
->SetWritableIsChangable(false);
853 m_pwndBottomView
->SetTarget(false);
855 if (!m_Data
.IsBaseFileInUse())
857 CSysProgressDlg progDlg
;
858 if (m_Data
.IsYourFileInUse() && m_Data
.IsTheirFileInUse())
860 m_Data
.m_baseFile
.TransferDetailsFrom(m_Data
.m_theirFile
);
862 else if ((!m_Data
.m_sDiffFile
.IsEmpty())&&(!m_Patch
.Init(m_Data
.m_sDiffFile
, m_Data
.m_sPatchPath
, &progDlg
)))
865 ClearViewNamesAndPaths();
866 MessageBox(m_Patch
.GetErrorMessage(), NULL
, MB_ICONERROR
);
867 m_bSaveRequired
= false;
871 if (m_Patch
.GetNumberOfFiles() > 0)
873 CString betterpatchpath
= m_Patch
.CheckPatchPath(m_Data
.m_sPatchPath
);
874 if (betterpatchpath
.CompareNoCase(m_Data
.m_sPatchPath
)!=0)
877 msg
.Format(IDS_WARNBETTERPATCHPATHFOUND
, (LPCTSTR
)m_Data
.m_sPatchPath
, (LPCTSTR
)betterpatchpath
);
878 CTaskDialog
taskdlg(msg
,
879 CString(MAKEINTRESOURCE(IDS_WARNBETTERPATCHPATHFOUND_TASK2
)),
882 TDF_ENABLE_HYPERLINKS
| TDF_USE_COMMAND_LINKS
| TDF_ALLOW_DIALOG_CANCELLATION
| TDF_POSITION_RELATIVE_TO_WINDOW
);
884 WCHAR t3
[MAX_PATH
] = { 0 };
885 CString cp
= betterpatchpath
.Left(MAX_PATH
- 1);
886 PathCompactPathEx(t3
, cp
, 50, 0);
887 task3
.Format(IDS_WARNBETTERPATCHPATHFOUND_TASK3
, t3
);
888 taskdlg
.AddCommandControl(1, task3
);
890 WCHAR t4
[MAX_PATH
] = { 0 };
891 cp
= m_Data
.m_sPatchPath
.Left(MAX_PATH
- 1);
892 PathCompactPathEx(t4
, cp
, 50, 0);
893 task4
.Format(IDS_WARNBETTERPATCHPATHFOUND_TASK4
, t4
);
894 taskdlg
.AddCommandControl(2, task4
);
895 taskdlg
.SetDefaultCommandControl(1);
896 taskdlg
.SetMainIcon(TD_INFORMATION_ICON
);
897 taskdlg
.SetCommonButtons(TDCBF_CANCEL_BUTTON
);
898 if (taskdlg
.DoModal(m_hWnd
) == 1)
900 m_Data
.m_sPatchPath
= betterpatchpath
;
901 m_Patch
.Init(m_Data
.m_sDiffFile
, m_Data
.m_sPatchPath
, &progDlg
);
904 m_dlgFilePatches
.Init(&m_Patch
, this, m_Data
.m_sPatchPath
, this);
905 m_dlgFilePatches
.ShowWindow(SW_SHOW
);
906 ClearViewNamesAndPaths();
907 if (!m_wndSplitter
.IsRowHidden(1))
908 m_wndSplitter
.HideRow(1);
909 m_pwndLeftView
->SetHidden(FALSE
);
910 m_pwndRightView
->SetHidden(FALSE
);
911 m_pwndBottomView
->SetHidden(TRUE
);
914 if (m_Data
.IsBaseFileInUse() && !m_Data
.IsYourFileInUse() && m_Data
.IsTheirFileInUse())
916 m_Data
.m_yourFile
.TransferDetailsFrom(m_Data
.m_theirFile
);
918 if (m_Data
.IsBaseFileInUse() && m_Data
.IsYourFileInUse() && !m_Data
.IsTheirFileInUse())
920 //diff between YOUR and BASE
923 pwndActiveView
= m_pwndLeftView
;
924 if (!m_wndSplitter2
.IsColumnHidden(1))
925 m_wndSplitter2
.HideColumn(1);
927 m_pwndLeftView
->m_pViewData
= &m_Data
.m_YourBaseBoth
;
928 m_pwndLeftView
->SetTextType(m_Data
.m_arYourFile
.GetUnicodeType());
929 m_pwndLeftView
->SetLineEndingStyle(m_Data
.m_arYourFile
.GetLineEndings());
930 m_pwndLeftView
->m_sWindowName
= m_Data
.m_baseFile
.GetWindowName() + _T(" - ") + m_Data
.m_yourFile
.GetWindowName();
931 m_pwndLeftView
->m_sFullFilePath
= m_Data
.m_baseFile
.GetFilename() + _T(" - ") + m_Data
.m_yourFile
.GetFilename();
932 m_pwndLeftView
->m_sReflectedName
= m_Data
.m_yourFile
.GetReflectedName();
933 m_pwndLeftView
->m_pWorkingFile
= &m_Data
.m_yourFile
;
934 m_pwndLeftView
->SetTarget();
935 m_pwndLeftView
->SetWritableIsChangable(true);
937 m_pwndRightView
->m_pViewData
= NULL
;
938 m_pwndRightView
->m_pWorkingFile
= NULL
;
939 m_pwndBottomView
->m_pViewData
= NULL
;
940 m_pwndBottomView
->m_pWorkingFile
= NULL
;
942 if (!m_wndSplitter
.IsRowHidden(1))
943 m_wndSplitter
.HideRow(1);
944 m_pwndLeftView
->SetHidden(FALSE
);
945 m_pwndRightView
->SetHidden(TRUE
);
946 m_pwndBottomView
->SetHidden(TRUE
);
947 ::SetWindowPos(m_pwndLeftView
->m_hWnd
, NULL
, 0, 0, 0, 0, SWP_FRAMECHANGED
| SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOSIZE
);
951 pwndActiveView
= m_pwndRightView
;
952 if (m_wndSplitter2
.IsColumnHidden(1))
953 m_wndSplitter2
.ShowColumn();
955 m_pwndLeftView
->m_pViewData
= &m_Data
.m_YourBaseLeft
;
956 m_pwndLeftView
->SetTextType(m_Data
.m_arBaseFile
.GetUnicodeType());
957 m_pwndLeftView
->SetLineEndingStyle(m_Data
.m_arBaseFile
.GetLineEndings());
958 m_pwndLeftView
->m_sWindowName
= m_Data
.m_baseFile
.GetWindowName();
959 m_pwndLeftView
->m_sFullFilePath
= m_Data
.m_baseFile
.GetFilename();
960 m_pwndLeftView
->m_sConvertedFilePath
= m_Data
.m_baseFile
.GetConvertedFileName();
961 m_pwndLeftView
->m_sReflectedName
= m_Data
.m_baseFile
.GetReflectedName();
962 m_pwndLeftView
->m_pWorkingFile
= &m_Data
.m_baseFile
;
963 m_pwndLeftView
->SetWritableIsChangable(true);
965 m_pwndRightView
->m_pViewData
= &m_Data
.m_YourBaseRight
;
966 m_pwndRightView
->SetTextType(m_Data
.m_arYourFile
.GetUnicodeType());
967 m_pwndRightView
->SetLineEndingStyle(m_Data
.m_arYourFile
.GetLineEndings());
968 m_pwndRightView
->m_sWindowName
= m_Data
.m_yourFile
.GetWindowName();
969 m_pwndRightView
->m_sFullFilePath
= m_Data
.m_yourFile
.GetFilename();
970 m_pwndRightView
->m_sConvertedFilePath
= m_Data
.m_yourFile
.GetConvertedFileName();
971 m_pwndRightView
->m_sReflectedName
= m_Data
.m_yourFile
.GetReflectedName();
972 m_pwndRightView
->m_pWorkingFile
= &m_Data
.m_yourFile
;
973 m_pwndRightView
->SetWritable();
974 m_pwndRightView
->SetTarget();
976 m_pwndBottomView
->m_pViewData
= NULL
;
977 m_pwndBottomView
->m_pWorkingFile
= NULL
;
979 if (!m_wndSplitter
.IsRowHidden(1))
980 m_wndSplitter
.HideRow(1);
981 m_pwndLeftView
->SetHidden(FALSE
);
982 m_pwndRightView
->SetHidden(FALSE
);
983 m_pwndBottomView
->SetHidden(TRUE
);
985 bool hasMods
, hasConflicts
, hasWhitespaceMods
;
986 pwndActiveView
->CheckModifications(hasMods
, hasConflicts
, hasWhitespaceMods
);
987 if (!hasMods
&& !hasConflicts
)
989 // files appear identical, show a dialog informing the user that there are or might
990 // be other differences
991 bool hasEncodingDiff
= m_Data
.m_arBaseFile
.GetUnicodeType() != m_Data
.m_arYourFile
.GetUnicodeType();
992 bool hasEOLDiff
= m_Data
.m_arBaseFile
.GetLineEndings() != m_Data
.m_arYourFile
.GetLineEndings();
993 if (hasWhitespaceMods
|| hasEncodingDiff
|| hasEOLDiff
)
995 // text is identical, but the files do not match
996 CString
sWarning(MAKEINTRESOURCE(IDS_TEXTIDENTICAL_MAIN
));
997 CString
sWhitespace(MAKEINTRESOURCE(IDS_TEXTIDENTICAL_WHITESPACE
));
998 CString
sEncoding(MAKEINTRESOURCE(IDS_TEXTIDENTICAL_ENCODING
));
999 CString
sEOL(MAKEINTRESOURCE(IDS_TEXTIDENTICAL_EOL
));
1000 if (hasWhitespaceMods
)
1002 sWarning
+= L
"\r\n";
1003 sWarning
+= sWhitespace
;
1005 if (hasEncodingDiff
)
1007 sWarning
+= L
"\r\n";
1008 sWarning
+= sEncoding
;
1010 sWarning
+= m_Data
.m_arBaseFile
.GetEncodingName(m_Data
.m_arBaseFile
.GetUnicodeType());
1012 sWarning
+= m_Data
.m_arYourFile
.GetEncodingName(m_Data
.m_arYourFile
.GetUnicodeType());
1017 sWarning
+= L
"\r\n";
1020 AfxMessageBox(sWarning
, MB_ICONINFORMATION
);
1024 else if (m_Data
.IsBaseFileInUse() && m_Data
.IsYourFileInUse() && m_Data
.IsTheirFileInUse())
1026 //diff between THEIR, YOUR and BASE
1027 m_pwndBottomView
->SetWritable();
1028 m_pwndBottomView
->SetTarget();
1029 pwndActiveView
= m_pwndBottomView
;
1031 m_pwndLeftView
->m_pViewData
= &m_Data
.m_TheirBaseBoth
;
1032 m_pwndLeftView
->SetTextType(m_Data
.m_arTheirFile
.GetUnicodeType());
1033 m_pwndLeftView
->SetLineEndingStyle(m_Data
.m_arTheirFile
.GetLineEndings());
1034 m_pwndLeftView
->m_sWindowName
.LoadString(IDS_VIEWTITLE_THEIRS
);
1035 m_pwndLeftView
->m_sWindowName
+= _T(" - ") + m_Data
.m_theirFile
.GetWindowName();
1036 m_pwndLeftView
->m_sFullFilePath
= m_Data
.m_theirFile
.GetFilename();
1037 m_pwndLeftView
->m_sConvertedFilePath
= m_Data
.m_theirFile
.GetConvertedFileName();
1038 m_pwndLeftView
->m_sReflectedName
= m_Data
.m_theirFile
.GetReflectedName();
1039 m_pwndLeftView
->m_pWorkingFile
= &m_Data
.m_theirFile
;
1041 m_pwndRightView
->m_pViewData
= &m_Data
.m_YourBaseBoth
;
1042 m_pwndRightView
->SetTextType(m_Data
.m_arYourFile
.GetUnicodeType());
1043 m_pwndRightView
->SetLineEndingStyle(m_Data
.m_arYourFile
.GetLineEndings());
1044 m_pwndRightView
->m_sWindowName
.LoadString(IDS_VIEWTITLE_MINE
);
1045 m_pwndRightView
->m_sWindowName
+= _T(" - ") + m_Data
.m_yourFile
.GetWindowName();
1046 m_pwndRightView
->m_sFullFilePath
= m_Data
.m_yourFile
.GetFilename();
1047 m_pwndRightView
->m_sConvertedFilePath
= m_Data
.m_yourFile
.GetConvertedFileName();
1048 m_pwndRightView
->m_sReflectedName
= m_Data
.m_yourFile
.GetReflectedName();
1049 m_pwndRightView
->m_pWorkingFile
= &m_Data
.m_yourFile
;
1051 m_pwndBottomView
->m_pViewData
= &m_Data
.m_Diff3
;
1052 m_pwndBottomView
->SetTextType(m_Data
.m_arTheirFile
.GetUnicodeType());
1053 m_pwndBottomView
->SetLineEndingStyle(m_Data
.m_arTheirFile
.GetLineEndings());
1054 m_pwndBottomView
->m_sWindowName
.LoadString(IDS_VIEWTITLE_MERGED
);
1055 m_pwndBottomView
->m_sWindowName
+= _T(" - ") + m_Data
.m_mergedFile
.GetWindowName();
1056 m_pwndBottomView
->m_sFullFilePath
= m_Data
.m_mergedFile
.GetFilename();
1057 m_pwndBottomView
->m_sConvertedFilePath
= m_Data
.m_mergedFile
.GetConvertedFileName();
1058 m_pwndBottomView
->m_sReflectedName
= m_Data
.m_mergedFile
.GetReflectedName();
1059 m_pwndBottomView
->m_pWorkingFile
= &m_Data
.m_mergedFile
;
1061 if (m_wndSplitter2
.IsColumnHidden(1))
1062 m_wndSplitter2
.ShowColumn();
1063 if (m_wndSplitter
.IsRowHidden(1))
1064 m_wndSplitter
.ShowRow();
1065 m_pwndLeftView
->SetHidden(FALSE
);
1066 m_pwndRightView
->SetHidden(FALSE
);
1067 m_pwndBottomView
->SetHidden(FALSE
);
1068 // in three pane view, hide the line diff bar
1069 m_wndLineDiffBar
.ShowPane(false, false, true);
1070 m_wndLineDiffBar
.DocumentUpdated();
1072 if (!m_Data
.m_mergedFile
.InUse())
1074 m_Data
.m_mergedFile
.SetFileName(m_Data
.m_yourFile
.GetFilename());
1076 m_pwndLeftView
->BuildAllScreen2ViewVector();
1077 m_pwndLeftView
->DocumentUpdated();
1078 m_pwndRightView
->DocumentUpdated();
1079 m_pwndBottomView
->DocumentUpdated();
1080 m_wndLocatorBar
.DocumentUpdated();
1081 m_wndLineDiffBar
.DocumentUpdated();
1083 SetActiveView(pwndActiveView
);
1085 if ((line
>= -1) && m_pwndRightView
->m_pViewData
)
1087 int n
= line
== -1 ? min( nOldLineNumber
, nOldLine
) : line
;
1089 n
= m_pwndRightView
->m_pViewData
->FindLineNumber(n
);
1093 m_pwndRightView
->ScrollAllToLine(n
);
1097 if ((ptOldCaretPos
.x
>= 0) || (ptOldCaretPos
.y
>= 0))
1099 m_pwndLeftView
->SetCaretPosition(p
);
1100 m_pwndRightView
->SetCaretPosition(p
);
1101 m_pwndBottomView
->SetCaretPosition(p
);
1102 m_pwndBottomView
->ScrollToChar(0);
1103 m_pwndLeftView
->ScrollToChar(0);
1104 m_pwndRightView
->ScrollToChar(0);
1108 CRegDWORD regFirstDiff
= CRegDWORD(_T("Software\\TortoiseGitMerge\\FirstDiffOnLoad"), TRUE
);
1109 CRegDWORD regFirstConflict
= CRegDWORD(_T("Software\\TortoiseGitMerge\\FirstConflictOnLoad"), TRUE
);
1110 bool bGoFirstDiff
= (0 != (DWORD
)regFirstDiff
);
1111 bool bGoFirstConflict
= (0 != (DWORD
)regFirstConflict
);
1112 if (bGoFirstConflict
&& (CheckResolved()>=0))
1114 pwndActiveView
->GoToFirstConflict();
1115 // Ignore the first few Mouse Move messages, so that the line diff stays on
1116 // the first diff line until the user actually moves the mouse
1117 m_nMoveMovesToIgnore
= MOVESTOIGNORE
;
1119 else if (bGoFirstDiff
)
1121 pwndActiveView
->GoToFirstDifference();
1122 // Ignore the first few Mouse Move messages, so that the line diff stays on
1123 // the first diff line until the user actually moves the mouse
1124 m_nMoveMovesToIgnore
= MOVESTOIGNORE
;
1128 // Avoid incorrect rendering of active pane.
1129 m_pwndBottomView
->ScrollToChar(0);
1130 m_pwndLeftView
->ScrollToChar(0);
1131 m_pwndRightView
->ScrollToChar(0);
1135 if (m_bHasConflicts
&& !m_bSaveRequiredOnConflicts
)
1136 m_bSaveRequired
= false;
1137 CUndo::GetInstance().Clear();
1141 void CMainFrame::UpdateLayout()
1143 if (m_bInitSplitter
)
1145 m_wndSplitter
.CenterSplitter();
1146 m_wndSplitter2
.CenterSplitter();
1150 void CMainFrame::OnSize(UINT nType
, int cx
, int cy
)
1152 CFrameWndEx::OnSize(nType
, cx
, cy
);
1153 if (m_bInitSplitter
&& nType
!= SIZE_MINIMIZED
)
1155 if (m_wndSplitter
.GetSafeHwnd())
1157 if (m_wndSplitter
.HasOldRowSize() && (m_wndSplitter
.GetOldRowCount() == 2))
1159 int oldTotal
= m_wndSplitter
.GetOldRowSize(0) + m_wndSplitter
.GetOldRowSize(1);
1162 int cxCur0
, cxCur1
, cxMin0
, cxMin1
;
1163 m_wndSplitter
.GetRowInfo(0, cxCur0
, cxMin0
);
1164 m_wndSplitter
.GetRowInfo(1, cxCur1
, cxMin1
);
1165 cxCur0
= m_wndSplitter
.GetOldRowSize(0) * (cxCur0
+ cxCur1
) / oldTotal
;
1166 cxCur1
= m_wndSplitter
.GetOldRowSize(1) * (cxCur0
+ cxCur1
) / oldTotal
;
1167 m_wndSplitter
.SetRowInfo(0, cxCur0
, 0);
1168 m_wndSplitter
.SetRowInfo(1, cxCur1
, 0);
1169 m_wndSplitter
.RecalcLayout();
1173 if (m_wndSplitter2
.HasOldColSize() && (m_wndSplitter2
.GetOldColCount() == 2))
1175 int oldTotal
= m_wndSplitter2
.GetOldColSize(0) + m_wndSplitter2
.GetOldColSize(1);
1178 int cyCur0
, cyCur1
, cyMin0
, cyMin1
;
1179 m_wndSplitter2
.GetColumnInfo(0, cyCur0
, cyMin0
);
1180 m_wndSplitter2
.GetColumnInfo(1, cyCur1
, cyMin1
);
1181 cyCur0
= m_wndSplitter2
.GetOldColSize(0) * (cyCur0
+ cyCur1
) / oldTotal
;
1182 cyCur1
= m_wndSplitter2
.GetOldColSize(1) * (cyCur0
+ cyCur1
) / oldTotal
;
1183 m_wndSplitter2
.SetColumnInfo(0, cyCur0
, 0);
1184 m_wndSplitter2
.SetColumnInfo(1, cyCur1
, 0);
1185 m_wndSplitter2
.RecalcLayout();
1190 if ((nType
== SIZE_RESTORED
)&&m_bCheckReload
)
1192 m_bCheckReload
= false;
1197 void CMainFrame::OnViewWhitespaces()
1199 CRegDWORD regViewWhitespaces
= CRegDWORD(_T("Software\\TortoiseGitMerge\\ViewWhitespaces"), 1);
1200 BOOL bViewWhitespaces
= regViewWhitespaces
;
1202 bViewWhitespaces
= m_pwndLeftView
->m_bViewWhitespace
;
1204 bViewWhitespaces
= !bViewWhitespaces
;
1205 regViewWhitespaces
= bViewWhitespaces
;
1208 m_pwndLeftView
->m_bViewWhitespace
= bViewWhitespaces
;
1209 m_pwndLeftView
->Invalidate();
1211 if (m_pwndRightView
)
1213 m_pwndRightView
->m_bViewWhitespace
= bViewWhitespaces
;
1214 m_pwndRightView
->Invalidate();
1216 if (m_pwndBottomView
)
1218 m_pwndBottomView
->m_bViewWhitespace
= bViewWhitespaces
;
1219 m_pwndBottomView
->Invalidate();
1223 void CMainFrame::OnUpdateViewWhitespaces(CCmdUI
*pCmdUI
)
1226 pCmdUI
->SetCheck(m_pwndLeftView
->m_bViewWhitespace
);
1229 void CMainFrame::OnViewCollapsed()
1231 m_regCollapsed
= !(DWORD
)m_regCollapsed
;
1232 m_bCollapsed
= !!(DWORD
)m_regCollapsed
;
1234 OnViewTextFoldUnfold();
1235 m_wndLocatorBar
.Invalidate();
1238 void CMainFrame::OnUpdateViewCollapsed(CCmdUI
*pCmdUI
)
1240 pCmdUI
->SetCheck(m_bCollapsed
);
1243 void CMainFrame::OnViewWraplonglines()
1245 m_bWrapLines
= !(DWORD
)m_regWrapLines
;
1246 m_regWrapLines
= m_bWrapLines
;
1248 if (m_pwndLeftView
) m_pwndLeftView
->WrapChanged();
1249 if (m_pwndRightView
) m_pwndRightView
->WrapChanged();
1250 if (m_pwndBottomView
) m_pwndBottomView
->WrapChanged();
1251 OnViewTextFoldUnfold();
1252 m_wndLocatorBar
.DocumentUpdated();
1255 void CMainFrame::OnViewTextFoldUnfold()
1257 OnViewTextFoldUnfold(m_pwndLeftView
);
1258 OnViewTextFoldUnfold(m_pwndRightView
);
1259 OnViewTextFoldUnfold(m_pwndBottomView
);
1262 void CMainFrame::OnViewTextFoldUnfold(CBaseView
* view
)
1266 view
->BuildAllScreen2ViewVector();
1267 view
->UpdateCaret();
1269 view
->EnsureCaretVisible();
1272 void CMainFrame::OnUpdateViewWraplonglines(CCmdUI
*pCmdUI
)
1274 pCmdUI
->SetCheck(m_bWrapLines
);
1277 void CMainFrame::OnViewOnewaydiff()
1279 if (CheckForSave(CHFSR_RELOAD
)==IDCANCEL
)
1281 m_bOneWay
= !m_bOneWay
;
1282 ShowDiffBar(!m_bOneWay
);
1286 void CMainFrame::ShowDiffBar(bool bShow
)
1290 // restore the line diff bar
1291 m_wndLineDiffBar
.ShowPane(m_bLineDiff
, false, true);
1292 m_wndLineDiffBar
.DocumentUpdated();
1293 m_wndLocatorBar
.ShowPane(m_bLocatorBar
, false, true);
1294 m_wndLocatorBar
.DocumentUpdated();
1298 // in one way view, hide the line diff bar
1299 m_wndLineDiffBar
.ShowPane(false, false, true);
1300 m_wndLineDiffBar
.DocumentUpdated();
1304 int CMainFrame::CheckResolved()
1306 //only in three way diffs can be conflicts!
1307 m_bHasConflicts
= true;
1308 if (IsViewGood(m_pwndBottomView
))
1310 CViewData
* viewdata
= m_pwndBottomView
->m_pViewData
;
1313 for (int i
=0; i
<viewdata
->GetCount(); i
++)
1315 const DiffStates state
= viewdata
->GetState(i
);
1316 if ((DIFFSTATE_CONFLICTED
== state
)||(DIFFSTATE_CONFLICTED_IGNORED
== state
))
1321 m_bHasConflicts
= false;
1325 int CMainFrame::SaveFile(const CString
& sFilePath
)
1327 CBaseView
* pView
= NULL
;
1328 CViewData
* pViewData
= NULL
;
1329 CFileTextLines
* pOriginFile
= &m_Data
.m_arBaseFile
;
1330 if (IsViewGood(m_pwndBottomView
))
1332 pView
= m_pwndBottomView
;
1333 pViewData
= m_pwndBottomView
->m_pViewData
;
1335 else if (IsViewGood(m_pwndRightView
))
1337 pView
= m_pwndRightView
;
1338 pViewData
= m_pwndRightView
->m_pViewData
;
1339 if (m_Data
.IsYourFileInUse())
1340 pOriginFile
= &m_Data
.m_arYourFile
;
1341 else if (m_Data
.IsTheirFileInUse())
1342 pOriginFile
= &m_Data
.m_arTheirFile
;
1350 if ((pViewData
)&&(pOriginFile
))
1352 CFileTextLines file
;
1353 pOriginFile
->CopySettings(&file
);
1354 CFileTextLines::SaveParams saveParams
;
1355 saveParams
.m_LineEndings
= pView
->GetLineEndings();
1356 saveParams
.m_UnicodeType
= pView
->GetTextType();
1357 file
.SetSaveParams(saveParams
);
1358 for (int i
=0; i
<pViewData
->GetCount(); i
++)
1360 //only copy non-removed lines
1361 DiffStates state
= pViewData
->GetState(i
);
1364 case DIFFSTATE_CONFLICTED
:
1365 case DIFFSTATE_CONFLICTED_IGNORED
:
1372 } while((last
<pViewData
->GetCount()) && ((pViewData
->GetState(last
)==DIFFSTATE_CONFLICTED
)||(pViewData
->GetState(last
)==DIFFSTATE_CONFLICTED_IGNORED
)));
1373 // TortoiseGitMerge changes here
1374 file
.Add(_T("<<<<<<< .mine"), m_pwndRightView
->GetLineEndings());
1375 for (int j
=first
; j
<last
; j
++)
1377 EOL lineending
= m_pwndRightView
->m_pViewData
->GetLineEnding(j
);
1378 if (lineending
== EOL_NOENDING
)
1379 lineending
= m_pwndRightView
->GetLineEndings();
1380 file
.Add(m_pwndRightView
->m_pViewData
->GetLine(j
), lineending
);
1382 file
.Add(_T("======="), m_pwndRightView
->GetLineEndings());
1383 for (int j
=first
; j
<last
; j
++)
1385 EOL lineending
= m_pwndLeftView
->m_pViewData
->GetLineEnding(j
);
1386 if (lineending
== EOL_NOENDING
)
1387 lineending
= m_pwndLeftView
->GetLineEndings();
1388 file
.Add(m_pwndLeftView
->m_pViewData
->GetLine(j
), lineending
);
1390 file
.Add(_T(">>>>>>> .theirs"), m_pwndRightView
->GetLineEndings());
1394 case DIFFSTATE_EMPTY
:
1395 case DIFFSTATE_CONFLICTEMPTY
:
1396 case DIFFSTATE_IDENTICALREMOVED
:
1397 case DIFFSTATE_REMOVED
:
1398 case DIFFSTATE_THEIRSREMOVED
:
1399 case DIFFSTATE_YOURSREMOVED
:
1400 case DIFFSTATE_CONFLICTRESOLVEDEMPTY
:
1401 // do not save removed lines
1404 file
.Add(pViewData
->GetLine(i
), pViewData
->GetLineEnding(i
));
1408 if (!file
.Save(sFilePath
, false, false))
1410 CMessageBox::Show(m_hWnd
, file
.GetErrorString(), _T("TortoiseGitMerge"), MB_ICONERROR
);
1413 if (sFilePath
== m_Data
.m_baseFile
.GetFilename())
1415 m_Data
.m_baseFile
.StoreFileAttributes();
1417 if (sFilePath
== m_Data
.m_theirFile
.GetFilename())
1419 m_Data
.m_theirFile
.StoreFileAttributes();
1421 if (sFilePath
== m_Data
.m_yourFile
.GetFilename())
1423 m_Data
.m_yourFile
.StoreFileAttributes();
1425 /*if (sFilePath == m_Data.m_mergedFile.GetFilename())
1427 m_Data.m_mergedFile.StoreFileAttributes();
1429 m_dlgFilePatches
.SetFileStatusAsPatched(sFilePath
);
1430 if (IsViewGood(m_pwndBottomView
))
1431 m_pwndBottomView
->SetModified(FALSE
);
1432 else if (IsViewGood(m_pwndRightView
))
1433 m_pwndRightView
->SetModified(FALSE
);
1434 CUndo::GetInstance().MarkAsOriginalState(
1436 IsViewGood(m_pwndRightView
) && (pViewData
== m_pwndRightView
->m_pViewData
),
1437 IsViewGood(m_pwndBottomView
) && (pViewData
== m_pwndBottomView
->m_pViewData
));
1438 if (file
.GetCount() == 1 && file
.GetAt(0).IsEmpty() && file
.GetLineEnding(0) == EOL_NOENDING
)
1440 return file
.GetCount();
1445 void CMainFrame::OnFileSave()
1447 // when multiple files are set as writable we have to ask what file to save
1448 int nEditableViewCount
=
1449 (CBaseView::IsViewGood(m_pwndLeftView
) && m_pwndLeftView
->IsWritable() ? 1 : 0)
1450 + (CBaseView::IsViewGood(m_pwndRightView
) && m_pwndRightView
->IsWritable() ? 1 : 0)
1451 + (CBaseView::IsViewGood(m_pwndBottomView
) && m_pwndBottomView
->IsWritable() ? 1 : 0);
1452 bool bLeftIsModified
= CBaseView::IsViewGood(m_pwndLeftView
) && m_pwndLeftView
->IsModified();
1453 bool bRightIsModified
= CBaseView::IsViewGood(m_pwndRightView
) && m_pwndRightView
->IsModified();
1454 bool bBottomIsModified
= CBaseView::IsViewGood(m_pwndBottomView
) && m_pwndBottomView
->IsModified();
1455 int nModifiedViewCount
=
1456 (bLeftIsModified
? 1 : 0)
1457 + (bRightIsModified
? 1 : 0)
1458 + (bBottomIsModified
? 1 : 0);
1459 if (nEditableViewCount
>1)
1461 if (nModifiedViewCount
== 1)
1463 if (bLeftIsModified
)
1464 m_pwndLeftView
->SaveFile(SAVE_REMOVEDLINES
);
1468 else if (nModifiedViewCount
>0)
1471 CTaskDialog
taskdlg(CString(MAKEINTRESOURCE(IDS_SAVE_MORE
)),
1472 CString(MAKEINTRESOURCE(IDS_SAVE
)),
1473 CString(MAKEINTRESOURCE(IDS_APPNAME
)),
1475 TDF_ENABLE_HYPERLINKS
| TDF_USE_COMMAND_LINKS
| TDF_ALLOW_DIALOG_CANCELLATION
| TDF_POSITION_RELATIVE_TO_WINDOW
);
1477 if (m_pwndLeftView
->m_pWorkingFile
->InUse() && !m_pwndLeftView
->m_pWorkingFile
->IsReadonly())
1478 sTaskTemp
.Format(IDS_ASKFORSAVE_SAVELEFT
, (LPCTSTR
)m_pwndLeftView
->m_pWorkingFile
->GetFilename());
1480 sTaskTemp
= CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_SAVELEFTAS
));
1481 taskdlg
.AddCommandControl(201, sTaskTemp
, bLeftIsModified
);// left
1482 if (bLeftIsModified
)
1483 taskdlg
.SetDefaultCommandControl(201);
1484 if (m_pwndRightView
->m_pWorkingFile
->InUse() && !m_pwndRightView
->m_pWorkingFile
->IsReadonly())
1485 sTaskTemp
.Format(IDS_ASKFORSAVE_SAVERIGHT
, (LPCTSTR
)m_pwndRightView
->m_pWorkingFile
->GetFilename());
1487 sTaskTemp
= CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_SAVERIGHTAS
));
1488 taskdlg
.AddCommandControl(202, sTaskTemp
, bRightIsModified
); // right
1489 if (bRightIsModified
)
1490 taskdlg
.SetDefaultCommandControl(202);
1491 taskdlg
.AddCommandControl(203, CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_SAVEALL2
)), nModifiedViewCount
>1); // both
1492 if (nModifiedViewCount
> 1)
1493 taskdlg
.SetDefaultCommandControl(203);
1494 taskdlg
.SetCommonButtons(TDCBF_CANCEL_BUTTON
);
1495 taskdlg
.SetMainIcon(TD_WARNING_ICON
);
1496 UINT ret
= (UINT
)taskdlg
.DoModal(m_hWnd
);
1500 m_pwndLeftView
->SaveFile(SAVE_REMOVEDLINES
);
1503 m_pwndLeftView
->SaveFile(SAVE_REMOVEDLINES
);
1505 m_pwndRightView
->SaveFile();
1512 // only target view was modified
1517 void CMainFrame::PatchSave()
1519 bool bDoesNotExist
= !PathFileExists(m_Data
.m_mergedFile
.GetFilename());
1520 if (m_Data
.m_bPatchRequired
)
1522 m_Patch
.PatchPath(m_Data
.m_mergedFile
.GetFilename());
1524 if (!PathIsDirectory(m_Data
.m_mergedFile
.GetFilename()))
1526 int saveret
= SaveFile(m_Data
.m_mergedFile
.GetFilename());
1529 // file was saved with 0 lines, remove it.
1530 m_Patch
.RemoveFile(m_Data
.m_mergedFile
.GetFilename());
1532 DeleteFile(m_Data
.m_mergedFile
.GetFilename());
1534 m_Data
.m_mergedFile
.StoreFileAttributes();
1535 if (m_Data
.m_mergedFile
.GetFilename() == m_Data
.m_yourFile
.GetFilename())
1536 m_Data
.m_yourFile
.StoreFileAttributes();
1537 if ((bDoesNotExist
)&&(DWORD(CRegDWORD(_T("Software\\TortoiseGitMerge\\AutoAdd"), TRUE
))))
1539 // call TortoiseProc to add the new file to version control
1540 CString cmd
= _T("/command:add /noui /path:\"");
1541 cmd
+= m_Data
.m_mergedFile
.GetFilename() + _T("\"");
1542 CAppUtils::RunTortoiseGitProc(cmd
);
1547 bool CMainFrame::FileSave(bool bCheckResolved
/*=true*/)
1549 if (HasMarkedBlocks())
1551 CString
sTitle(MAKEINTRESOURCE(IDS_WARNMARKEDBLOCKS
));
1552 CString
sSubTitle(MAKEINTRESOURCE(IDS_ASKFORSAVE_MARKEDBLOCKS
));
1553 CString
sAppName(MAKEINTRESOURCE(IDS_APPNAME
));
1554 CTaskDialog
taskdlg(sTitle
,
1558 TDF_ENABLE_HYPERLINKS
| TDF_USE_COMMAND_LINKS
| TDF_ALLOW_DIALOG_CANCELLATION
| TDF_POSITION_RELATIVE_TO_WINDOW
);
1559 taskdlg
.AddCommandControl(10, CString(MAKEINTRESOURCE(IDS_MARKEDBLOCKSSAVEINCLUDE
)));
1560 taskdlg
.AddCommandControl(11, CString(MAKEINTRESOURCE(IDS_MARKEDBLOCKSSAVEEXCLUDE
)));
1561 taskdlg
.AddCommandControl(12, CString(MAKEINTRESOURCE(IDS_MARKEDBLCOKSSAVEIGNORE
)));
1562 taskdlg
.AddCommandControl(IDCANCEL
, CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_CANCEL_OPEN
)));
1563 taskdlg
.SetCommonButtons(TDCBF_CANCEL_BUTTON
);
1564 taskdlg
.SetDefaultCommandControl(10);
1565 taskdlg
.SetMainIcon(TD_WARNING_ICON
);
1566 UINT ret
= (UINT
)taskdlg
.DoModal(m_hWnd
);
1568 m_pwndRightView
->LeaveOnlyMarkedBlocks();
1570 m_pwndRightView
->UseViewFileOfMarked();
1572 m_pwndRightView
->UseViewFileExceptEdited();
1577 if (!m_Data
.m_mergedFile
.InUse())
1578 return FileSaveAs(bCheckResolved
);
1579 // check if the file has the readonly attribute set
1580 bool bDoesNotExist
= false;
1581 DWORD fAttribs
= GetFileAttributes(m_Data
.m_mergedFile
.GetFilename());
1582 if ((fAttribs
!= INVALID_FILE_ATTRIBUTES
)&&(fAttribs
& FILE_ATTRIBUTE_READONLY
))
1583 return FileSaveAs(bCheckResolved
);
1584 if (fAttribs
== INVALID_FILE_ATTRIBUTES
)
1586 bDoesNotExist
= (GetLastError() == ERROR_FILE_NOT_FOUND
);
1588 if (bCheckResolved
&& HasConflictsWontKeep())
1591 if (((DWORD
)CRegDWORD(_T("Software\\TortoiseGitMerge\\Backup"))) != 0)
1593 MoveFileEx(m_Data
.m_mergedFile
.GetFilename(), m_Data
.m_mergedFile
.GetFilename() + _T(".bak"), MOVEFILE_COPY_ALLOWED
| MOVEFILE_REPLACE_EXISTING
| MOVEFILE_WRITE_THROUGH
);
1595 if (m_Data
.m_bPatchRequired
)
1597 m_Patch
.PatchPath(m_Data
.m_mergedFile
.GetFilename());
1599 int saveret
= SaveFile(m_Data
.m_mergedFile
.GetFilename());
1602 // file was saved with 0 lines!
1603 // ask the user if the file should be deleted
1605 msg
.Format(IDS_DELETEWHENEMPTY
, (LPCTSTR
)CPathUtils::GetFileNameFromPath(m_Data
.m_mergedFile
.GetFilename()));
1606 CTaskDialog
taskdlg(msg
,
1607 CString(MAKEINTRESOURCE(IDS_DELETEWHENEMPTY_TASK2
)),
1608 CString(MAKEINTRESOURCE(IDS_APPNAME
)),
1610 TDF_ENABLE_HYPERLINKS
| TDF_USE_COMMAND_LINKS
| TDF_ALLOW_DIALOG_CANCELLATION
| TDF_POSITION_RELATIVE_TO_WINDOW
);
1611 taskdlg
.AddCommandControl(1, CString(MAKEINTRESOURCE(IDS_DELETEWHENEMPTY_TASK3
)));
1612 taskdlg
.AddCommandControl(2, CString(MAKEINTRESOURCE(IDS_DELETEWHENEMPTY_TASK4
)));
1613 taskdlg
.SetCommonButtons(TDCBF_CANCEL_BUTTON
);
1614 taskdlg
.SetDefaultCommandControl(1);
1615 taskdlg
.SetMainIcon(TD_WARNING_ICON
);
1616 if (taskdlg
.DoModal(m_hWnd
) == 1)
1618 m_Patch
.RemoveFile(m_Data
.m_mergedFile
.GetFilename());
1619 DeleteFile(m_Data
.m_mergedFile
.GetFilename());
1622 else if (saveret
< 0)
1624 // error while saving the file
1628 // if we're in conflict resolve mode (three pane view), check if there are no more conflicts
1629 // and if there aren't, ask to mark the file as resolved
1630 if (IsViewGood(m_pwndBottomView
) && !m_bHasConflicts
&& bCheckResolved
)
1632 CString projectRoot
;
1633 if (GitAdminDir::HasAdminDir(m_Data
.m_mergedFile
.GetFilename(), false, &projectRoot
))
1635 CString subpath
= m_Data
.m_mergedFile
.GetFilename();
1636 subpath
.Replace(_T('\\'), _T('/'));
1637 if (subpath
.GetLength() >= projectRoot
.GetLength())
1639 if (subpath
[projectRoot
.GetLength()] == _T('/'))
1640 subpath
= subpath
.Right(subpath
.GetLength() - projectRoot
.GetLength() - 1);
1642 subpath
= subpath
.Right(subpath
.GetLength() - projectRoot
.GetLength());
1645 CAutoRepository
repository(projectRoot
);
1646 bool hasConflictInIndex
= false;
1653 if (git_repository_index(index
.GetPointer(), repository
))
1656 CStringA path
= CUnicodeUtils::GetMulti(subpath
, CP_UTF8
);
1657 const git_index_entry
* entry
= git_index_get_bypath(index
, path
, 1);
1658 hasConflictInIndex
= entry
!= nullptr;
1661 if (hasConflictInIndex
)
1664 msg
.Format(IDS_MARKASRESOLVED
, (LPCTSTR
)CPathUtils::GetFileNameFromPath(m_Data
.m_mergedFile
.GetFilename()));
1665 CTaskDialog
taskdlg(msg
,
1666 CString(MAKEINTRESOURCE(IDS_MARKASRESOLVED_TASK2
)),
1667 CString(MAKEINTRESOURCE(IDS_APPNAME
)),
1669 TDF_ENABLE_HYPERLINKS
| TDF_USE_COMMAND_LINKS
| TDF_ALLOW_DIALOG_CANCELLATION
| TDF_POSITION_RELATIVE_TO_WINDOW
);
1670 taskdlg
.AddCommandControl(1, CString(MAKEINTRESOURCE(IDS_MARKASRESOLVED_TASK3
)));
1671 taskdlg
.AddCommandControl(2, CString(MAKEINTRESOURCE(IDS_MARKASRESOLVED_TASK4
)));
1672 taskdlg
.SetCommonButtons(TDCBF_CANCEL_BUTTON
);
1673 taskdlg
.SetDefaultCommandControl(1);
1674 taskdlg
.SetMainIcon(TD_WARNING_ICON
);
1675 if (taskdlg
.DoModal(m_hWnd
) == 1)
1681 m_bSaveRequired
= false;
1682 m_Data
.m_mergedFile
.StoreFileAttributes();
1684 if ((bDoesNotExist
)&&(DWORD(CRegDWORD(_T("Software\\TortoiseGitMerge\\AutoAdd"), TRUE
))))
1686 // call TortoiseProc to add the new file to version control
1687 CString cmd
= _T("/command:add /noui /path:\"");
1688 cmd
+= m_Data
.m_mergedFile
.GetFilename() + _T("\"");
1689 if(!CAppUtils::RunTortoiseGitProc(cmd
))
1695 void CMainFrame::OnFileSaveAs()
1697 // ask what file to save as
1698 bool bHaveConflict
= (CheckResolved() >= 0);
1699 CTaskDialog
taskdlg(
1700 CString(MAKEINTRESOURCE(bHaveConflict
? IDS_ASKFORSAVEAS_MORECONFLICT
: IDS_ASKFORSAVEAS_MORE
)),
1701 CString(MAKEINTRESOURCE(IDS_ASKFORSAVEAS
)),
1702 CString(MAKEINTRESOURCE(IDS_APPNAME
)),
1704 TDF_ENABLE_HYPERLINKS
| TDF_USE_COMMAND_LINKS
| TDF_ALLOW_DIALOG_CANCELLATION
| TDF_POSITION_RELATIVE_TO_WINDOW
);
1705 // default can be last view (target) as was in 1.7 or actual (where is cursor) as is in most text editor
1706 if (IsViewGood(m_pwndLeftView
))
1708 taskdlg
.AddCommandControl(201, CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_SAVELEFTAS
))); // left
1709 taskdlg
.SetDefaultCommandControl(201);
1711 if (IsViewGood(m_pwndRightView
))
1713 taskdlg
.AddCommandControl(202, CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_SAVERIGHTAS
))); // right
1714 taskdlg
.SetDefaultCommandControl(202);
1716 if (IsViewGood(m_pwndBottomView
))
1718 taskdlg
.AddCommandControl(203, CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_SAVEBOTTOMAS
))); // bottom
1719 taskdlg
.SetDefaultCommandControl(203);
1723 taskdlg
.AddCommandControl(204, CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_NEEDRESOLVE
))); // resolve
1724 taskdlg
.SetDefaultCommandControl(204);
1726 taskdlg
.SetCommonButtons(TDCBF_CANCEL_BUTTON
);
1727 taskdlg
.SetMainIcon(bHaveConflict
? TD_WARNING_ICON
: TD_INFORMATION_ICON
);
1728 int nCommand
= (int)taskdlg
.DoModal(m_hWnd
);
1733 if (TryGetFileName(sFileName
))
1735 // in 2, 3 view display we want to keep removed lines
1736 m_pwndLeftView
->SaveFileTo(sFileName
, IsViewGood(m_pwndRightView
) ? SAVE_REMOVEDLINES
: 0);
1740 if (TryGetFileName(sFileName
))
1742 m_pwndRightView
->SaveFileTo(sFileName
);
1748 case 204: // continue resolving
1749 if (IsViewGood(m_pwndBottomView
))
1751 m_pwndBottomView
->GoToLine(CheckResolved());
1757 bool CMainFrame::FileSaveAs(bool bCheckResolved
/*=true*/)
1759 if (bCheckResolved
&& HasConflictsWontKeep())
1763 if(!TryGetFileName(fileName
))
1770 void CMainFrame::OnUpdateFileSave(CCmdUI
*pCmdUI
)
1772 BOOL bEnable
= FALSE
;
1773 if (m_Data
.m_mergedFile
.InUse())
1775 if (IsViewGood(m_pwndBottomView
)&&(m_pwndBottomView
->m_pViewData
))
1777 else if ( (IsViewGood(m_pwndRightView
)&&(m_pwndRightView
->m_pViewData
)) &&
1778 (m_pwndRightView
->IsModified() || (m_Data
.m_yourFile
.GetWindowName().Right(9).Compare(_T(": patched"))==0)) )
1780 else if (IsViewGood(m_pwndLeftView
)
1781 && (m_pwndLeftView
->m_pViewData
)
1782 && (m_pwndLeftView
->IsModified()))
1785 pCmdUI
->Enable(bEnable
);
1788 void CMainFrame::OnUpdateFileSaveAs(CCmdUI
*pCmdUI
)
1790 // any file is open we can save it as
1791 BOOL bEnable
= FALSE
;
1792 if (IsViewGood(m_pwndBottomView
)&&(m_pwndBottomView
->m_pViewData
))
1794 else if (IsViewGood(m_pwndRightView
)&&(m_pwndRightView
->m_pViewData
))
1796 else if (IsViewGood(m_pwndLeftView
)&&(m_pwndLeftView
->m_pViewData
))
1798 pCmdUI
->Enable(bEnable
);
1801 void CMainFrame::OnUpdateViewOnewaydiff(CCmdUI
*pCmdUI
)
1803 pCmdUI
->SetCheck(!m_bOneWay
);
1804 BOOL bEnable
= TRUE
;
1805 if (IsViewGood(m_pwndBottomView
))
1809 pCmdUI
->Enable(bEnable
);
1812 void CMainFrame::OnViewOptions()
1815 sTemp
.LoadString(IDS_SETTINGSTITLE
);
1816 CSettings
dlg(sTemp
);
1818 if (dlg
.IsReloadNeeded())
1820 if (CheckForSave(CHFSR_OPTIONS
)==IDCANCEL
)
1822 CDiffColors::GetInstance().LoadRegistry();
1826 CDiffColors::GetInstance().LoadRegistry();
1827 if (m_pwndBottomView
)
1828 m_pwndBottomView
->Invalidate();
1830 m_pwndLeftView
->Invalidate();
1831 if (m_pwndRightView
)
1832 m_pwndRightView
->Invalidate();
1835 void CMainFrame::OnClose()
1837 if (!IsWindowEnabled())
1838 return; // just in case someone sends a WM_CLOSE to the main window while another window (dialog,...) is open
1839 if (CheckForSave(CHFSR_CLOSE
)!=IDCANCEL
)
1843 // before it is destroyed, save the position of the window
1844 wp
.length
= sizeof wp
;
1846 if (GetWindowPlacement(&wp
))
1850 // never restore to Iconic state
1851 wp
.showCmd
= SW_SHOW
;
1853 if ((wp
.flags
& WPF_RESTORETOMAXIMIZED
) != 0)
1854 // if maximized and maybe iconic restore maximized state
1855 wp
.showCmd
= SW_SHOWMAXIMIZED
;
1858 WriteWindowPlacement(&wp
);
1864 void CMainFrame::OnActivate(UINT nValue
, CWnd
* /*pwnd*/, BOOL
/*bActivated?*/)
1866 if (nValue
!= 0) // activated
1870 m_bCheckReload
= TRUE
;
1874 // use a timer to give other messages time to get processed
1875 // first, like e.g. the WM_CLOSE message in case the user
1876 // clicked the close button and that brought the window
1877 // to the front - in that case checking for reload wouldn't
1879 SetTimer(IDT_RELOADCHECKTIMER
, 300, NULL
);
1884 void CMainFrame::OnViewLinedown()
1886 OnViewLineUpDown(1);
1889 void CMainFrame::OnViewLineup()
1891 OnViewLineUpDown(-1);
1894 void CMainFrame::OnViewLineUpDown(int direction
)
1897 m_pwndLeftView
->ScrollToLine(m_pwndLeftView
->m_nTopLine
+direction
);
1898 if (m_pwndRightView
)
1899 m_pwndRightView
->ScrollToLine(m_pwndRightView
->m_nTopLine
+direction
);
1900 if (m_pwndBottomView
)
1901 m_pwndBottomView
->ScrollToLine(m_pwndBottomView
->m_nTopLine
+direction
);
1902 m_wndLocatorBar
.Invalidate();
1903 m_nMoveMovesToIgnore
= MOVESTOIGNORE
;
1906 void CMainFrame::OnViewLineleft()
1908 OnViewLineLeftRight(-1);
1911 void CMainFrame::OnViewLineright()
1913 OnViewLineLeftRight(1);
1916 void CMainFrame::OnViewLineLeftRight(int direction
)
1919 m_pwndLeftView
->ScrollSide(direction
);
1920 if (m_pwndRightView
)
1921 m_pwndRightView
->ScrollSide(direction
);
1922 if (m_pwndBottomView
)
1923 m_pwndBottomView
->ScrollSide(direction
);
1926 void CMainFrame::OnEditUseTheirs()
1928 if (m_pwndBottomView
)
1929 m_pwndBottomView
->UseTheirTextBlock();
1931 void CMainFrame::OnUpdateEditUsetheirblock(CCmdUI
*pCmdUI
)
1933 pCmdUI
->Enable(m_pwndBottomView
&& m_pwndBottomView
->HasSelection());
1936 void CMainFrame::OnEditUseMine()
1938 if (m_pwndBottomView
)
1939 m_pwndBottomView
->UseMyTextBlock();
1941 void CMainFrame::OnUpdateEditUsemyblock(CCmdUI
*pCmdUI
)
1943 OnUpdateEditUsetheirblock(pCmdUI
);
1946 void CMainFrame::OnEditUseTheirsThenMine()
1948 if (m_pwndBottomView
)
1949 m_pwndBottomView
->UseTheirAndYourBlock();
1952 void CMainFrame::OnUpdateEditUsetheirthenmyblock(CCmdUI
*pCmdUI
)
1954 OnUpdateEditUsetheirblock(pCmdUI
);
1957 void CMainFrame::OnEditUseMineThenTheirs()
1959 if (m_pwndBottomView
)
1960 m_pwndBottomView
->UseYourAndTheirBlock();
1963 void CMainFrame::OnUpdateEditUseminethentheirblock(CCmdUI
*pCmdUI
)
1965 OnUpdateEditUsetheirblock(pCmdUI
);
1968 void CMainFrame::OnEditUseleftblock()
1970 if (m_pwndBottomView
->IsWindowVisible())
1971 m_pwndBottomView
->UseRightBlock();
1973 m_pwndRightView
->UseLeftBlock();
1976 void CMainFrame::OnUpdateEditUseleftblock(CCmdUI
*pCmdUI
)
1978 pCmdUI
->Enable(IsViewGood(m_pwndRightView
) && m_pwndRightView
->IsTarget() && m_pwndRightView
->HasSelection());
1981 void CMainFrame::OnUpdateUseBlock(CCmdUI
*pCmdUI
)
1983 pCmdUI
->Enable(TRUE
);
1986 void CMainFrame::OnEditUseleftfile()
1988 if (m_pwndBottomView
->IsWindowVisible())
1989 m_pwndBottomView
->UseRightFile();
1991 m_pwndRightView
->UseLeftFile();
1994 void CMainFrame::OnUpdateEditUseleftfile(CCmdUI
*pCmdUI
)
1996 pCmdUI
->Enable(IsViewGood(m_pwndRightView
) && m_pwndRightView
->IsTarget());
1999 void CMainFrame::OnEditUseblockfromleftbeforeright()
2001 if (m_pwndRightView
)
2002 m_pwndRightView
->UseBothLeftFirst();
2005 void CMainFrame::OnUpdateEditUseblockfromleftbeforeright(CCmdUI
*pCmdUI
)
2007 OnUpdateEditUseleftblock(pCmdUI
);
2010 void CMainFrame::OnEditUseblockfromrightbeforeleft()
2012 if (m_pwndRightView
)
2013 m_pwndRightView
->UseBothRightFirst();
2016 void CMainFrame::OnUpdateEditUseblockfromrightbeforeleft(CCmdUI
*pCmdUI
)
2018 OnUpdateEditUseleftblock(pCmdUI
);
2021 void CMainFrame::OnFileReload()
2023 if (CheckForSave(CHFSR_RELOAD
)==IDCANCEL
)
2025 CDiffColors::GetInstance().LoadRegistry();
2029 void CMainFrame::ActivateFrame(int nCmdShow
)
2031 // nCmdShow is the normal show mode this frame should be in
2032 // translate default nCmdShow (-1)
2035 if (!IsWindowVisible())
2036 nCmdShow
= SW_SHOWNORMAL
;
2037 else if (IsIconic())
2038 nCmdShow
= SW_RESTORE
;
2041 // bring to top before showing
2042 BringToTop(nCmdShow
);
2046 // show the window as specified
2049 if ( !ReadWindowPlacement(&wp
) )
2051 ShowWindow(nCmdShow
);
2055 if ( nCmdShow
!= SW_SHOWNORMAL
)
2056 wp
.showCmd
= nCmdShow
;
2058 SetWindowPlacement(&wp
);
2061 // and finally, bring to top after showing
2062 BringToTop(nCmdShow
);
2066 BOOL
CMainFrame::ReadWindowPlacement(WINDOWPLACEMENT
* pwp
)
2068 CRegString placement
= CRegString(_T("Software\\TortoiseGitMerge\\WindowPos"));
2069 CString sPlacement
= placement
;
2070 if (sPlacement
.IsEmpty())
2072 int nRead
= _stscanf_s(sPlacement
, _T("%u,%u,%d,%d,%d,%d,%d,%d,%d,%d"),
2073 &pwp
->flags
, &pwp
->showCmd
,
2074 &pwp
->ptMinPosition
.x
, &pwp
->ptMinPosition
.y
,
2075 &pwp
->ptMaxPosition
.x
, &pwp
->ptMaxPosition
.y
,
2076 &pwp
->rcNormalPosition
.left
, &pwp
->rcNormalPosition
.top
,
2077 &pwp
->rcNormalPosition
.right
, &pwp
->rcNormalPosition
.bottom
);
2080 pwp
->length
= sizeof(WINDOWPLACEMENT
);
2085 void CMainFrame::WriteWindowPlacement(WINDOWPLACEMENT
* pwp
)
2087 CRegString
placement(L
"Software\\TortoiseGitMerge\\WindowPos");
2088 TCHAR szBuffer
[_countof("-32767")*8 + sizeof("65535")*2];
2090 _stprintf_s(szBuffer
, _T("%u,%u,%d,%d,%d,%d,%d,%d,%d,%d"),
2091 pwp
->flags
, pwp
->showCmd
,
2092 pwp
->ptMinPosition
.x
, pwp
->ptMinPosition
.y
,
2093 pwp
->ptMaxPosition
.x
, pwp
->ptMaxPosition
.y
,
2094 pwp
->rcNormalPosition
.left
, pwp
->rcNormalPosition
.top
,
2095 pwp
->rcNormalPosition
.right
, pwp
->rcNormalPosition
.bottom
);
2096 placement
= szBuffer
;
2099 void CMainFrame::OnUpdateMergeMarkasresolved(CCmdUI
*pCmdUI
)
2103 BOOL bEnable
= FALSE
;
2104 if ((!m_bReadOnly
)&&(m_Data
.m_mergedFile
.InUse()))
2106 if (IsViewGood(m_pwndBottomView
)&&(m_pwndBottomView
->m_pViewData
))
2111 pCmdUI
->Enable(bEnable
);
2114 void CMainFrame::OnMergeMarkasresolved()
2116 if(HasConflictsWontKeep())
2119 // now check if the file has already been saved and if not, save it.
2120 if (m_Data
.m_mergedFile
.InUse())
2122 if (IsViewGood(m_pwndBottomView
)&&(m_pwndBottomView
->m_pViewData
))
2124 if (!FileSave(false))
2126 m_bSaveRequired
= false;
2132 BOOL
CMainFrame::MarkAsResolved()
2136 if (!IsViewGood(m_pwndBottomView
))
2139 CString cmd
= _T("/command:resolve /path:\"");
2140 cmd
+= m_Data
.m_mergedFile
.GetFilename();
2141 cmd
+= _T("\" /closeonend:1 /noquestion /skipcheck /silent");
2145 s
.Format(L
" /resolvemsghwnd:%I64d /resolvemsgwparam:%I64d /resolvemsglparam:%I64d", (__int64
)resolveMsgWnd
, (__int64
)resolveMsgWParam
, (__int64
)resolveMsgLParam
);
2148 if(!CAppUtils::RunTortoiseGitProc(cmd
))
2150 m_bSaveRequired
= false;
2154 void CMainFrame::OnUpdateMergeNextconflict(CCmdUI
*pCmdUI
)
2157 if (HasNextConflict(m_pwndBottomView
))
2159 else if (HasNextConflict(m_pwndRightView
))
2161 else if (HasNextConflict(m_pwndLeftView
))
2163 pCmdUI
->Enable(bShow
);
2166 bool CMainFrame::HasNextConflict(CBaseView
* view
)
2170 if (!view
->IsTarget())
2172 return view
->HasNextConflict();
2175 void CMainFrame::OnUpdateMergePreviousconflict(CCmdUI
*pCmdUI
)
2178 if (HasPrevConflict(m_pwndBottomView
))
2180 else if (HasPrevConflict(m_pwndRightView
))
2182 else if (HasPrevConflict(m_pwndLeftView
))
2184 pCmdUI
->Enable(bShow
);
2187 bool CMainFrame::HasPrevConflict(CBaseView
* view
)
2191 if (!view
->IsTarget())
2193 return view
->HasPrevConflict();
2196 void CMainFrame::OnUpdateNavigateNextdifference(CCmdUI
*pCmdUI
)
2198 CBaseView
* baseView
= GetActiveBaseView();
2201 bShow
= baseView
->HasNextDiff();
2202 pCmdUI
->Enable(bShow
);
2205 void CMainFrame::OnUpdateNavigatePreviousdifference(CCmdUI
*pCmdUI
)
2207 CBaseView
* baseView
= GetActiveBaseView();
2210 bShow
= baseView
->HasPrevDiff();
2211 pCmdUI
->Enable(bShow
);
2214 void CMainFrame::OnUpdateNavigateNextinlinediff(CCmdUI
*pCmdUI
)
2217 if (HasNextInlineDiff(m_pwndBottomView
))
2219 else if (HasNextInlineDiff(m_pwndRightView
))
2221 else if (HasNextInlineDiff(m_pwndLeftView
))
2223 pCmdUI
->Enable(bShow
);
2226 bool CMainFrame::HasNextInlineDiff(CBaseView
* view
)
2230 if (!view
->IsTarget())
2232 return view
->HasNextInlineDiff();
2235 void CMainFrame::OnUpdateNavigatePrevinlinediff(CCmdUI
*pCmdUI
)
2238 if (HasPrevInlineDiff(m_pwndBottomView
))
2240 else if (HasPrevInlineDiff(m_pwndRightView
))
2242 else if (HasPrevInlineDiff(m_pwndLeftView
))
2244 pCmdUI
->Enable(bShow
);
2247 bool CMainFrame::HasPrevInlineDiff(CBaseView
* view
)
2251 if (!view
->IsTarget())
2253 return view
->HasPrevInlineDiff();
2256 void CMainFrame::OnMoving(UINT fwSide
, LPRECT pRect
)
2258 // if the pathfilelist dialog is attached to the mainframe,
2259 // move it along with the mainframe
2260 if (::IsWindow(m_dlgFilePatches
.m_hWnd
))
2263 m_dlgFilePatches
.GetWindowRect(&patchrect
);
2264 if (::IsWindow(m_hWnd
))
2267 GetWindowRect(&thisrect
);
2268 if (patchrect
.right
== thisrect
.left
)
2270 m_dlgFilePatches
.SetWindowPos(NULL
, patchrect
.left
- (thisrect
.left
- pRect
->left
), patchrect
.top
- (thisrect
.top
- pRect
->top
),
2271 0, 0, SWP_NOACTIVATE
| SWP_NOOWNERZORDER
| SWP_NOSIZE
| SWP_NOZORDER
);
2275 __super::OnMoving(fwSide
, pRect
);
2278 void CMainFrame::OnUpdateEditCopy(CCmdUI
*pCmdUI
)
2281 if ((m_pwndBottomView
)&&(m_pwndBottomView
->HasSelection()))
2283 else if ((m_pwndRightView
)&&(m_pwndRightView
->HasSelection()))
2285 else if ((m_pwndLeftView
)&&(m_pwndLeftView
->HasSelection()))
2287 pCmdUI
->Enable(bShow
);
2290 void CMainFrame::OnUpdateEditPaste(CCmdUI
*pCmdUI
)
2292 BOOL bWritable
= FALSE
;
2293 if ((m_pwndBottomView
)&&(m_pwndBottomView
->IsWritable()))
2295 else if ((m_pwndRightView
)&&(m_pwndRightView
->IsWritable()))
2297 else if ((m_pwndLeftView
)&&(m_pwndLeftView
->IsWritable()))
2299 pCmdUI
->Enable(bWritable
&& ::IsClipboardFormatAvailable(CF_TEXT
));
2302 void CMainFrame::OnViewSwitchleft()
2304 if (CheckForSave(CHFSR_SWITCH
)!=IDCANCEL
)
2306 CWorkingFile file
= m_Data
.m_baseFile
;
2307 m_Data
.m_baseFile
= m_Data
.m_yourFile
;
2308 m_Data
.m_yourFile
= file
;
2309 if (m_Data
.m_mergedFile
.GetFilename().CompareNoCase(m_Data
.m_yourFile
.GetFilename())==0)
2311 m_Data
.m_mergedFile
= m_Data
.m_baseFile
;
2313 else if (m_Data
.m_mergedFile
.GetFilename().CompareNoCase(m_Data
.m_baseFile
.GetFilename())==0)
2315 m_Data
.m_mergedFile
= m_Data
.m_yourFile
;
2321 void CMainFrame::OnUpdateViewSwitchleft(CCmdUI
*pCmdUI
)
2323 BOOL bEnable
= !IsViewGood(m_pwndBottomView
);
2324 pCmdUI
->Enable(bEnable
);
2327 void CMainFrame::OnUpdateViewShowfilelist(CCmdUI
*pCmdUI
)
2329 BOOL bEnable
= m_dlgFilePatches
.HasFiles();
2330 pCmdUI
->Enable(bEnable
);
2331 pCmdUI
->SetCheck(m_dlgFilePatches
.IsWindowVisible());
2334 void CMainFrame::OnViewShowfilelist()
2336 m_dlgFilePatches
.ShowWindow(m_dlgFilePatches
.IsWindowVisible() ? SW_HIDE
: SW_SHOW
);
2339 void CMainFrame::OnEditUndo()
2341 if (CUndo::GetInstance().CanUndo())
2343 CUndo::GetInstance().Undo(m_pwndLeftView
, m_pwndRightView
, m_pwndBottomView
);
2347 void CMainFrame::OnUpdateEditUndo(CCmdUI
*pCmdUI
)
2349 pCmdUI
->Enable(CUndo::GetInstance().CanUndo());
2352 void CMainFrame::OnEditRedo()
2354 if (CUndo::GetInstance().CanRedo())
2356 CUndo::GetInstance().Redo(m_pwndLeftView
, m_pwndRightView
, m_pwndBottomView
);
2360 void CMainFrame::OnUpdateEditRedo(CCmdUI
*pCmdUI
)
2362 pCmdUI
->Enable(CUndo::GetInstance().CanRedo());
2365 void CMainFrame::OnEditEnable()
2367 CBaseView
* pView
= GetActiveBaseView();
2368 if (pView
&& pView
->IsReadonlyChangable())
2370 bool isReadOnly
= pView
->IsReadonly();
2371 pView
->SetReadonly(!isReadOnly
);
2375 void CMainFrame::OnUpdateEditEnable(CCmdUI
*pCmdUI
)
2377 CBaseView
* pView
= GetActiveBaseView();
2380 pCmdUI
->Enable(pView
->IsReadonlyChangable() || !pView
->IsReadonly());
2381 pCmdUI
->SetCheck(!pView
->IsReadonly());
2385 pCmdUI
->Enable(FALSE
);
2389 void CMainFrame::OnIndicatorLeftview()
2393 if (IsViewGood(m_pwndLeftView
))
2395 m_pwndLeftView
->AskUserForNewLineEndingsAndTextType(IDS_STATUSBAR_LEFTVIEW
);
2399 void CMainFrame::OnIndicatorRightview()
2403 if (IsViewGood(m_pwndRightView
))
2405 m_pwndRightView
->AskUserForNewLineEndingsAndTextType(IDS_STATUSBAR_RIGHTVIEW
);
2409 void CMainFrame::OnIndicatorBottomview()
2413 if (IsViewGood(m_pwndBottomView
))
2415 m_pwndBottomView
->AskUserForNewLineEndingsAndTextType(IDS_STATUSBAR_BOTTOMVIEW
);
2419 int CMainFrame::CheckForReload()
2421 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
2427 bool bSourceChanged
=
2428 m_Data
.m_baseFile
.HasSourceFileChanged()
2429 || m_Data
.m_yourFile
.HasSourceFileChanged()
2430 || m_Data
.m_theirFile
.HasSourceFileChanged()
2431 /*|| m_Data.m_mergedFile.HasSourceFileChanged()*/;
2432 if (!bSourceChanged
)
2438 CString msg
= HasUnsavedEdits() ? CString(MAKEINTRESOURCE(IDS_WARNMODIFIEDOUTSIDELOOSECHANGES
)) : CString(MAKEINTRESOURCE(IDS_WARNMODIFIEDOUTSIDE
));
2439 CTaskDialog
taskdlg(msg
,
2440 CString(MAKEINTRESOURCE(IDS_WARNMODIFIEDOUTSIDE_TASK2
)),
2441 L
"TortoiseGitMerge",
2443 TDF_ENABLE_HYPERLINKS
| TDF_USE_COMMAND_LINKS
| TDF_ALLOW_DIALOG_CANCELLATION
| TDF_POSITION_RELATIVE_TO_WINDOW
);
2445 if (HasUnsavedEdits())
2446 sTask3
.LoadString(IDS_WARNMODIFIEDOUTSIDE_TASK3
);
2448 sTask3
.LoadString(IDS_WARNMODIFIEDOUTSIDE_TASK4
);
2449 taskdlg
.AddCommandControl(IDYES
, sTask3
);
2450 taskdlg
.AddCommandControl(IDNO
, CString(MAKEINTRESOURCE(IDS_WARNMODIFIEDOUTSIDE_TASK5
)));
2451 taskdlg
.SetCommonButtons(TDCBF_CANCEL_BUTTON
);
2452 taskdlg
.SetDefaultCommandControl(IDYES
);
2453 taskdlg
.SetMainIcon(TD_WARNING_ICON
);
2454 UINT ret
= (UINT
)taskdlg
.DoModal(m_hWnd
);
2457 CDiffColors::GetInstance().LoadRegistry();
2462 if (IsViewGood(m_pwndBottomView
)) // three pane view
2464 /*if (m_Data.m_sourceFile.HasSourceFileChanged())
2465 m_pwndBottomView->SetModified();
2466 if (m_Data.m_mergedFile.HasSourceFileChanged())
2467 m_pwndBottomView->SetModified();//*/
2468 if (m_Data
.m_yourFile
.HasSourceFileChanged())
2469 m_pwndRightView
->SetModified();
2470 if (m_Data
.m_theirFile
.HasSourceFileChanged())
2471 m_pwndLeftView
->SetModified();
2473 else if (IsViewGood(m_pwndRightView
)) // two pane view
2475 if (m_Data
.m_baseFile
.HasSourceFileChanged())
2476 m_pwndLeftView
->SetModified();
2477 if (m_Data
.m_yourFile
.HasSourceFileChanged())
2478 m_pwndRightView
->SetModified();
2482 if (m_Data
.m_yourFile
.HasSourceFileChanged())
2483 m_pwndLeftView
->SetModified();
2486 // no reload just store updated file time
2487 m_Data
.m_baseFile
.StoreFileAttributes();
2488 m_Data
.m_theirFile
.StoreFileAttributes();
2489 m_Data
.m_yourFile
.StoreFileAttributes();
2490 //m_Data.m_mergedFile.StoreFileAttributes();
2496 int CMainFrame::CheckForSave(ECheckForSaveReason eReason
)
2498 int idTitle
= IDS_WARNMODIFIEDLOOSECHANGES
;
2499 int idNoSave
= IDS_ASKFORSAVE_TASK7
;
2500 int idCancelAction
= IDS_ASKFORSAVE_CANCEL_OPEN
;
2504 //idTitle = IDS_WARNMODIFIEDLOOSECHANGES;
2505 idNoSave
= IDS_ASKFORSAVE_TASK4
;
2506 idCancelAction
= IDS_ASKFORSAVE_TASK5
;
2509 //idTitle = IDS_WARNMODIFIEDLOOSECHANGES;
2510 //idNoSave = IDS_ASKFORSAVE_TASK7;
2511 idCancelAction
= IDS_ASKFORSAVE_TASK8
;
2514 //idTitle = IDS_WARNMODIFIEDLOOSECHANGES;
2515 //idNoSave = IDS_ASKFORSAVE_TASK7;
2516 idCancelAction
= IDS_ASKFORSAVE_CANCEL_OPEN
;
2519 idTitle
= IDS_WARNMODIFIEDLOOSECHANGESOPTIONS
;
2520 //idNoSave = IDS_ASKFORSAVE_TASK7;
2521 idCancelAction
= IDS_ASKFORSAVE_CANCEL_OPTIONS
;
2524 //idTitle = IDS_WARNMODIFIEDLOOSECHANGES;
2525 idNoSave
= IDS_ASKFORSAVE_NOSAVE_OPEN
;
2526 idCancelAction
= IDS_ASKFORSAVE_CANCEL_OPEN
;
2530 CString
sTitle(MAKEINTRESOURCE(idTitle
));
2531 CString
sSubTitle(MAKEINTRESOURCE(IDS_ASKFORSAVE_TASK2
));
2532 CString
sNoSave(MAKEINTRESOURCE(idNoSave
));
2533 CString
sCancelAction(MAKEINTRESOURCE(idCancelAction
));
2534 CString
sAppName(MAKEINTRESOURCE(IDS_APPNAME
));
2536 // TODO simplify logic, reduce code duplication
2537 if (CBaseView::IsViewGood(m_pwndBottomView
))
2539 // three-way diff - by design only bottom can be changed
2540 // use 1.7 way to do that
2542 else if (CBaseView::IsViewGood(m_pwndRightView
))
2545 // 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
2546 if (HasUnsavedEdits(m_pwndLeftView
))
2549 CTaskDialog
taskdlg(sTitle
,
2553 TDF_ENABLE_HYPERLINKS
| TDF_USE_COMMAND_LINKS
| TDF_ALLOW_DIALOG_CANCELLATION
| TDF_POSITION_RELATIVE_TO_WINDOW
);
2555 if (m_pwndLeftView
->m_pWorkingFile
->InUse() && !m_pwndLeftView
->m_pWorkingFile
->IsReadonly())
2556 sTaskTemp
.Format(IDS_ASKFORSAVE_SAVELEFT
, (LPCTSTR
)m_pwndLeftView
->m_pWorkingFile
->GetFilename());
2558 sTaskTemp
= CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_SAVELEFTAS
));
2559 taskdlg
.AddCommandControl(201, sTaskTemp
); // left
2560 taskdlg
.SetDefaultCommandControl(201);
2561 if (HasUnsavedEdits(m_pwndRightView
))
2563 if (m_pwndRightView
->m_pWorkingFile
->InUse() && !m_pwndRightView
->m_pWorkingFile
->IsReadonly())
2564 sTaskTemp
.Format(IDS_ASKFORSAVE_SAVERIGHT
, (LPCTSTR
)m_pwndRightView
->m_pWorkingFile
->GetFilename());
2566 sTaskTemp
= CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_SAVERIGHTAS
));
2567 taskdlg
.AddCommandControl(202, sTaskTemp
); // right
2568 taskdlg
.AddCommandControl(203, CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_SAVEALL2
))); // both
2569 taskdlg
.SetDefaultCommandControl(203);
2571 taskdlg
.AddCommandControl(IDNO
, sNoSave
); // none
2572 taskdlg
.AddCommandControl(IDCANCEL
, sCancelAction
); // cancel
2573 taskdlg
.SetCommonButtons(TDCBF_CANCEL_BUTTON
);
2574 taskdlg
.SetMainIcon(TD_WARNING_ICON
);
2575 UINT ret
= (UINT
)taskdlg
.DoModal(m_hWnd
);
2579 m_pwndLeftView
->SaveFile(SAVE_REMOVEDLINES
);
2582 m_pwndLeftView
->SaveFile(SAVE_REMOVEDLINES
);
2584 m_pwndRightView
->SaveFile();
2587 if (ret
!= IDCANCEL
&& (eReason
== CHFSR_CLOSE
|| eReason
== CHFSR_OPEN
))
2588 DeleteBaseTheirsMineOnClose();
2593 // only secondary (left) view
2595 // only right view - 1.7 implementation is used
2597 else if (CBaseView::IsViewGood(m_pwndLeftView
))
2599 // only one view - only one to save
2600 // 1.7 FileSave don't support this mode
2601 if (HasUnsavedEdits(m_pwndLeftView
))
2603 CTaskDialog
taskdlg(sTitle
,
2607 TDF_ENABLE_HYPERLINKS
| TDF_USE_COMMAND_LINKS
| TDF_ALLOW_DIALOG_CANCELLATION
| TDF_POSITION_RELATIVE_TO_WINDOW
);
2609 if (m_Data
.m_mergedFile
.InUse())
2610 sTask3
.Format(IDS_ASKFORSAVE_TASK3
, (LPCTSTR
)m_Data
.m_mergedFile
.GetFilename());
2612 sTask3
.LoadString(IDS_ASKFORSAVE_TASK6
);
2613 taskdlg
.AddCommandControl(IDYES
, sTask3
);
2614 taskdlg
.AddCommandControl(IDNO
, sNoSave
);
2615 taskdlg
.AddCommandControl(IDCANCEL
, sCancelAction
);
2616 taskdlg
.SetCommonButtons(TDCBF_CANCEL_BUTTON
);
2617 taskdlg
.SetDefaultCommandControl(IDYES
);
2618 taskdlg
.SetMainIcon(TD_WARNING_ICON
);
2619 if ((UINT
)taskdlg
.DoModal(m_hWnd
) == IDYES
)
2621 if (m_pwndLeftView
->SaveFile()<0)
2625 if (eReason
== CHFSR_CLOSE
|| eReason
== CHFSR_OPEN
)
2626 DeleteBaseTheirsMineOnClose();
2631 if (eReason
== CHFSR_CLOSE
|| eReason
== CHFSR_OPEN
)
2632 DeleteBaseTheirsMineOnClose();
2633 return IDNO
; // nothing to save
2636 // 1.7 implementation
2638 if (HasUnsavedEdits())
2640 CTaskDialog
taskdlg(sTitle
,
2644 TDF_ENABLE_HYPERLINKS
| TDF_USE_COMMAND_LINKS
| TDF_ALLOW_DIALOG_CANCELLATION
| TDF_POSITION_RELATIVE_TO_WINDOW
);
2646 if (m_Data
.m_mergedFile
.InUse())
2647 sTask3
.Format(IDS_ASKFORSAVE_TASK3
, (LPCTSTR
)m_Data
.m_mergedFile
.GetFilename());
2649 sTask3
.LoadString(IDS_ASKFORSAVE_TASK6
);
2650 taskdlg
.AddCommandControl(IDYES
, sTask3
);
2651 taskdlg
.AddCommandControl(IDNO
, sNoSave
);
2652 taskdlg
.AddCommandControl(IDCANCEL
, sCancelAction
);
2653 taskdlg
.SetCommonButtons(TDCBF_CANCEL_BUTTON
);
2654 taskdlg
.SetDefaultCommandControl(IDYES
);
2655 taskdlg
.SetMainIcon(TD_WARNING_ICON
);
2656 ret
= (UINT
)taskdlg
.DoModal(m_hWnd
);
2665 if (ret
!= IDCANCEL
&& (eReason
== CHFSR_CLOSE
|| eReason
== CHFSR_OPEN
))
2666 DeleteBaseTheirsMineOnClose();
2671 void CMainFrame::DeleteBaseTheirsMineOnClose()
2673 if (!m_bDeleteBaseTheirsMineOnClose
)
2676 m_bDeleteBaseTheirsMineOnClose
= false;
2678 DeleteFile(m_Data
.m_baseFile
.GetFilename());
2679 DeleteFile(m_Data
.m_theirFile
.GetFilename());
2680 DeleteFile(m_Data
.m_yourFile
.GetFilename());
2683 bool CMainFrame::HasUnsavedEdits() const
2685 return HasUnsavedEdits(m_pwndBottomView
) || HasUnsavedEdits(m_pwndRightView
) || m_bSaveRequired
;
2688 bool CMainFrame::HasUnsavedEdits(const CBaseView
* view
)
2690 if (!CBaseView::IsViewGood(view
))
2692 return view
->IsModified();
2695 bool CMainFrame::HasMarkedBlocks() const
2697 return CBaseView::IsViewGood(m_pwndRightView
) && m_pwndRightView
->HasMarkedBlocks();
2700 bool CMainFrame::IsViewGood(const CBaseView
* view
)
2702 return CBaseView::IsViewGood(view
);
2705 void CMainFrame::OnViewInlinediffword()
2707 m_bInlineWordDiff
= !m_bInlineWordDiff
;
2710 m_pwndLeftView
->SetInlineWordDiff(m_bInlineWordDiff
);
2711 m_pwndLeftView
->BuildAllScreen2ViewVector();
2712 m_pwndLeftView
->DocumentUpdated();
2714 if (m_pwndRightView
)
2716 m_pwndRightView
->SetInlineWordDiff(m_bInlineWordDiff
);
2717 m_pwndRightView
->BuildAllScreen2ViewVector();
2718 m_pwndRightView
->DocumentUpdated();
2720 if (m_pwndBottomView
)
2722 m_pwndBottomView
->SetInlineWordDiff(m_bInlineWordDiff
);
2723 m_pwndBottomView
->BuildAllScreen2ViewVector();
2724 m_pwndBottomView
->DocumentUpdated();
2726 m_wndLineDiffBar
.DocumentUpdated();
2729 void CMainFrame::OnUpdateViewInlinediffword(CCmdUI
*pCmdUI
)
2731 pCmdUI
->Enable(m_bInlineDiff
&& IsViewGood(m_pwndLeftView
) && IsViewGood(m_pwndRightView
));
2732 pCmdUI
->SetCheck(m_bInlineWordDiff
);
2735 void CMainFrame::OnViewInlinediff()
2737 m_bInlineDiff
= !m_bInlineDiff
;
2740 m_pwndLeftView
->SetInlineDiff(m_bInlineDiff
);
2741 m_pwndLeftView
->BuildAllScreen2ViewVector();
2742 m_pwndLeftView
->DocumentUpdated();
2744 if (m_pwndRightView
)
2746 m_pwndRightView
->SetInlineDiff(m_bInlineDiff
);
2747 m_pwndRightView
->BuildAllScreen2ViewVector();
2748 m_pwndRightView
->DocumentUpdated();
2750 if (m_pwndBottomView
)
2752 m_pwndBottomView
->SetInlineDiff(m_bInlineDiff
);
2753 m_pwndBottomView
->BuildAllScreen2ViewVector();
2754 m_pwndBottomView
->DocumentUpdated();
2756 m_wndLineDiffBar
.DocumentUpdated();
2759 void CMainFrame::OnUpdateViewInlinediff(CCmdUI
*pCmdUI
)
2761 pCmdUI
->Enable(IsViewGood(m_pwndLeftView
) && IsViewGood(m_pwndRightView
));
2762 pCmdUI
->SetCheck(m_bInlineDiff
);
2765 void CMainFrame::OnUpdateEditCreateunifieddifffile(CCmdUI
*pCmdUI
)
2767 // "create unified diff file" is only available if two files
2768 // are diffed, not three.
2769 bool bEnabled
= true;
2770 if (!IsViewGood(m_pwndLeftView
))
2772 else if (!IsViewGood(m_pwndRightView
))
2774 else if (IsViewGood(m_pwndBottomView
)) //no negation here
2776 pCmdUI
->Enable(bEnabled
);
2779 void CMainFrame::OnEditCreateunifieddifffile()
2781 CString origFile
, modifiedFile
;
2782 // the original file is the one on the left
2784 origFile
= m_pwndLeftView
->m_sFullFilePath
;
2785 if (m_pwndRightView
)
2786 modifiedFile
= m_pwndRightView
->m_sFullFilePath
;
2787 if (origFile
.IsEmpty() || modifiedFile
.IsEmpty())
2791 if(!TryGetFileName(outputFile
))
2794 CRegStdDWORD
regContextLines(L
"Software\\TortoiseGitMerge\\ContextLines", (DWORD
)-1);
2795 CAppUtils::CreateUnifiedDiff(origFile
, modifiedFile
, outputFile
, regContextLines
, true);
2798 void CMainFrame::OnUpdateViewLinediffbar(CCmdUI
*pCmdUI
)
2800 pCmdUI
->SetCheck(m_bLineDiff
);
2804 void CMainFrame::OnViewLinediffbar()
2806 m_bLineDiff
= !m_bLineDiff
;
2807 m_wndLineDiffBar
.ShowPane(m_bLineDiff
, false, true);
2808 m_wndLineDiffBar
.DocumentUpdated();
2809 m_wndLocatorBar
.ShowPane(m_bLocatorBar
, false, true);
2810 m_wndLocatorBar
.DocumentUpdated();
2813 void CMainFrame::OnUpdateViewLocatorbar(CCmdUI
*pCmdUI
)
2815 pCmdUI
->SetCheck(m_bLocatorBar
);
2819 void CMainFrame::OnUpdateViewBars(CCmdUI
* pCmdUI
)
2824 void CMainFrame::OnViewLocatorbar()
2826 m_bLocatorBar
= !m_bLocatorBar
;
2827 m_wndLocatorBar
.ShowPane(m_bLocatorBar
, false, true);
2828 m_wndLocatorBar
.DocumentUpdated();
2829 m_wndLineDiffBar
.ShowPane(m_bLineDiff
, false, true);
2830 m_wndLineDiffBar
.DocumentUpdated();
2833 void CMainFrame::OnViewComparewhitespaces()
2835 if (CheckForSave(CHFSR_OPTIONS
)==IDCANCEL
)
2837 CRegDWORD
regIgnoreWS(L
"Software\\TortoiseGitMerge\\IgnoreWS");
2842 void CMainFrame::OnUpdateViewComparewhitespaces(CCmdUI
*pCmdUI
)
2844 CRegDWORD
regIgnoreWS(L
"Software\\TortoiseGitMerge\\IgnoreWS");
2845 DWORD dwIgnoreWS
= regIgnoreWS
;
2846 pCmdUI
->SetCheck(dwIgnoreWS
== 0);
2849 void CMainFrame::OnViewIgnorewhitespacechanges()
2851 if (CheckForSave(CHFSR_OPTIONS
)==IDCANCEL
)
2853 CRegDWORD
regIgnoreWS(L
"Software\\TortoiseGitMerge\\IgnoreWS");
2858 void CMainFrame::OnUpdateViewIgnorewhitespacechanges(CCmdUI
*pCmdUI
)
2860 CRegDWORD
regIgnoreWS(L
"Software\\TortoiseGitMerge\\IgnoreWS");
2861 DWORD dwIgnoreWS
= regIgnoreWS
;
2862 pCmdUI
->SetCheck(dwIgnoreWS
== 2);
2865 void CMainFrame::OnViewIgnoreallwhitespacechanges()
2867 if (CheckForSave(CHFSR_OPTIONS
)==IDCANCEL
)
2869 CRegDWORD
regIgnoreWS(L
"Software\\TortoiseGitMerge\\IgnoreWS");
2874 void CMainFrame::OnUpdateViewIgnoreallwhitespacechanges(CCmdUI
*pCmdUI
)
2876 CRegDWORD
regIgnoreWS(L
"Software\\TortoiseGitMerge\\IgnoreWS");
2877 DWORD dwIgnoreWS
= regIgnoreWS
;
2878 pCmdUI
->SetCheck(dwIgnoreWS
== 1);
2881 void CMainFrame::OnViewMovedBlocks()
2883 m_bViewMovedBlocks
= !(DWORD
)m_regViewModedBlocks
;
2884 m_regViewModedBlocks
= m_bViewMovedBlocks
;
2888 void CMainFrame::OnUpdateViewMovedBlocks(CCmdUI
*pCmdUI
)
2890 pCmdUI
->SetCheck(m_bViewMovedBlocks
);
2891 BOOL bEnable
= TRUE
;
2892 if (IsViewGood(m_pwndBottomView
))
2896 pCmdUI
->Enable(bEnable
);
2899 bool CMainFrame::HasConflictsWontKeep()
2901 const int nConflictLine
= CheckResolved();
2902 if (nConflictLine
< 0)
2904 if (m_pwndBottomView
== nullptr)
2908 sTemp
.Format(IDS_ERR_MAINFRAME_FILEHASCONFLICTS
, m_pwndBottomView
->m_pViewData
->GetLineNumber(nConflictLine
)+1);
2909 CTaskDialog
taskdlg(sTemp
,
2910 CString(MAKEINTRESOURCE(IDS_ERR_MAINFRAME_FILEHASCONFLICTS_TASK2
)),
2911 L
"TortoiseGitMerge",
2913 TDF_ENABLE_HYPERLINKS
| TDF_USE_COMMAND_LINKS
| TDF_ALLOW_DIALOG_CANCELLATION
| TDF_POSITION_RELATIVE_TO_WINDOW
);
2914 taskdlg
.AddCommandControl(1, CString(MAKEINTRESOURCE(IDS_ERR_MAINFRAME_FILEHASCONFLICTS_TASK3
)));
2915 taskdlg
.AddCommandControl(2, CString(MAKEINTRESOURCE(IDS_ERR_MAINFRAME_FILEHASCONFLICTS_TASK4
)));
2916 taskdlg
.SetCommonButtons(TDCBF_CANCEL_BUTTON
);
2917 taskdlg
.SetDefaultCommandControl(2);
2918 taskdlg
.SetMainIcon(TD_ERROR_ICON
);
2919 if (taskdlg
.DoModal(m_hWnd
) == 1)
2922 m_pwndBottomView
->GoToLine(nConflictLine
);
2926 bool CMainFrame::TryGetFileName(CString
& result
)
2928 return CCommonAppUtils::FileOpenSave(result
, NULL
, IDS_SAVEASTITLE
, IDS_COMMONFILEFILTER
, false, m_hWnd
);
2931 CBaseView
* CMainFrame::GetActiveBaseView() const
2933 CView
* activeView
= GetActiveView();
2934 CBaseView
* activeBase
= dynamic_cast<CBaseView
*>( activeView
);
2938 void CMainFrame::SetWindowTitle()
2940 // try to find a suitable window title
2941 CString sYour
= m_Data
.m_yourFile
.GetDescriptiveName();
2942 if (sYour
.Find(_T(" - "))>=0)
2943 sYour
= sYour
.Left(sYour
.Find(_T(" - ")));
2944 if (sYour
.Find(_T(" : "))>=0)
2945 sYour
= sYour
.Left(sYour
.Find(_T(" : ")));
2946 CString sTheir
= m_Data
.m_theirFile
.GetDescriptiveName();
2947 if (sTheir
.IsEmpty())
2948 sTheir
= m_Data
.m_baseFile
.GetDescriptiveName();
2949 if (sTheir
.Find(_T(" - "))>=0)
2950 sTheir
= sTheir
.Left(sTheir
.Find(_T(" - ")));
2951 if (sTheir
.Find(_T(" : "))>=0)
2952 sTheir
= sTheir
.Left(sTheir
.Find(_T(" : ")));
2954 if (!sYour
.IsEmpty() && !sTheir
.IsEmpty())
2956 if (sYour
.CompareNoCase(sTheir
)==0)
2957 SetWindowText(sYour
+ _T(" - TortoiseGitMerge"));
2958 else if ((sYour
.GetLength() < 10) &&
2959 (sTheir
.GetLength() < 10))
2960 SetWindowText(sYour
+ _T(" - ") + sTheir
+ _T(" - TortoiseGitMerge"));
2963 // we have two very long descriptive texts here, which
2964 // means we have to find a way to use them as a window
2965 // title in a shorter way.
2966 // for simplicity, we just use the one from "yourfile"
2967 SetWindowText(sYour
+ _T(" - TortoiseGitMerge"));
2970 else if (!sYour
.IsEmpty())
2971 SetWindowText(sYour
+ _T(" - TortoiseGitMerge"));
2972 else if (!sTheir
.IsEmpty())
2973 SetWindowText(sTheir
+ _T(" - TortoiseGitMerge"));
2975 SetWindowText(L
"TortoiseGitMerge");
2978 void CMainFrame::OnTimer(UINT_PTR nIDEvent
)
2982 case IDT_RELOADCHECKTIMER
:
2983 KillTimer(nIDEvent
);
2988 __super::OnTimer(nIDEvent
);
2991 void CMainFrame::LoadIgnoreCommentData()
2993 static bool bLoaded
= false;
2996 CString sPath
= CPathUtils::GetAppDataDirectory() + L
"ignorecomments.txt";
2997 if (!PathFileExists(sPath
))
2999 // ignore comments file does not exist (yet), so create a default one
3000 HRSRC hRes
= FindResource(NULL
, MAKEINTRESOURCE(IDR_IGNORECOMMENTSTXT
), L
"config");
3003 HGLOBAL hResourceLoaded
= LoadResource(NULL
, hRes
);
3004 if (hResourceLoaded
)
3006 char * lpResLock
= (char *) LockResource(hResourceLoaded
);
3007 DWORD dwSizeRes
= SizeofResource(NULL
, hRes
);
3010 HANDLE hFile
= CreateFile(sPath
, GENERIC_WRITE
, 0, nullptr, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, nullptr);
3011 if (hFile
!= INVALID_HANDLE_VALUE
)
3013 DWORD dwWritten
= 0;
3014 WriteFile(hFile
, lpResLock
, dwSizeRes
, &dwWritten
, NULL
);
3025 if (file
.Open(sPath
, CFile::modeRead
))
3028 while (file
.ReadString(sLine
))
3030 int eqpos
= sLine
.Find('=');
3033 CString sExts
= sLine
.Left(eqpos
);
3034 CString sComments
= sLine
.Mid(eqpos
+1);
3036 int pos
= sComments
.Find(',');
3037 CString sLineStart
= sComments
.Left(pos
);
3038 pos
= sComments
.Find(',', pos
);
3039 int pos2
= sComments
.Find(',', pos
+1);
3040 CString sBlockStart
= sComments
.Mid(pos
+1, pos2
-pos
-1);
3041 CString sBlockEnd
= sComments
.Mid(pos2
+1);
3043 auto commentTuple
= std::make_tuple(sLineStart
, sBlockStart
, sBlockEnd
);
3049 temp
= sExts
.Tokenize(_T(","),pos
);
3054 ASSERT(m_IgnoreCommentsMap
.find(temp
) == m_IgnoreCommentsMap
.end());
3055 m_IgnoreCommentsMap
[temp
] = commentTuple
;
3061 catch (CFileException
* e
)
3068 void CMainFrame::OnViewIgnorecomments()
3070 if (CheckForSave(CHFSR_OPTIONS
)==IDCANCEL
)
3072 m_regIgnoreComments
= !DWORD(m_regIgnoreComments
);
3076 void CMainFrame::OnUpdateViewIgnorecomments(CCmdUI
*pCmdUI
)
3078 // only enable if we have comments defined for this file extension
3079 CString sExt
= CPathUtils::GetFileExtFromPath(m_Data
.m_baseFile
.GetFilename()).MakeLower();
3080 sExt
.TrimLeft(L
".");
3081 auto sC
= m_IgnoreCommentsMap
.find(sExt
);
3082 if (sC
== m_IgnoreCommentsMap
.end())
3084 sExt
= CPathUtils::GetFileExtFromPath(m_Data
.m_yourFile
.GetFilename()).MakeLower();
3085 sExt
.TrimLeft(L
".");
3086 sC
= m_IgnoreCommentsMap
.find(sExt
);
3087 if (sC
== m_IgnoreCommentsMap
.end())
3089 sExt
= CPathUtils::GetFileExtFromPath(m_Data
.m_theirFile
.GetFilename()).MakeLower();
3090 sExt
.TrimLeft(L
".");
3091 sC
= m_IgnoreCommentsMap
.find(sExt
);
3094 pCmdUI
->Enable(sC
!= m_IgnoreCommentsMap
.end());
3096 pCmdUI
->SetCheck(DWORD(m_regIgnoreComments
) != 0);
3100 void CMainFrame::OnRegexfilter(UINT cmd
)
3102 if ((cmd
== ID_REGEXFILTER
)||(cmd
== (ID_REGEXFILTER
+1)))
3104 CRegexFiltersDlg
dlg(this);
3105 dlg
.SetIniFile(&m_regexIni
);
3106 if (dlg
.DoModal() == IDOK
)
3108 FILE * pFile
= NULL
;
3109 _tfopen_s(&pFile
, CPathUtils::GetAppDataDirectory() + L
"regexfilters.ini", _T("wb"));
3110 m_regexIni
.SaveFile(pFile
);
3113 BuildRegexSubitems();
3117 if (cmd
== (UINT
)m_regexIndex
)
3119 if (CheckForSave(CHFSR_OPTIONS
)==IDCANCEL
)
3121 m_Data
.SetRegexTokens(std::wregex(), L
"");
3127 CSimpleIni::TNamesDepend sections
;
3128 m_regexIni
.GetAllSections(sections
);
3129 int index
= ID_REGEXFILTER
+ 2;
3131 for (const auto& section
: sections
)
3133 if (cmd
== (UINT
)index
)
3135 if (CheckForSave(CHFSR_OPTIONS
)==IDCANCEL
)
3139 std::wregex
rx(m_regexIni
.GetValue(section
, L
"regex", L
""));
3140 m_Data
.SetRegexTokens(rx
, m_regexIni
.GetValue(section
, L
"replace", L
""));
3142 catch (std::exception
&ex
)
3144 MessageBox(_T("Regex is invalid!\r\n") + CString(ex
.what()));
3146 m_regexIndex
= index
;
3156 void CMainFrame::OnUpdateViewRegexFilter( CCmdUI
*pCmdUI
)
3159 pCmdUI
->SetCheck(pCmdUI
->m_nID
== (UINT
)m_regexIndex
);
3162 void CMainFrame::BuildRegexSubitems(CMFCPopupMenu
* pMenuPopup
)
3164 CString sIniPath
= CPathUtils::GetAppDataDirectory() + L
"regexfilters.ini";
3165 if (!PathFileExists(sIniPath
))
3167 // ini file does not exist (yet), so create a default one
3168 HRSRC hRes
= FindResource(NULL
, MAKEINTRESOURCE(IDR_REGEXFILTERINI
), L
"config");
3171 HGLOBAL hResourceLoaded
= LoadResource(NULL
, hRes
);
3172 if (hResourceLoaded
)
3174 char * lpResLock
= (char *)LockResource(hResourceLoaded
);
3175 DWORD dwSizeRes
= SizeofResource(NULL
, hRes
);
3178 HANDLE hFile
= CreateFile(sIniPath
, GENERIC_WRITE
, 0, nullptr, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, nullptr);
3179 if (hFile
!= INVALID_HANDLE_VALUE
)
3181 DWORD dwWritten
= 0;
3182 WriteFile(hFile
, lpResLock
, dwSizeRes
, &dwWritten
, NULL
);
3190 m_regexIni
.LoadFile(sIniPath
);
3191 CSimpleIni::TNamesDepend sections
;
3192 m_regexIni
.GetAllSections(sections
);
3196 CArray
<CMFCRibbonBaseElement
*, CMFCRibbonBaseElement
*> arButtons
;
3197 m_wndRibbonBar
.GetElementsByID(ID_REGEXFILTER
, arButtons
);
3198 if (arButtons
.GetCount() == 1)
3200 CMFCRibbonButton
* pButton
= (CMFCRibbonButton
*)arButtons
.GetAt(0);
3203 pButton
->RemoveAllSubItems();
3204 pButton
->AddSubItem(new CMFCRibbonButton(ID_REGEXFILTER
+ 1, CString(MAKEINTRESOURCE(IDS_CONFIGUREREGEXES
)), 47, 47));
3206 if (!sections
.empty())
3207 pButton
->AddSubItem(new CMFCRibbonSeparator(TRUE
));
3209 for (const auto& section
: sections
)
3211 pButton
->AddSubItem(new CMFCRibbonButton(ID_REGEXFILTER
+ cmdIndex
, section
, 46, 46));
3217 else if (pMenuPopup
)
3220 if (!CMFCToolBar::IsCustomizeMode() &&
3221 (iIndex
= pMenuPopup
->GetMenuBar()->CommandToIndex(ID_REGEXFILTER
)) >= 0)
3223 if (!sections
.empty())
3224 pMenuPopup
->InsertSeparator(iIndex
+ 1); // insert the separator at the end
3226 for (const auto& section
: sections
)
3228 pMenuPopup
->InsertItem(CMFCToolBarMenuButton(ID_REGEXFILTER
+ cmdIndex
, NULL
, -1, (LPCWSTR
)section
), iIndex
+ cmdIndex
);
3235 void CMainFrame::FillEncodingButton( CMFCRibbonButton
* pButton
, int start
)
3237 pButton
->SetDefaultCommand(FALSE
);
3238 pButton
->AddSubItem(new CMFCRibbonButton(start
+ CFileTextLines::UnicodeType::ASCII
, L
"ASCII" ));
3239 pButton
->AddSubItem(new CMFCRibbonButton(start
+ CFileTextLines::UnicodeType::BINARY
, L
"BINARY" ));
3240 pButton
->AddSubItem(new CMFCRibbonButton(start
+ CFileTextLines::UnicodeType::UTF16_LE
, L
"UTF-16LE" ));
3241 pButton
->AddSubItem(new CMFCRibbonButton(start
+ CFileTextLines::UnicodeType::UTF16_LEBOM
, L
"UTF-16LE BOM"));
3242 pButton
->AddSubItem(new CMFCRibbonButton(start
+ CFileTextLines::UnicodeType::UTF16_BE
, L
"UTF-16BE" ));
3243 pButton
->AddSubItem(new CMFCRibbonButton(start
+ CFileTextLines::UnicodeType::UTF16_BEBOM
, L
"UTF-16BE BOM"));
3244 pButton
->AddSubItem(new CMFCRibbonButton(start
+ CFileTextLines::UnicodeType::UTF32_LE
, L
"UTF-32LE" ));
3245 pButton
->AddSubItem(new CMFCRibbonButton(start
+ CFileTextLines::UnicodeType::UTF32_BE
, L
"UTF-32BE" ));
3246 pButton
->AddSubItem(new CMFCRibbonButton(start
+ CFileTextLines::UnicodeType::UTF8
, L
"UTF-8" ));
3247 pButton
->AddSubItem(new CMFCRibbonButton(start
+ CFileTextLines::UnicodeType::UTF8BOM
, L
"UTF-8 BOM" ));
3250 void CMainFrame::FillEOLButton( CMFCRibbonButton
* pButton
, int start
)
3252 pButton
->SetDefaultCommand(FALSE
);
3253 pButton
->AddSubItem(new CMFCRibbonButton(start
+ EOL::EOL_LF
, L
"LF" ));
3254 pButton
->AddSubItem(new CMFCRibbonButton(start
+ EOL::EOL_CRLF
, L
"CRLF"));
3255 pButton
->AddSubItem(new CMFCRibbonButton(start
+ EOL::EOL_LFCR
, L
"LRCR"));
3256 pButton
->AddSubItem(new CMFCRibbonButton(start
+ EOL::EOL_CR
, L
"CR" ));
3257 pButton
->AddSubItem(new CMFCRibbonButton(start
+ EOL::EOL_VT
, L
"VT" ));
3258 pButton
->AddSubItem(new CMFCRibbonButton(start
+ EOL::EOL_FF
, L
"FF" ));
3259 pButton
->AddSubItem(new CMFCRibbonButton(start
+ EOL::EOL_NEL
, L
"NEL" ));
3260 pButton
->AddSubItem(new CMFCRibbonButton(start
+ EOL::EOL_LS
, L
"LS" ));
3261 pButton
->AddSubItem(new CMFCRibbonButton(start
+ EOL::EOL_PS
, L
"PS" ));
3264 void CMainFrame::FillTabModeButton(CMFCRibbonButton
* pButton
, int start
)
3266 pButton
->SetDefaultCommand(FALSE
);
3267 pButton
->AddSubItem(new CMFCRibbonButton(start
+ TABMODE_NONE
, L
"Tab"));
3268 pButton
->AddSubItem(new CMFCRibbonButton(start
+ TABMODE_USESPACES
, L
"Space"));
3269 pButton
->AddSubItem(new CMFCRibbonSeparator(TRUE
));
3270 pButton
->AddSubItem(new CMFCRibbonButton(start
+ TABMODE_SMARTINDENT
, L
"Smart tab char"));
3271 pButton
->AddSubItem(new CMFCRibbonSeparator(TRUE
));
3272 pButton
->AddSubItem(new CMFCRibbonButton(start
+ TABSIZEBUTTON1
, L
"1"));
3273 pButton
->AddSubItem(new CMFCRibbonButton(start
+ TABSIZEBUTTON2
, L
"2"));
3274 pButton
->AddSubItem(new CMFCRibbonButton(start
+ TABSIZEBUTTON4
, L
"4"));
3275 pButton
->AddSubItem(new CMFCRibbonButton(start
+ TABSIZEBUTTON8
, L
"8"));
3276 pButton
->AddSubItem(new CMFCRibbonSeparator(TRUE
));
3277 pButton
->AddSubItem(new CMFCRibbonButton(start
+ ENABLEEDITORCONFIG
, L
"EditorConfig"));
3280 bool CMainFrame::AdjustUnicodeTypeForLoad(CFileTextLines::UnicodeType
& type
)
3284 case CFileTextLines::UnicodeType::AUTOTYPE
:
3285 case CFileTextLines::UnicodeType::BINARY
:
3288 case CFileTextLines::UnicodeType::ASCII
:
3289 case CFileTextLines::UnicodeType::UTF16_LE
:
3290 case CFileTextLines::UnicodeType::UTF16_BE
:
3291 case CFileTextLines::UnicodeType::UTF32_LE
:
3292 case CFileTextLines::UnicodeType::UTF32_BE
:
3293 case CFileTextLines::UnicodeType::UTF8
:
3296 case CFileTextLines::UnicodeType::UTF16_LEBOM
:
3297 type
= CFileTextLines::UnicodeType::UTF16_LE
;
3300 case CFileTextLines::UnicodeType::UTF16_BEBOM
:
3301 type
= CFileTextLines::UnicodeType::UTF16_BE
;
3304 case CFileTextLines::UnicodeType::UTF8BOM
:
3305 type
= CFileTextLines::UnicodeType::UTF8
;
3311 void CMainFrame::OnEncodingLeft( UINT cmd
)
3315 if (GetKeyState(VK_CONTROL
) & 0x8000)
3317 // reload with selected encoding
3318 auto saveparams
= m_Data
.m_arBaseFile
.GetSaveParams();
3319 saveparams
.m_UnicodeType
= CFileTextLines::UnicodeType(cmd
- ID_INDICATOR_LEFTENCODINGSTART
);
3320 if (AdjustUnicodeTypeForLoad(saveparams
.m_UnicodeType
))
3322 m_Data
.m_arBaseFile
.SetSaveParams(saveparams
);
3323 m_Data
.m_arBaseFile
.KeepEncoding();
3329 m_pwndLeftView
->SetTextType(CFileTextLines::UnicodeType(cmd
- ID_INDICATOR_LEFTENCODINGSTART
));
3330 m_pwndLeftView
->RefreshViews();
3335 void CMainFrame::OnEncodingRight( UINT cmd
)
3337 if (m_pwndRightView
)
3339 if (GetKeyState(VK_CONTROL
) & 0x8000)
3341 // reload with selected encoding
3342 auto saveparams
= m_Data
.m_arYourFile
.GetSaveParams();
3343 saveparams
.m_UnicodeType
= CFileTextLines::UnicodeType(cmd
- ID_INDICATOR_RIGHTENCODINGSTART
);
3344 if (AdjustUnicodeTypeForLoad(saveparams
.m_UnicodeType
))
3346 m_Data
.m_arYourFile
.SetSaveParams(saveparams
);
3347 m_Data
.m_arYourFile
.KeepEncoding();
3353 m_pwndRightView
->SetTextType(CFileTextLines::UnicodeType(cmd
- ID_INDICATOR_RIGHTENCODINGSTART
));
3354 m_pwndRightView
->RefreshViews();
3359 void CMainFrame::OnEncodingBottom( UINT cmd
)
3361 if (m_pwndBottomView
)
3363 if (GetKeyState(VK_CONTROL
) & 0x8000)
3365 // reload with selected encoding
3366 auto saveparams
= m_Data
.m_arTheirFile
.GetSaveParams();
3367 saveparams
.m_UnicodeType
= CFileTextLines::UnicodeType(cmd
- ID_INDICATOR_BOTTOMENCODINGSTART
);
3368 if (AdjustUnicodeTypeForLoad(saveparams
.m_UnicodeType
))
3370 m_Data
.m_arTheirFile
.SetSaveParams(saveparams
);
3371 m_Data
.m_arTheirFile
.KeepEncoding();
3377 m_pwndBottomView
->SetTextType(CFileTextLines::UnicodeType(cmd
- ID_INDICATOR_BOTTOMENCODINGSTART
));
3378 m_pwndBottomView
->RefreshViews();
3383 void CMainFrame::OnEOLLeft( UINT cmd
)
3387 m_pwndLeftView
->ReplaceLineEndings(EOL(cmd
-ID_INDICATOR_LEFTEOLSTART
));
3388 m_pwndLeftView
->RefreshViews();
3392 void CMainFrame::OnEOLRight( UINT cmd
)
3394 if (m_pwndRightView
)
3396 m_pwndRightView
->ReplaceLineEndings(EOL(cmd
-ID_INDICATOR_RIGHTEOLSTART
));
3397 m_pwndRightView
->RefreshViews();
3401 void CMainFrame::OnEOLBottom( UINT cmd
)
3403 if (m_pwndBottomView
)
3405 m_pwndBottomView
->ReplaceLineEndings(EOL(cmd
-ID_INDICATOR_BOTTOMEOLSTART
));
3406 m_pwndBottomView
->RefreshViews();
3410 void CMainFrame::OnTabModeLeft( UINT cmd
)
3412 OnTabMode(m_pwndLeftView
, (int)cmd
- ID_INDICATOR_LEFTTABMODESTART
);
3415 void CMainFrame::OnTabModeRight( UINT cmd
)
3417 OnTabMode(m_pwndRightView
, (int)cmd
- ID_INDICATOR_RIGHTTABMODESTART
);
3420 void CMainFrame::OnTabModeBottom( UINT cmd
)
3422 OnTabMode(m_pwndBottomView
, (int)cmd
- ID_INDICATOR_BOTTOMTABMODESTART
);
3425 void CMainFrame::OnTabMode(CBaseView
*view
, int cmd
)
3429 int nTabMode
= view
->GetTabMode();
3430 if (cmd
== TABMODE_NONE
|| cmd
== TABMODE_USESPACES
)
3431 view
->SetTabMode((nTabMode
& (~TABMODE_USESPACES
)) | (cmd
& TABMODE_USESPACES
));
3432 else if (cmd
== TABMODE_SMARTINDENT
) // Toggle
3433 view
->SetTabMode((nTabMode
& (~TABMODE_SMARTINDENT
)) | ((nTabMode
& TABMODE_SMARTINDENT
) ? 0 : TABMODE_SMARTINDENT
));
3434 else if (cmd
== TABSIZEBUTTON1
)
3435 view
->SetTabSize(1);
3436 else if (cmd
== TABSIZEBUTTON2
)
3437 view
->SetTabSize(2);
3438 else if (cmd
== TABSIZEBUTTON4
)
3439 view
->SetTabSize(4);
3440 else if (cmd
== TABSIZEBUTTON8
)
3441 view
->SetTabSize(8);
3442 else if (cmd
== ENABLEEDITORCONFIG
)
3443 view
->SetEditorConfigEnabled(!view
->GetEditorConfigEnabled());
3444 view
->RefreshViews();
3447 void CMainFrame::OnUpdateEncodingLeft( CCmdUI
*pCmdUI
)
3451 pCmdUI
->SetCheck(CFileTextLines::UnicodeType(pCmdUI
->m_nID
- ID_INDICATOR_LEFTENCODINGSTART
) == m_pwndLeftView
->GetTextType());
3452 pCmdUI
->Enable(m_pwndLeftView
->IsWritable() || (GetKeyState(VK_CONTROL
)&0x8000));
3455 pCmdUI
->Enable(FALSE
);
3458 void CMainFrame::OnUpdateEncodingRight( CCmdUI
*pCmdUI
)
3460 if (m_pwndRightView
)
3462 pCmdUI
->SetCheck(CFileTextLines::UnicodeType(pCmdUI
->m_nID
- ID_INDICATOR_RIGHTENCODINGSTART
) == m_pwndRightView
->GetTextType());
3463 pCmdUI
->Enable(m_pwndRightView
->IsWritable() || (GetKeyState(VK_CONTROL
) & 0x8000));
3466 pCmdUI
->Enable(FALSE
);
3469 void CMainFrame::OnUpdateEncodingBottom( CCmdUI
*pCmdUI
)
3471 if (m_pwndBottomView
)
3473 pCmdUI
->SetCheck(CFileTextLines::UnicodeType(pCmdUI
->m_nID
- ID_INDICATOR_BOTTOMENCODINGSTART
) == m_pwndBottomView
->GetTextType());
3474 pCmdUI
->Enable(m_pwndBottomView
->IsWritable() || (GetKeyState(VK_CONTROL
) & 0x8000));
3477 pCmdUI
->Enable(FALSE
);
3480 void CMainFrame::OnUpdateEOLLeft( CCmdUI
*pCmdUI
)
3484 pCmdUI
->SetCheck(EOL(pCmdUI
->m_nID
- ID_INDICATOR_LEFTEOLSTART
) == m_pwndLeftView
->GetLineEndings());
3485 pCmdUI
->Enable(m_pwndLeftView
->IsWritable());
3488 pCmdUI
->Enable(FALSE
);
3491 void CMainFrame::OnUpdateEOLRight( CCmdUI
*pCmdUI
)
3493 if (m_pwndRightView
)
3495 pCmdUI
->SetCheck(EOL(pCmdUI
->m_nID
- ID_INDICATOR_RIGHTEOLSTART
) == m_pwndRightView
->GetLineEndings());
3496 pCmdUI
->Enable(m_pwndRightView
->IsWritable());
3499 pCmdUI
->Enable(FALSE
);
3502 void CMainFrame::OnUpdateEOLBottom( CCmdUI
*pCmdUI
)
3504 if (m_pwndBottomView
)
3506 pCmdUI
->SetCheck(EOL(pCmdUI
->m_nID
- ID_INDICATOR_BOTTOMEOLSTART
) == m_pwndBottomView
->GetLineEndings());
3507 pCmdUI
->Enable(m_pwndBottomView
->IsWritable());
3510 pCmdUI
->Enable(FALSE
);
3513 void CMainFrame::OnUpdateTabModeLeft(CCmdUI
*pCmdUI
)
3515 OnUpdateTabMode(m_pwndLeftView
, pCmdUI
, ID_INDICATOR_LEFTTABMODESTART
);
3518 void CMainFrame::OnUpdateTabModeRight(CCmdUI
*pCmdUI
)
3520 OnUpdateTabMode(m_pwndRightView
, pCmdUI
, ID_INDICATOR_RIGHTTABMODESTART
);
3523 void CMainFrame::OnUpdateTabModeBottom(CCmdUI
*pCmdUI
)
3525 OnUpdateTabMode(m_pwndBottomView
, pCmdUI
, ID_INDICATOR_BOTTOMTABMODESTART
);
3528 void CMainFrame::OnUpdateTabMode(CBaseView
*view
, CCmdUI
*pCmdUI
, int startid
)
3532 int cmd
= (int)pCmdUI
->m_nID
- startid
;
3533 if (cmd
== TABMODE_NONE
)
3534 pCmdUI
->SetCheck((view
->GetTabMode() & TABMODE_USESPACES
) == TABMODE_NONE
);
3535 else if (cmd
== TABMODE_USESPACES
)
3536 pCmdUI
->SetCheck(view
->GetTabMode() & TABMODE_USESPACES
);
3537 else if (cmd
== TABMODE_SMARTINDENT
)
3538 pCmdUI
->SetCheck(view
->GetTabMode() & TABMODE_SMARTINDENT
);
3539 else if (cmd
== TABSIZEBUTTON1
)
3540 pCmdUI
->SetCheck(view
->GetTabSize() == 1);
3541 else if (cmd
== TABSIZEBUTTON2
)
3542 pCmdUI
->SetCheck(view
->GetTabSize() == 2);
3543 else if (cmd
== TABSIZEBUTTON4
)
3544 pCmdUI
->SetCheck(view
->GetTabSize() == 4);
3545 else if (cmd
== TABSIZEBUTTON8
)
3546 pCmdUI
->SetCheck(view
->GetTabSize() == 8);
3547 else if (cmd
== ENABLEEDITORCONFIG
)
3548 pCmdUI
->SetCheck(view
->GetEditorConfigEnabled());
3549 pCmdUI
->Enable(view
->IsWritable());
3550 if (cmd
== ENABLEEDITORCONFIG
)
3551 pCmdUI
->Enable(view
->IsWritable() && view
->GetEditorConfigLoaded());
3554 pCmdUI
->Enable(FALSE
);
3557 BOOL
CMainFrame::OnShowPopupMenu(CMFCPopupMenu
* pMenuPopup
)
3559 __super::OnShowPopupMenu(pMenuPopup
);
3561 if (pMenuPopup
== NULL
)
3567 if (!CMFCToolBar::IsCustomizeMode() &&
3568 (iIndex
= pMenuPopup
->GetMenuBar()->CommandToIndex(ID_REGEXFILTER
)) >= 0)
3570 BuildRegexSubitems(pMenuPopup
);