1 // TortoiseGitMerge - a Diff/Patch program
3 // Copyright (C) 2008-2014 - TortoiseGit
4 // Copyright (C) 2004-2014 - TortoiseSVN
5 // Copyright (C) 2012-2014 - Sven Strickroth <email@cs-ware.de>
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 2
10 // of the License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software Foundation,
19 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "TortoiseMerge.h"
23 #include "CustomMFCRibbonButton.h"
25 #include "SysProgressDlg.h"
27 #include "MessageBox.h"
29 #include "PathUtils.h"
32 #include "RightView.h"
33 #include "BottomView.h"
34 #include "DiffColors.h"
35 #include "SelectFileFilter.h"
36 #include "FormatMessageWrapper.h"
37 #include "TaskbarUUID.h"
39 #include "SmartLibgit2Ref.h" // needs to be included after git2.h
40 #include "RegexFiltersDlg.h"
47 CCustomMFCRibbonButton button1
;
50 const UINT TaskBarButtonCreated
= RegisterWindowMessage(L
"TaskbarButtonCreated");
51 #define IDT_RELOADCHECKTIMER 123
53 IMPLEMENT_DYNCREATE(CMainFrame
, CFrameWndEx
)
55 BEGIN_MESSAGE_MAP(CMainFrame
, CFrameWndEx
)
57 ON_COMMAND_RANGE(ID_VIEW_APPLOOK_WIN7
, ID_VIEW_APPLOOK_OFF_2007_AQUA
, &CMainFrame::OnApplicationLook
)
58 ON_UPDATE_COMMAND_UI_RANGE(IDC_STYLEBUTTON
, ID_VIEW_APPLOOK_OFF_2007_AQUA
, &CMainFrame::OnUpdateApplicationLook
)
59 // Global help commands
60 ON_COMMAND(ID_HELP_FINDER
, CFrameWndEx::OnHelpFinder
)
61 ON_COMMAND(ID_HELP
, CFrameWndEx::OnHelp
)
62 ON_COMMAND(ID_CONTEXT_HELP
, CFrameWndEx::OnContextHelp
)
63 ON_COMMAND(ID_DEFAULT_HELP
, CFrameWndEx::OnHelpFinder
)
64 ON_COMMAND(ID_FILE_OPEN
, OnFileOpen
)
65 ON_COMMAND(ID_VIEW_WHITESPACES
, OnViewWhitespaces
)
67 ON_COMMAND(ID_FILE_SAVE
, OnFileSave
)
68 ON_COMMAND(ID_FILE_SAVE_AS
, OnFileSaveAs
)
69 ON_UPDATE_COMMAND_UI(ID_FILE_SAVE
, OnUpdateFileSave
)
70 ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_AS
, OnUpdateFileSaveAs
)
71 ON_COMMAND(ID_VIEW_ONEWAYDIFF
, OnViewOnewaydiff
)
72 ON_UPDATE_COMMAND_UI(ID_VIEW_ONEWAYDIFF
, OnUpdateViewOnewaydiff
)
73 ON_UPDATE_COMMAND_UI(ID_VIEW_WHITESPACES
, OnUpdateViewWhitespaces
)
74 ON_COMMAND(ID_VIEW_OPTIONS
, OnViewOptions
)
77 ON_COMMAND(ID_FILE_RELOAD
, OnFileReload
)
78 ON_COMMAND(ID_VIEW_LINEDOWN
, OnViewLinedown
)
79 ON_COMMAND(ID_VIEW_LINEUP
, OnViewLineup
)
80 ON_COMMAND(ID_VIEW_MOVEDBLOCKS
, OnViewMovedBlocks
)
81 ON_UPDATE_COMMAND_UI(ID_VIEW_MOVEDBLOCKS
, OnUpdateViewMovedBlocks
)
82 ON_UPDATE_COMMAND_UI(ID_EDIT_MARKASRESOLVED
, OnUpdateMergeMarkasresolved
)
83 ON_COMMAND(ID_EDIT_MARKASRESOLVED
, OnMergeMarkasresolved
)
84 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_NEXTCONFLICT
, OnUpdateMergeNextconflict
)
85 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_PREVIOUSCONFLICT
, OnUpdateMergePreviousconflict
)
88 ON_UPDATE_COMMAND_UI(ID_EDIT_COPY
, OnUpdateEditCopy
)
89 ON_COMMAND(ID_VIEW_SWITCHLEFT
, OnViewSwitchleft
)
90 ON_UPDATE_COMMAND_UI(ID_VIEW_SWITCHLEFT
, OnUpdateViewSwitchleft
)
91 ON_COMMAND(ID_VIEW_LINELEFT
, &CMainFrame::OnViewLineleft
)
92 ON_COMMAND(ID_VIEW_LINERIGHT
, &CMainFrame::OnViewLineright
)
93 ON_UPDATE_COMMAND_UI(ID_VIEW_SHOWFILELIST
, &CMainFrame::OnUpdateViewShowfilelist
)
94 ON_COMMAND(ID_VIEW_SHOWFILELIST
, &CMainFrame::OnViewShowfilelist
)
95 ON_COMMAND(ID_EDIT_USETHEIRBLOCK
, &CMainFrame::OnEditUseTheirs
)
96 ON_COMMAND(ID_EDIT_USEMYBLOCK
, &CMainFrame::OnEditUseMine
)
97 ON_COMMAND(ID_EDIT_USETHEIRTHENMYBLOCK
, &CMainFrame::OnEditUseTheirsThenMine
)
98 ON_COMMAND(ID_EDIT_USEMINETHENTHEIRBLOCK
, &CMainFrame::OnEditUseMineThenTheirs
)
99 ON_COMMAND(ID_EDIT_UNDO
, &CMainFrame::OnEditUndo
)
100 ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO
, &CMainFrame::OnUpdateEditUndo
)
101 ON_COMMAND(ID_EDIT_ENABLE
, &CMainFrame::OnEditEnable
)
102 ON_UPDATE_COMMAND_UI(ID_EDIT_ENABLE
, &CMainFrame::OnUpdateEditEnable
)
103 ON_UPDATE_COMMAND_UI(ID_EDIT_USEMINETHENTHEIRBLOCK
, &CMainFrame::OnUpdateEditUseminethentheirblock
)
104 ON_UPDATE_COMMAND_UI(ID_EDIT_USEMYBLOCK
, &CMainFrame::OnUpdateEditUsemyblock
)
105 ON_UPDATE_COMMAND_UI(ID_EDIT_USETHEIRBLOCK
, &CMainFrame::OnUpdateEditUsetheirblock
)
106 ON_UPDATE_COMMAND_UI(ID_EDIT_USETHEIRTHENMYBLOCK
, &CMainFrame::OnUpdateEditUsetheirthenmyblock
)
107 ON_COMMAND(ID_VIEW_INLINEDIFFWORD
, &CMainFrame::OnViewInlinediffword
)
108 ON_UPDATE_COMMAND_UI(ID_VIEW_INLINEDIFFWORD
, &CMainFrame::OnUpdateViewInlinediffword
)
109 ON_COMMAND(ID_VIEW_INLINEDIFF
, &CMainFrame::OnViewInlinediff
)
110 ON_UPDATE_COMMAND_UI(ID_VIEW_INLINEDIFF
, &CMainFrame::OnUpdateViewInlinediff
)
111 ON_UPDATE_COMMAND_UI(ID_EDIT_CREATEUNIFIEDDIFFFILE
, &CMainFrame::OnUpdateEditCreateunifieddifffile
)
112 ON_COMMAND(ID_EDIT_CREATEUNIFIEDDIFFFILE
, &CMainFrame::OnEditCreateunifieddifffile
)
113 ON_UPDATE_COMMAND_UI(ID_EDIT_TABSPACE
, &CMainFrame::OnUpdateEditTabspace
)
114 ON_COMMAND(ID_EDIT_TABSPACE
, &CMainFrame::OnEditTabspace
)
115 ON_UPDATE_COMMAND_UI(ID_EDIT_SMARTTAB
, &CMainFrame::OnUpdateEditSmartTab
)
116 ON_COMMAND(ID_EDIT_SMARTTAB
, &CMainFrame::OnEditSmartTab
)
117 ON_UPDATE_COMMAND_UI(ID_VIEW_LINEDIFFBAR
, &CMainFrame::OnUpdateViewLinediffbar
)
118 ON_COMMAND(ID_VIEW_LINEDIFFBAR
, &CMainFrame::OnViewLinediffbar
)
119 ON_UPDATE_COMMAND_UI(ID_VIEW_LOCATORBAR
, &CMainFrame::OnUpdateViewLocatorbar
)
120 ON_COMMAND(ID_VIEW_LOCATORBAR
, &CMainFrame::OnViewLocatorbar
)
121 ON_COMMAND(ID_EDIT_USELEFTBLOCK
, &CMainFrame::OnEditUseleftblock
)
122 ON_UPDATE_COMMAND_UI(ID_USEBLOCKS
, &CMainFrame::OnUpdateUseBlock
)
123 ON_UPDATE_COMMAND_UI(ID_EDIT_USELEFTBLOCK
, &CMainFrame::OnUpdateEditUseleftblock
)
124 ON_COMMAND(ID_EDIT_USELEFTFILE
, &CMainFrame::OnEditUseleftfile
)
125 ON_UPDATE_COMMAND_UI(ID_EDIT_USELEFTFILE
, &CMainFrame::OnUpdateEditUseleftfile
)
126 ON_COMMAND(ID_EDIT_USEBLOCKFROMLEFTBEFORERIGHT
, &CMainFrame::OnEditUseblockfromleftbeforeright
)
127 ON_UPDATE_COMMAND_UI(ID_EDIT_USEBLOCKFROMLEFTBEFORERIGHT
, &CMainFrame::OnUpdateEditUseblockfromleftbeforeright
)
128 ON_COMMAND(ID_EDIT_USEBLOCKFROMRIGHTBEFORELEFT
, &CMainFrame::OnEditUseblockfromrightbeforeleft
)
129 ON_UPDATE_COMMAND_UI(ID_EDIT_USEBLOCKFROMRIGHTBEFORELEFT
, &CMainFrame::OnUpdateEditUseblockfromrightbeforeleft
)
130 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_NEXTDIFFERENCE
, &CMainFrame::OnUpdateNavigateNextdifference
)
131 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_PREVIOUSDIFFERENCE
, &CMainFrame::OnUpdateNavigatePreviousdifference
)
132 ON_COMMAND(ID_VIEW_COLLAPSED
, &CMainFrame::OnViewCollapsed
)
133 ON_UPDATE_COMMAND_UI(ID_VIEW_COLLAPSED
, &CMainFrame::OnUpdateViewCollapsed
)
134 ON_COMMAND(ID_VIEW_COMPAREWHITESPACES
, &CMainFrame::OnViewComparewhitespaces
)
135 ON_UPDATE_COMMAND_UI(ID_VIEW_COMPAREWHITESPACES
, &CMainFrame::OnUpdateViewComparewhitespaces
)
136 ON_COMMAND(ID_VIEW_IGNOREWHITESPACECHANGES
, &CMainFrame::OnViewIgnorewhitespacechanges
)
137 ON_UPDATE_COMMAND_UI(ID_VIEW_IGNOREWHITESPACECHANGES
, &CMainFrame::OnUpdateViewIgnorewhitespacechanges
)
138 ON_COMMAND(ID_VIEW_IGNOREALLWHITESPACECHANGES
, &CMainFrame::OnViewIgnoreallwhitespacechanges
)
139 ON_UPDATE_COMMAND_UI(ID_VIEW_IGNOREALLWHITESPACECHANGES
, &CMainFrame::OnUpdateViewIgnoreallwhitespacechanges
)
140 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_NEXTINLINEDIFF
, &CMainFrame::OnUpdateNavigateNextinlinediff
)
141 ON_UPDATE_COMMAND_UI(ID_NAVIGATE_PREVINLINEDIFF
, &CMainFrame::OnUpdateNavigatePrevinlinediff
)
142 ON_COMMAND(ID_VIEW_WRAPLONGLINES
, &CMainFrame::OnViewWraplonglines
)
143 ON_UPDATE_COMMAND_UI(ID_VIEW_WRAPLONGLINES
, &CMainFrame::OnUpdateViewWraplonglines
)
144 ON_REGISTERED_MESSAGE( TaskBarButtonCreated
, CMainFrame::OnTaskbarButtonCreated
)
145 ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE
, &CMainFrame::OnUpdateEditPaste
)
146 ON_COMMAND(ID_INDICATOR_LEFTVIEW
, &CMainFrame::OnIndicatorLeftview
)
147 ON_COMMAND(ID_INDICATOR_RIGHTVIEW
, &CMainFrame::OnIndicatorRightview
)
148 ON_COMMAND(ID_INDICATOR_BOTTOMVIEW
, &CMainFrame::OnIndicatorBottomview
)
150 ON_COMMAND(ID_VIEW_IGNORECOMMENTS
, &CMainFrame::OnViewIgnorecomments
)
151 ON_UPDATE_COMMAND_UI(ID_VIEW_IGNORECOMMENTS
, &CMainFrame::OnUpdateViewIgnorecomments
)
152 ON_COMMAND_RANGE(ID_REGEXFILTER
, ID_REGEXFILTER
+400, &CMainFrame::OnRegexfilter
)
153 ON_UPDATE_COMMAND_UI_RANGE(ID_REGEXFILTER
, ID_REGEXFILTER
+400, &CMainFrame::OnUpdateViewRegexFilter
)
154 ON_COMMAND(ID_INDICATOR_LEFTVIEWCOMBOENCODING
, &CMainFrame::OnDummyEnabled
)
155 ON_COMMAND(ID_INDICATOR_RIGHTVIEWCOMBOENCODING
, &CMainFrame::OnDummyEnabled
)
156 ON_COMMAND(ID_INDICATOR_BOTTOMVIEWCOMBOENCODING
, &CMainFrame::OnDummyEnabled
)
157 ON_COMMAND(ID_INDICATOR_LEFTVIEWCOMBOEOL
, &CMainFrame::OnDummyEnabled
)
158 ON_COMMAND(ID_INDICATOR_RIGHTVIEWCOMBOEOL
, &CMainFrame::OnDummyEnabled
)
159 ON_COMMAND(ID_INDICATOR_BOTTOMVIEWCOMBOEOL
, &CMainFrame::OnDummyEnabled
)
160 ON_COMMAND_RANGE(ID_INDICATOR_LEFTENCODINGSTART
, ID_INDICATOR_LEFTENCODINGSTART
+19, &CMainFrame::OnEncodingLeft
)
161 ON_COMMAND_RANGE(ID_INDICATOR_RIGHTENCODINGSTART
, ID_INDICATOR_RIGHTENCODINGSTART
+19, &CMainFrame::OnEncodingRight
)
162 ON_COMMAND_RANGE(ID_INDICATOR_BOTTOMENCODINGSTART
, ID_INDICATOR_BOTTOMENCODINGSTART
+19, &CMainFrame::OnEncodingBottom
)
163 ON_COMMAND_RANGE(ID_INDICATOR_LEFTEOLSTART
, ID_INDICATOR_LEFTEOLSTART
+19, &CMainFrame::OnEOLLeft
)
164 ON_COMMAND_RANGE(ID_INDICATOR_RIGHTEOLSTART
, ID_INDICATOR_RIGHTEOLSTART
+19, &CMainFrame::OnEOLRight
)
165 ON_COMMAND_RANGE(ID_INDICATOR_BOTTOMEOLSTART
, ID_INDICATOR_BOTTOMEOLSTART
+19, &CMainFrame::OnEOLBottom
)
166 ON_UPDATE_COMMAND_UI_RANGE(ID_INDICATOR_LEFTENCODINGSTART
, ID_INDICATOR_LEFTENCODINGSTART
+19, &CMainFrame::OnUpdateEncodingLeft
)
167 ON_UPDATE_COMMAND_UI_RANGE(ID_INDICATOR_RIGHTENCODINGSTART
, ID_INDICATOR_RIGHTENCODINGSTART
+19, &CMainFrame::OnUpdateEncodingRight
)
168 ON_UPDATE_COMMAND_UI_RANGE(ID_INDICATOR_BOTTOMENCODINGSTART
, ID_INDICATOR_BOTTOMENCODINGSTART
+19, &CMainFrame::OnUpdateEncodingBottom
)
169 ON_UPDATE_COMMAND_UI_RANGE(ID_INDICATOR_LEFTEOLSTART
, ID_INDICATOR_LEFTEOLSTART
+19, &CMainFrame::OnUpdateEOLLeft
)
170 ON_UPDATE_COMMAND_UI_RANGE(ID_INDICATOR_RIGHTEOLSTART
, ID_INDICATOR_RIGHTEOLSTART
+19, &CMainFrame::OnUpdateEOLRight
)
171 ON_UPDATE_COMMAND_UI_RANGE(ID_INDICATOR_BOTTOMEOLSTART
, ID_INDICATOR_BOTTOMEOLSTART
+19, &CMainFrame::OnUpdateEOLBottom
)
174 static UINT indicators
[] =
176 ID_SEPARATOR
, // status line indicator
177 ID_INDICATOR_LEFTVIEW
,
178 ID_INDICATOR_RIGHTVIEW
,
179 ID_INDICATOR_BOTTOMVIEW
,
185 // CMainFrame construction/destruction
187 CMainFrame::CMainFrame()
188 : m_bInitSplitter(FALSE
)
189 , m_bReversedPatch(FALSE
)
190 , m_bHasConflicts(false)
191 , m_bInlineWordDiff(true)
193 , m_bLocatorBar(true)
194 , m_nMoveMovesToIgnore(0)
195 , m_pwndLeftView(NULL
)
196 , m_pwndRightView(NULL
)
197 , m_pwndBottomView(NULL
)
200 , m_bCheckReload(false)
201 , m_bSaveRequired(false)
202 , m_bSaveRequiredOnConflicts(false)
204 , resolveMsgWParam(0)
205 , resolveMsgLParam(0)
206 , m_regWrapLines(L
"Software\\TortoiseGitMerge\\WrapLines", 0)
207 , m_regViewModedBlocks(L
"Software\\TortoiseGitMerge\\ViewMovedBlocks", TRUE
)
208 , m_regOneWay(L
"Software\\TortoiseGitMerge\\OnePane")
209 , m_regCollapsed(L
"Software\\TortoiseGitMerge\\Collapsed", 0)
210 , m_regInlineDiff(L
"Software\\TortoiseGitMerge\\DisplayBinDiff", TRUE
)
211 , m_regUseRibbons(L
"Software\\TortoiseGitMerge\\UseRibbons", TRUE
)
212 , m_regUseTaskDialog(L
"Software\\TortoiseGitMerge\\UseTaskDialog", TRUE
)
213 , m_regIgnoreComments(_T("Software\\TortoiseGitMerge\\IgnoreComments"), FALSE
)
215 , m_regTabMode(L
"Software\\TortoiseGitMerge\\TabMode", TABMODE_NONE
)
217 m_bOneWay
= (0 != ((DWORD
)m_regOneWay
));
218 theApp
.m_nAppLook
= theApp
.GetInt(_T("ApplicationLook"), ID_VIEW_APPLOOK_VS_2005
);
219 m_bCollapsed
= !!(DWORD
)m_regCollapsed
;
220 m_bViewMovedBlocks
= !!(DWORD
)m_regViewModedBlocks
;
221 m_bWrapLines
= !!(DWORD
)m_regWrapLines
;
222 m_bInlineDiff
= !!m_regInlineDiff
;
223 m_bUseRibbons
= !!m_regUseRibbons
;
225 if (SysInfo::Instance().IsXP())
226 m_bUseRibbons
= FALSE
;
228 m_bUseTaskDialog
= CTaskDialog::IsSupported() && (DWORD
)m_regUseTaskDialog
;
229 CMFCVisualManagerWindows::m_b3DTabsXPTheme
= TRUE
;
232 CMainFrame::~CMainFrame()
236 LRESULT
CMainFrame::OnTaskbarButtonCreated(WPARAM
/*wParam*/, LPARAM
/*lParam*/)
238 SetUUIDOverlayIcon(m_hWnd
);
243 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct
)
245 if (CFrameWndEx::OnCreate(lpCreateStruct
) == -1)
248 OnApplicationLook(theApp
.m_nAppLook
);
252 m_wndRibbonBar
.Create(this);
253 m_wndRibbonBar
.LoadFromResource(IDR_RIBBON
);
255 // enable the dialog launch button on the view panel
256 CMFCRibbonCategory
* pMainCat
= m_wndRibbonBar
.GetCategory(1);
259 CMFCRibbonPanel
* pPanel
= pMainCat
->GetPanel(3);
261 pPanel
->EnableLaunchButton(ID_VIEW_OPTIONS
);
263 // now replace all buttons with our custom button class
264 for (int i
= 0; i
< m_wndRibbonBar
.GetCategoryCount(); ++i
)
266 CMFCRibbonCategory
* pCat
= m_wndRibbonBar
.GetCategory(i
);
267 for (int j
= 0; j
< pCat
->GetPanelCount(); ++j
)
269 CMFCRibbonPanel
* pPanel
= pCat
->GetPanel(j
);
270 CList
<UINT
, UINT
> lstItems
;
271 pPanel
->GetItemIDsList(lstItems
);
272 while (!lstItems
.IsEmpty())
274 UINT id
= lstItems
.GetHead();
275 lstItems
.RemoveHead();
276 CMFCRibbonButton
* pButton
= dynamic_cast<CMFCRibbonButton
*>(pPanel
->FindByID(id
));
279 CCustomMFCRibbonButton
* c
= new CCustomMFCRibbonButton(id
, pButton
->GetText());
280 pPanel
->ReplaceByID(id
, c
);
285 BuildRegexSubitems();
286 if (!m_wndRibbonStatusBar
.Create(this))
288 TRACE0("Failed to create ribbon status bar\n");
289 return -1; // fail to create
291 m_wndRibbonStatusBar
.AddElement(new CMFCRibbonStatusBarPane(ID_SEPARATOR
, CString(MAKEINTRESOURCE(AFX_IDS_IDLEMESSAGE
)), TRUE
), L
"");
293 std::unique_ptr
<CMFCRibbonButtonsGroup
> apBtnGroupLeft(new 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 FillEncodingButton(pButton
, ID_INDICATOR_LEFTENCODINGSTART
);
298 apBtnGroupLeft
->AddButton(pButton
);
299 pButton
= new CMFCRibbonButton(ID_INDICATOR_LEFTVIEWCOMBOEOL
, L
"");
300 FillEOLButton(pButton
, ID_INDICATOR_LEFTEOLSTART
);
301 apBtnGroupLeft
->AddButton(pButton
);
302 apBtnGroupLeft
->AddButton(new CMFCRibbonStatusBarPane(ID_INDICATOR_LEFTVIEW
, L
"", TRUE
));
303 m_wndRibbonStatusBar
.AddExtendedElement(apBtnGroupLeft
.release(), L
"");
305 std::unique_ptr
<CMFCRibbonButtonsGroup
> apBtnGroupRight(new CMFCRibbonButtonsGroup
);
306 apBtnGroupRight
->SetID(ID_INDICATOR_RIGHTVIEW
);
307 apBtnGroupRight
->AddButton(new CMFCRibbonStatusBarPane(ID_SEPARATOR
, CString(MAKEINTRESOURCE(IDS_STATUSBAR_RIGHTVIEW
)), TRUE
));
308 pButton
= new CMFCRibbonButton(ID_INDICATOR_RIGHTVIEWCOMBOENCODING
, L
"");
309 FillEncodingButton(pButton
, ID_INDICATOR_RIGHTENCODINGSTART
);
310 apBtnGroupRight
->AddButton(pButton
);
311 pButton
= new CMFCRibbonButton(ID_INDICATOR_RIGHTVIEWCOMBOEOL
, L
"");
312 FillEOLButton(pButton
, ID_INDICATOR_RIGHTEOLSTART
);
313 apBtnGroupRight
->AddButton(pButton
);
314 apBtnGroupRight
->AddButton(new CMFCRibbonStatusBarPane(ID_INDICATOR_RIGHTVIEW
, L
"", TRUE
));
315 m_wndRibbonStatusBar
.AddExtendedElement(apBtnGroupRight
.release(), L
"");
319 if (!m_wndMenuBar
.Create(this))
321 TRACE0("Failed to create menubar\n");
322 return -1; // fail to create
324 m_wndMenuBar
.SetPaneStyle(m_wndMenuBar
.GetPaneStyle() | CBRS_SIZE_DYNAMIC
| CBRS_TOOLTIPS
| CBRS_FLYBY
);
326 // prevent the menu bar from taking the focus on activation
327 CMFCPopupMenu::SetForceMenuFocus(FALSE
);
328 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
))
330 TRACE0("Failed to create toolbar\n");
331 return -1; // fail to create
333 m_wndToolBar
.SetWindowText(_T("Main"));
334 if (!m_wndStatusBar
.Create(this) ||
335 !m_wndStatusBar
.SetIndicators(indicators
,
336 _countof(indicators
)))
338 TRACE0("Failed to create status bar\n");
339 return -1; // fail to create
341 m_wndStatusBar
.EnablePaneDoubleClick();
344 if (!m_wndLocatorBar
.Create(this, IDD_DIFFLOCATOR
,
345 CBRS_ALIGN_LEFT
| CBRS_SIZE_FIXED
, ID_VIEW_LOCATORBAR
))
347 TRACE0("Failed to create dialogbar\n");
348 return -1; // fail to create
350 if (!m_wndLineDiffBar
.Create(this, IDD_LINEDIFF
,
351 CBRS_ALIGN_BOTTOM
| CBRS_SIZE_FIXED
, ID_VIEW_LINEDIFFBAR
))
353 TRACE0("Failed to create dialogbar\n");
354 return -1; // fail to create
356 m_wndLocatorBar
.m_pMainFrm
= this;
357 m_wndLineDiffBar
.m_pMainFrm
= this;
359 EnableDocking(CBRS_ALIGN_ANY
);
362 m_wndMenuBar
.EnableDocking(CBRS_ALIGN_TOP
);
363 m_wndToolBar
.EnableDocking(CBRS_ALIGN_TOP
);
364 DockPane(&m_wndMenuBar
);
365 DockPane(&m_wndToolBar
);
367 DockPane(&m_wndLocatorBar
);
368 DockPane(&m_wndLineDiffBar
);
369 ShowPane(&m_wndLocatorBar
, true, false, true);
370 ShowPane(&m_wndLineDiffBar
, true, false, true);
372 m_wndLocatorBar
.EnableGripper(FALSE
);
373 m_wndLineDiffBar
.EnableGripper(FALSE
);
378 BOOL
CMainFrame::PreCreateWindow(CREATESTRUCT
& cs
)
380 if( !CFrameWndEx::PreCreateWindow(cs
) )
385 void CMainFrame::OnApplicationLook(UINT id
)
389 theApp
.m_nAppLook
= id
;
391 switch (theApp
.m_nAppLook
)
393 case ID_VIEW_APPLOOK_WIN_2000
:
394 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManager
));
395 m_wndRibbonBar
.SetWindows7Look(FALSE
);
398 case ID_VIEW_APPLOOK_OFF_XP
:
399 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOfficeXP
));
400 m_wndRibbonBar
.SetWindows7Look(FALSE
);
403 case ID_VIEW_APPLOOK_WIN_XP
:
404 CMFCVisualManagerWindows::m_b3DTabsXPTheme
= TRUE
;
405 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows
));
406 m_wndRibbonBar
.SetWindows7Look(FALSE
);
409 case ID_VIEW_APPLOOK_OFF_2003
:
410 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2003
));
411 CDockingManager::SetDockingMode(DT_SMART
);
412 m_wndRibbonBar
.SetWindows7Look(FALSE
);
415 case ID_VIEW_APPLOOK_VS_2005
:
416 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerVS2005
));
417 CDockingManager::SetDockingMode(DT_SMART
);
418 m_wndRibbonBar
.SetWindows7Look(FALSE
);
421 case ID_VIEW_APPLOOK_VS_2008
:
422 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerVS2008
));
423 CDockingManager::SetDockingMode(DT_SMART
);
424 m_wndRibbonBar
.SetWindows7Look(FALSE
);
427 case ID_VIEW_APPLOOK_WIN7
:
428 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows7
));
429 CDockingManager::SetDockingMode(DT_SMART
);
430 m_wndRibbonBar
.SetWindows7Look(TRUE
);
434 switch (theApp
.m_nAppLook
)
436 case ID_VIEW_APPLOOK_OFF_2007_BLUE
:
437 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_LunaBlue
);
440 case ID_VIEW_APPLOOK_OFF_2007_BLACK
:
441 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_ObsidianBlack
);
444 case ID_VIEW_APPLOOK_OFF_2007_SILVER
:
445 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_Silver
);
448 case ID_VIEW_APPLOOK_OFF_2007_AQUA
:
449 CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_Aqua
);
453 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2007
));
454 CDockingManager::SetDockingMode(DT_SMART
);
455 m_wndRibbonBar
.SetWindows7Look(FALSE
);
458 RedrawWindow(NULL
, NULL
, RDW_ALLCHILDREN
| RDW_INVALIDATE
| RDW_UPDATENOW
| RDW_FRAME
| RDW_ERASE
);
460 theApp
.WriteInt(_T("ApplicationLook"), theApp
.m_nAppLook
);
463 void CMainFrame::OnUpdateApplicationLook(CCmdUI
* pCmdUI
)
466 pCmdUI
->SetRadio(theApp
.m_nAppLook
== pCmdUI
->m_nID
);
470 // CMainFrame diagnostics
473 void CMainFrame::AssertValid() const
475 CFrameWndEx::AssertValid();
478 void CMainFrame::Dump(CDumpContext
& dc
) const
480 CFrameWndEx::Dump(dc
);
486 // CMainFrame message handlers
489 BOOL
CMainFrame::OnCreateClient(LPCREATESTRUCT
/*lpcs*/, CCreateContext
* pContext
)
495 // split into three panes:
504 // create a splitter with 2 rows, 1 column
505 if (!m_wndSplitter
.CreateStatic(this, 2, 1))
507 TRACE0("Failed to CreateStaticSplitter\n");
511 // add the second splitter pane - which is a nested splitter with 2 columns
512 if (!m_wndSplitter2
.CreateStatic(
513 &m_wndSplitter
, // our parent window is the first splitter
514 1, 2, // the new splitter is 1 row, 2 columns
515 WS_CHILD
| WS_VISIBLE
| WS_BORDER
, // style, WS_BORDER is needed
516 m_wndSplitter
.IdFromRowCol(0, 0)
517 // new splitter is in the first row, 1st column of first splitter
520 TRACE0("Failed to create nested splitter\n");
523 // add the first splitter pane - the default view in row 0
524 if (!m_wndSplitter
.CreateView(1, 0,
525 RUNTIME_CLASS(CBottomView
), CSize(cr
.Width(), cr
.Height()), pContext
))
527 TRACE0("Failed to create first pane\n");
530 m_pwndBottomView
= (CBottomView
*)m_wndSplitter
.GetPane(1,0);
531 m_pwndBottomView
->m_pwndLocator
= &m_wndLocatorBar
;
532 m_pwndBottomView
->m_pwndLineDiffBar
= &m_wndLineDiffBar
;
534 m_pwndBottomView
->m_pwndRibbonStatusBar
= &m_wndRibbonStatusBar
;
536 m_pwndBottomView
->m_pwndStatusBar
= &m_wndStatusBar
;
537 m_pwndBottomView
->m_pMainFrame
= this;
539 // now create the two views inside the nested splitter
541 if (!m_wndSplitter2
.CreateView(0, 0,
542 RUNTIME_CLASS(CLeftView
), CSize(cr
.Width()/2, cr
.Height()/2), pContext
))
544 TRACE0("Failed to create second pane\n");
547 m_pwndLeftView
= (CLeftView
*)m_wndSplitter2
.GetPane(0,0);
548 m_pwndLeftView
->m_pwndLocator
= &m_wndLocatorBar
;
549 m_pwndLeftView
->m_pwndLineDiffBar
= &m_wndLineDiffBar
;
551 m_pwndLeftView
->m_pwndRibbonStatusBar
= &m_wndRibbonStatusBar
;
553 m_pwndLeftView
->m_pwndStatusBar
= &m_wndStatusBar
;
554 m_pwndLeftView
->m_pMainFrame
= this;
556 if (!m_wndSplitter2
.CreateView(0, 1,
557 RUNTIME_CLASS(CRightView
), CSize(cr
.Width()/2, cr
.Height()/2), pContext
))
559 TRACE0("Failed to create third pane\n");
562 m_pwndRightView
= (CRightView
*)m_wndSplitter2
.GetPane(0,1);
563 m_pwndRightView
->m_pwndLocator
= &m_wndLocatorBar
;
564 m_pwndRightView
->m_pwndLineDiffBar
= &m_wndLineDiffBar
;
566 m_pwndRightView
->m_pwndRibbonStatusBar
= &m_wndRibbonStatusBar
;
568 m_pwndRightView
->m_pwndStatusBar
= &m_wndStatusBar
;
569 m_pwndRightView
->m_pMainFrame
= this;
570 m_bInitSplitter
= TRUE
;
572 m_dlgFilePatches
.Create(IDD_FILEPATCHES
, this);
578 BOOL
CMainFrame::PatchFile(CString sFilePath
, bool /*bContentMods*/, bool bPropMods
, CString sVersion
, BOOL bAutoPatch
)
581 //"dry run" was successful, so save the patched file somewhere...
582 CString sTempFile
= CTempFiles::Instance().GetTempFilePathString();
583 CString sRejectedFile
, sBasePath
;
584 if (m_Patch
.GetPatchResult(sFilePath
, sTempFile
, sRejectedFile
, sBasePath
) < 0)
586 MessageBox(m_Patch
.GetErrorMessage(), NULL
, MB_ICONERROR
);
589 sFilePath
= m_Patch
.GetTargetPath() + _T("\\") + sFilePath
;
590 sFilePath
.Replace('/', '\\');
591 if (sBasePath
.IsEmpty())
592 sBasePath
= sFilePath
;
593 if (m_bReversedPatch
)
595 m_Data
.m_baseFile
.SetFileName(sTempFile
);
597 temp
.Format(_T("%s %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sFilePath
), (LPCTSTR
)m_Data
.m_sPatchPatched
);
598 m_Data
.m_baseFile
.SetDescriptiveName(temp
);
599 m_Data
.m_yourFile
.SetFileName(sFilePath
);
600 temp
.Format(_T("%s %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sFilePath
), (LPCTSTR
)m_Data
.m_sPatchOriginal
);
601 m_Data
.m_yourFile
.SetDescriptiveName(temp
);
602 m_Data
.m_theirFile
.SetOutOfUse();
603 m_Data
.m_mergedFile
.SetOutOfUse();
607 if ((!PathFileExists(sBasePath
))||(PathIsDirectory(sBasePath
)))
609 m_Data
.m_baseFile
.SetFileName(CTempFiles::Instance().GetTempFilePathString());
610 m_Data
.m_baseFile
.CreateEmptyFile();
614 m_Data
.m_baseFile
.SetFileName(sBasePath
);
616 CString sDescription
;
617 sDescription
.Format(_T("%s %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sBasePath
), (LPCTSTR
)m_Data
.m_sPatchOriginal
);
618 m_Data
.m_baseFile
.SetDescriptiveName(sDescription
);
619 if (sBasePath
== sFilePath
)
621 m_Data
.m_yourFile
.SetFileName(sTempFile
);
623 temp
.Format(_T("%s %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sBasePath
), (LPCTSTR
)m_Data
.m_sPatchPatched
);
624 m_Data
.m_yourFile
.SetDescriptiveName(temp
);
625 m_Data
.m_theirFile
.SetOutOfUse();
629 if (!PathFileExists(sFilePath
) || PathIsDirectory(sFilePath
))
631 m_Data
.m_yourFile
.SetFileName(CTempFiles::Instance().GetTempFilePathString());
632 m_Data
.m_yourFile
.CreateEmptyFile();
634 temp
.Format(_T("%s %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sFilePath
), CString(MAKEINTRESOURCE(IDS_NOTFOUNDVIEWTITLEINDICATOR
)));
635 m_Data
.m_yourFile
.SetDescriptiveName(temp
);
638 m_Data
.m_yourFile
.SetFileName(sFilePath
);
639 m_Data
.m_theirFile
.SetFileName(sTempFile
);
641 temp
.Format(_T("%s %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sFilePath
), (LPCTSTR
)m_Data
.m_sPatchPatched
);
642 m_Data
.m_theirFile
.SetDescriptiveName(temp
);
644 m_Data
.m_mergedFile
.SetFileName(sFilePath
);
645 m_Data
.m_bPatchRequired
= bPropMods
;
647 TRACE(_T("comparing %s\nwith the patched result %s\n"), (LPCTSTR
)sFilePath
, (LPCTSTR
)sTempFile
);
650 if (!sRejectedFile
.IsEmpty())
653 // start TortoiseUDiff with the rejected hunks
655 sTitle
.Format(IDS_TITLE_REJECTEDHUNKS
, (LPCTSTR
)CPathUtils::GetFileNameFromPath(sFilePath
));
656 CAppUtils::StartUnifiedDiffViewer(sRejectedFile
, sTitle
);
661 if (sBasePath
!= sFilePath
&& HasConflictsWontKeep())
670 BOOL
CMainFrame::DiffFiles(CString sURL1
, CString sRev1
, CString sURL2
, CString sRev2
)
672 CString tempfile1
= CTempFiles::Instance().GetTempFilePathString();
673 CString tempfile2
= CTempFiles::Instance().GetTempFilePathString();
675 ASSERT(tempfile1
.Compare(tempfile2
));
678 CSysProgressDlg progDlg
;
679 sTemp
.Format(IDS_GETVERSIONOFFILE
, (LPCTSTR
)sRev1
);
680 progDlg
.SetLine(1, sTemp
, true);
681 progDlg
.SetLine(2, sURL1
, true);
682 sTemp
.LoadString(IDS_GETVERSIONOFFILETITLE
);
683 progDlg
.SetTitle(sTemp
);
684 progDlg
.SetShowProgressBar(true);
685 progDlg
.SetAnimation(IDR_DOWNLOAD
);
686 progDlg
.SetTime(FALSE
);
687 progDlg
.SetProgress(1,100);
688 progDlg
.ShowModeless(this);
689 if (!CAppUtils::GetVersionedFile(sURL1
, sRev1
, tempfile1
, &progDlg
, m_hWnd
))
693 sErrMsg
.Format(IDS_ERR_MAINFRAME_FILEVERSIONNOTFOUND
, (LPCTSTR
)sRev1
, (LPCTSTR
)sURL1
);
694 MessageBox(sErrMsg
, NULL
, MB_ICONERROR
);
697 sTemp
.Format(IDS_GETVERSIONOFFILE
, (LPCTSTR
)sRev2
);
698 progDlg
.SetLine(1, sTemp
, true);
699 progDlg
.SetLine(2, sURL2
, true);
700 progDlg
.SetProgress(50, 100);
701 if (!CAppUtils::GetVersionedFile(sURL2
, sRev2
, tempfile2
, &progDlg
, m_hWnd
))
705 sErrMsg
.Format(IDS_ERR_MAINFRAME_FILEVERSIONNOTFOUND
, (LPCTSTR
)sRev2
, (LPCTSTR
)sURL2
);
706 MessageBox(sErrMsg
, NULL
, MB_ICONERROR
);
709 progDlg
.SetProgress(100,100);
712 temp
.Format(_T("%s Revision %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sURL1
), (LPCTSTR
)sRev1
);
713 m_Data
.m_baseFile
.SetFileName(tempfile1
);
714 m_Data
.m_baseFile
.SetDescriptiveName(temp
);
715 temp
.Format(_T("%s Revision %s"), (LPCTSTR
)CPathUtils::GetFileNameFromPath(sURL2
), (LPCTSTR
)sRev2
);
716 m_Data
.m_yourFile
.SetFileName(tempfile2
);
717 m_Data
.m_yourFile
.SetDescriptiveName(temp
);
724 void CMainFrame::OnFileOpen()
726 if (CheckForSave(CHFSR_OPEN
)==IDCANCEL
)
729 if (dlg
.DoModal()!=IDOK
)
733 m_dlgFilePatches
.ShowWindow(SW_HIDE
);
734 m_dlgFilePatches
.Init(NULL
, NULL
, CString(), NULL
);
735 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
,
736 (LPCTSTR
)dlg
.m_sUnifiedDiffFile
, (LPCTSTR
)dlg
.m_sPatchDirectory
);
737 m_Data
.m_baseFile
.SetFileName(dlg
.m_sBaseFile
);
738 m_Data
.m_theirFile
.SetFileName(dlg
.m_sTheirFile
);
739 m_Data
.m_yourFile
.SetFileName(dlg
.m_sYourFile
);
740 m_Data
.m_sDiffFile
= dlg
.m_sUnifiedDiffFile
;
741 m_Data
.m_sPatchPath
= dlg
.m_sPatchDirectory
;
742 m_Data
.m_mergedFile
.SetOutOfUse();
743 CCrashReport::Instance().AddFile2(dlg
.m_sBaseFile
, NULL
, _T("Basefile"), CR_AF_MAKE_FILE_COPY
);
744 CCrashReport::Instance().AddFile2(dlg
.m_sTheirFile
, NULL
, _T("Theirfile"), CR_AF_MAKE_FILE_COPY
);
745 CCrashReport::Instance().AddFile2(dlg
.m_sYourFile
, NULL
, _T("Yourfile"), CR_AF_MAKE_FILE_COPY
);
746 CCrashReport::Instance().AddFile2(dlg
.m_sUnifiedDiffFile
, NULL
, _T("Difffile"), CR_AF_MAKE_FILE_COPY
);
748 if (!m_Data
.IsBaseFileInUse() && m_Data
.IsTheirFileInUse() && m_Data
.IsYourFileInUse())
750 // a diff between two files means "Yours" against "Base", not "Theirs" against "Yours"
751 m_Data
.m_baseFile
.TransferDetailsFrom(m_Data
.m_theirFile
);
753 if (m_Data
.IsBaseFileInUse() && m_Data
.IsTheirFileInUse() && !m_Data
.IsYourFileInUse())
755 // a diff between two files means "Yours" against "Base", not "Theirs" against "Base"
756 m_Data
.m_yourFile
.TransferDetailsFrom(m_Data
.m_theirFile
);
758 m_bSaveRequired
= false;
763 void CMainFrame::ClearViewNamesAndPaths()
765 m_pwndLeftView
->m_sWindowName
.Empty();
766 m_pwndLeftView
->m_sFullFilePath
.Empty();
767 m_pwndRightView
->m_sWindowName
.Empty();
768 m_pwndRightView
->m_sFullFilePath
.Empty();
769 m_pwndBottomView
->m_sWindowName
.Empty();
770 m_pwndBottomView
->m_sFullFilePath
.Empty();
773 bool CMainFrame::LoadViews(int line
)
775 LoadIgnoreCommentData();
776 m_Data
.SetBlame(m_bBlame
);
777 m_Data
.SetMovedBlocks(m_bViewMovedBlocks
);
778 m_bHasConflicts
= false;
779 CBaseView
* pwndActiveView
= m_pwndLeftView
;
780 int nOldLine
= m_pwndRightView
? m_pwndRightView
->m_nTopLine
: -1;
782 m_pwndRightView
&& m_pwndRightView
->m_pViewData
?
783 m_pwndRightView
->m_pViewData
->GetLineNumber(m_pwndRightView
->m_nTopLine
) : -1;
784 POINT ptOldCaretPos
= {-1, -1};
785 if (m_pwndRightView
&& m_pwndRightView
->IsTarget())
786 ptOldCaretPos
= m_pwndRightView
->GetCaretPosition();
787 if (m_pwndBottomView
&& m_pwndBottomView
->IsTarget())
788 ptOldCaretPos
= m_pwndBottomView
->GetCaretPosition();
789 CString sExt
= CPathUtils::GetFileExtFromPath(m_Data
.m_baseFile
.GetFilename()).MakeLower();
791 auto sC
= m_IgnoreCommentsMap
.find(sExt
);
792 if (sC
== m_IgnoreCommentsMap
.end())
794 sExt
= CPathUtils::GetFileExtFromPath(m_Data
.m_yourFile
.GetFilename()).MakeLower();
795 sC
= m_IgnoreCommentsMap
.find(sExt
);
796 if (sC
== m_IgnoreCommentsMap
.end())
798 sExt
= CPathUtils::GetFileExtFromPath(m_Data
.m_theirFile
.GetFilename()).MakeLower();
799 sC
= m_IgnoreCommentsMap
.find(sExt
);
802 if (sC
!= m_IgnoreCommentsMap
.end())
803 m_Data
.SetCommentTokens(std::get
<0>(sC
->second
), std::get
<1>(sC
->second
), std::get
<2>(sC
->second
));
805 m_Data
.SetCommentTokens(L
"", L
"", L
"");
808 m_pwndLeftView
->BuildAllScreen2ViewVector();
809 m_pwndLeftView
->DocumentUpdated();
810 m_pwndRightView
->DocumentUpdated();
811 m_pwndBottomView
->DocumentUpdated();
812 m_wndLocatorBar
.DocumentUpdated();
813 m_wndLineDiffBar
.DocumentUpdated();
814 ::MessageBox(m_hWnd
, m_Data
.GetError(), _T("TortoiseGitMerge"), MB_ICONERROR
);
815 m_Data
.m_mergedFile
.SetOutOfUse();
816 m_bSaveRequired
= false;
820 m_pwndLeftView
->BuildAllScreen2ViewVector();
821 m_pwndLeftView
->DocumentUpdated();
822 m_pwndRightView
->DocumentUpdated();
823 m_pwndBottomView
->DocumentUpdated();
824 m_wndLocatorBar
.DocumentUpdated();
825 m_wndLineDiffBar
.DocumentUpdated();
827 m_pwndLeftView
->SetWritable(false);
828 m_pwndLeftView
->SetWritableIsChangable(false);
829 m_pwndLeftView
->SetTarget(false);
830 m_pwndRightView
->SetWritable(false);
831 m_pwndRightView
->SetWritableIsChangable(false);
832 m_pwndRightView
->SetTarget(false);
833 m_pwndBottomView
->SetWritable(false);
834 m_pwndBottomView
->SetWritableIsChangable(false);
835 m_pwndBottomView
->SetTarget(false);
837 if (!m_Data
.IsBaseFileInUse())
839 CSysProgressDlg progDlg
;
840 if (m_Data
.IsYourFileInUse() && m_Data
.IsTheirFileInUse())
842 m_Data
.m_baseFile
.TransferDetailsFrom(m_Data
.m_theirFile
);
844 else if ((!m_Data
.m_sDiffFile
.IsEmpty())&&(!m_Patch
.Init(m_Data
.m_sDiffFile
, m_Data
.m_sPatchPath
, &progDlg
)))
847 ClearViewNamesAndPaths();
848 MessageBox(m_Patch
.GetErrorMessage(), NULL
, MB_ICONERROR
);
849 m_bSaveRequired
= false;
853 if (m_Patch
.GetNumberOfFiles() > 0)
855 CString betterpatchpath
= m_Patch
.CheckPatchPath(m_Data
.m_sPatchPath
);
856 if (betterpatchpath
.CompareNoCase(m_Data
.m_sPatchPath
)!=0)
859 msg
.Format(IDS_WARNBETTERPATCHPATHFOUND
, (LPCTSTR
)m_Data
.m_sPatchPath
, (LPCTSTR
)betterpatchpath
);
860 if (m_bUseTaskDialog
)
862 CTaskDialog
taskdlg(msg
,
863 CString(MAKEINTRESOURCE(IDS_WARNBETTERPATCHPATHFOUND_TASK2
)),
866 TDF_ENABLE_HYPERLINKS
|TDF_USE_COMMAND_LINKS
|TDF_ALLOW_DIALOG_CANCELLATION
|TDF_POSITION_RELATIVE_TO_WINDOW
);
868 WCHAR t3
[MAX_PATH
] = {0};
869 CString cp
= betterpatchpath
.Left(MAX_PATH
-1);
870 PathCompactPathEx(t3
, cp
, 50, 0);
871 task3
.Format(IDS_WARNBETTERPATCHPATHFOUND_TASK3
, t3
);
872 taskdlg
.AddCommandControl(1, task3
);
874 WCHAR t4
[MAX_PATH
] = {0};
875 cp
= m_Data
.m_sPatchPath
.Left(MAX_PATH
-1);
876 PathCompactPathEx(t4
, cp
, 50, 0);
877 task4
.Format(IDS_WARNBETTERPATCHPATHFOUND_TASK4
, t4
);
878 taskdlg
.AddCommandControl(2, task4
);
879 taskdlg
.SetDefaultCommandControl(1);
880 taskdlg
.SetMainIcon(TD_INFORMATION_ICON
);
881 taskdlg
.SetCommonButtons(TDCBF_CANCEL_BUTTON
);
882 if (taskdlg
.DoModal(m_hWnd
) == 1)
884 m_Data
.m_sPatchPath
= betterpatchpath
;
885 m_Patch
.Init(m_Data
.m_sDiffFile
, m_Data
.m_sPatchPath
, &progDlg
);
888 else if (::MessageBox(m_hWnd
, msg
, _T("TortoiseGitMerge"), MB_ICONQUESTION
| MB_YESNO
)==IDYES
)
890 m_Data
.m_sPatchPath
= betterpatchpath
;
891 m_Patch
.Init(m_Data
.m_sDiffFile
, m_Data
.m_sPatchPath
, &progDlg
);
894 m_dlgFilePatches
.Init(&m_Patch
, this, m_Data
.m_sPatchPath
, this);
895 m_dlgFilePatches
.ShowWindow(SW_SHOW
);
896 ClearViewNamesAndPaths();
897 if (!m_wndSplitter
.IsRowHidden(1))
898 m_wndSplitter
.HideRow(1);
899 m_pwndLeftView
->SetHidden(FALSE
);
900 m_pwndRightView
->SetHidden(FALSE
);
901 m_pwndBottomView
->SetHidden(TRUE
);
904 if (m_Data
.IsBaseFileInUse() && !m_Data
.IsYourFileInUse() && m_Data
.IsTheirFileInUse())
906 m_Data
.m_yourFile
.TransferDetailsFrom(m_Data
.m_theirFile
);
908 if (m_Data
.IsBaseFileInUse() && m_Data
.IsYourFileInUse() && !m_Data
.IsTheirFileInUse())
910 //diff between YOUR and BASE
913 pwndActiveView
= m_pwndLeftView
;
914 if (!m_wndSplitter2
.IsColumnHidden(1))
915 m_wndSplitter2
.HideColumn(1);
917 m_pwndLeftView
->m_pViewData
= &m_Data
.m_YourBaseBoth
;
918 m_pwndLeftView
->SetTextType(m_Data
.m_arYourFile
.GetUnicodeType());
919 m_pwndLeftView
->SetLineEndingStyle(m_Data
.m_arYourFile
.GetLineEndings());
920 m_pwndLeftView
->m_sWindowName
= m_Data
.m_baseFile
.GetWindowName() + _T(" - ") + m_Data
.m_yourFile
.GetWindowName();
921 m_pwndLeftView
->m_sFullFilePath
= m_Data
.m_baseFile
.GetFilename() + _T(" - ") + m_Data
.m_yourFile
.GetFilename();
922 m_pwndLeftView
->m_pWorkingFile
= &m_Data
.m_yourFile
;
923 m_pwndLeftView
->SetTarget();
924 m_pwndLeftView
->SetWritableIsChangable(true);
926 m_pwndRightView
->m_pViewData
= NULL
;
927 m_pwndRightView
->m_pWorkingFile
= NULL
;
928 m_pwndBottomView
->m_pViewData
= NULL
;
929 m_pwndBottomView
->m_pWorkingFile
= NULL
;
931 if (!m_wndSplitter
.IsRowHidden(1))
932 m_wndSplitter
.HideRow(1);
933 m_pwndLeftView
->SetHidden(FALSE
);
934 m_pwndRightView
->SetHidden(TRUE
);
935 m_pwndBottomView
->SetHidden(TRUE
);
936 ::SetWindowPos(m_pwndLeftView
->m_hWnd
, NULL
, 0, 0, 0, 0, SWP_FRAMECHANGED
| SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOSIZE
);
940 pwndActiveView
= m_pwndRightView
;
941 if (m_wndSplitter2
.IsColumnHidden(1))
942 m_wndSplitter2
.ShowColumn();
944 m_pwndLeftView
->m_pViewData
= &m_Data
.m_YourBaseLeft
;
945 m_pwndLeftView
->SetTextType(m_Data
.m_arBaseFile
.GetUnicodeType());
946 m_pwndLeftView
->SetLineEndingStyle(m_Data
.m_arBaseFile
.GetLineEndings());
947 m_pwndLeftView
->m_sWindowName
= m_Data
.m_baseFile
.GetWindowName();
948 m_pwndLeftView
->m_sFullFilePath
= m_Data
.m_baseFile
.GetFilename();
949 m_pwndLeftView
->m_sConvertedFilePath
= m_Data
.m_baseFile
.GetConvertedFileName();
950 m_pwndLeftView
->m_pWorkingFile
= &m_Data
.m_baseFile
;
951 m_pwndLeftView
->SetWritableIsChangable(true);
953 m_pwndRightView
->m_pViewData
= &m_Data
.m_YourBaseRight
;
954 m_pwndRightView
->SetTextType(m_Data
.m_arYourFile
.GetUnicodeType());
955 m_pwndRightView
->SetLineEndingStyle(m_Data
.m_arYourFile
.GetLineEndings());
956 m_pwndRightView
->m_sWindowName
= m_Data
.m_yourFile
.GetWindowName();
957 m_pwndRightView
->m_sFullFilePath
= m_Data
.m_yourFile
.GetFilename();
958 m_pwndRightView
->m_sConvertedFilePath
= m_Data
.m_yourFile
.GetConvertedFileName();
959 m_pwndRightView
->m_pWorkingFile
= &m_Data
.m_yourFile
;
960 m_pwndRightView
->SetWritable();
961 m_pwndRightView
->SetTarget();
963 m_pwndBottomView
->m_pViewData
= NULL
;
964 m_pwndBottomView
->m_pWorkingFile
= NULL
;
966 if (!m_wndSplitter
.IsRowHidden(1))
967 m_wndSplitter
.HideRow(1);
968 m_pwndLeftView
->SetHidden(FALSE
);
969 m_pwndRightView
->SetHidden(FALSE
);
970 m_pwndBottomView
->SetHidden(TRUE
);
972 bool hasMods
, hasConflicts
, hasWhitespaceMods
;
973 pwndActiveView
->CheckModifications(hasMods
, hasConflicts
, hasWhitespaceMods
);
974 if (!hasMods
&& !hasConflicts
)
976 // files appear identical, show a dialog informing the user that there are or might
977 // be other differences
978 bool hasEncodingDiff
= m_Data
.m_arBaseFile
.GetUnicodeType() != m_Data
.m_arYourFile
.GetUnicodeType();
979 bool hasEOLDiff
= m_Data
.m_arBaseFile
.GetLineEndings() != m_Data
.m_arYourFile
.GetLineEndings();
980 if (hasWhitespaceMods
|| hasEncodingDiff
|| hasEOLDiff
)
982 // text is identical, but the files do not match
983 CString
sWarning(MAKEINTRESOURCE(IDS_TEXTIDENTICAL_MAIN
));
984 CString
sWhitespace(MAKEINTRESOURCE(IDS_TEXTIDENTICAL_WHITESPACE
));
985 CString
sEncoding(MAKEINTRESOURCE(IDS_TEXTIDENTICAL_ENCODING
));
986 CString
sEOL(MAKEINTRESOURCE(IDS_TEXTIDENTICAL_EOL
));
987 if (hasWhitespaceMods
)
990 sWarning
+= sWhitespace
;
995 sWarning
+= sEncoding
;
997 sWarning
+= m_Data
.m_arBaseFile
.GetEncodingName(m_Data
.m_arBaseFile
.GetUnicodeType());
999 sWarning
+= m_Data
.m_arYourFile
.GetEncodingName(m_Data
.m_arYourFile
.GetUnicodeType());
1004 sWarning
+= L
"\r\n";
1007 AfxMessageBox(sWarning
, MB_ICONINFORMATION
);
1011 else if (m_Data
.IsBaseFileInUse() && m_Data
.IsYourFileInUse() && m_Data
.IsTheirFileInUse())
1013 //diff between THEIR, YOUR and BASE
1014 m_pwndBottomView
->SetWritable();
1015 m_pwndBottomView
->SetTarget();
1016 pwndActiveView
= m_pwndBottomView
;
1018 m_pwndLeftView
->m_pViewData
= &m_Data
.m_TheirBaseBoth
;
1019 m_pwndLeftView
->SetTextType(m_Data
.m_arTheirFile
.GetUnicodeType());
1020 m_pwndLeftView
->SetLineEndingStyle(m_Data
.m_arTheirFile
.GetLineEndings());
1021 m_pwndLeftView
->m_sWindowName
.LoadString(IDS_VIEWTITLE_THEIRS
);
1022 m_pwndLeftView
->m_sWindowName
+= _T(" - ") + m_Data
.m_theirFile
.GetWindowName();
1023 m_pwndLeftView
->m_sFullFilePath
= m_Data
.m_theirFile
.GetFilename();
1024 m_pwndLeftView
->m_sConvertedFilePath
= m_Data
.m_theirFile
.GetConvertedFileName();
1025 m_pwndLeftView
->m_pWorkingFile
= &m_Data
.m_theirFile
;
1027 m_pwndRightView
->m_pViewData
= &m_Data
.m_YourBaseBoth
;
1028 m_pwndRightView
->SetTextType(m_Data
.m_arYourFile
.GetUnicodeType());
1029 m_pwndRightView
->SetLineEndingStyle(m_Data
.m_arYourFile
.GetLineEndings());
1030 m_pwndRightView
->m_sWindowName
.LoadString(IDS_VIEWTITLE_MINE
);
1031 m_pwndRightView
->m_sWindowName
+= _T(" - ") + m_Data
.m_yourFile
.GetWindowName();
1032 m_pwndRightView
->m_sFullFilePath
= m_Data
.m_yourFile
.GetFilename();
1033 m_pwndRightView
->m_sConvertedFilePath
= m_Data
.m_yourFile
.GetConvertedFileName();
1034 m_pwndRightView
->m_pWorkingFile
= &m_Data
.m_yourFile
;
1036 m_pwndBottomView
->m_pViewData
= &m_Data
.m_Diff3
;
1037 m_pwndBottomView
->SetTextType(m_Data
.m_arTheirFile
.GetUnicodeType());
1038 m_pwndBottomView
->SetLineEndingStyle(m_Data
.m_arTheirFile
.GetLineEndings());
1039 m_pwndBottomView
->m_sWindowName
.LoadString(IDS_VIEWTITLE_MERGED
);
1040 m_pwndBottomView
->m_sWindowName
+= _T(" - ") + m_Data
.m_mergedFile
.GetWindowName();
1041 m_pwndBottomView
->m_sFullFilePath
= m_Data
.m_mergedFile
.GetFilename();
1042 m_pwndBottomView
->m_sConvertedFilePath
= m_Data
.m_mergedFile
.GetConvertedFileName();
1043 m_pwndBottomView
->m_pWorkingFile
= &m_Data
.m_mergedFile
;
1045 if (m_wndSplitter2
.IsColumnHidden(1))
1046 m_wndSplitter2
.ShowColumn();
1047 if (m_wndSplitter
.IsRowHidden(1))
1048 m_wndSplitter
.ShowRow();
1049 m_pwndLeftView
->SetHidden(FALSE
);
1050 m_pwndRightView
->SetHidden(FALSE
);
1051 m_pwndBottomView
->SetHidden(FALSE
);
1052 // in three pane view, hide the line diff bar
1053 m_wndLineDiffBar
.ShowPane(false, false, true);
1054 m_wndLineDiffBar
.DocumentUpdated();
1056 if (!m_Data
.m_mergedFile
.InUse())
1058 m_Data
.m_mergedFile
.SetFileName(m_Data
.m_yourFile
.GetFilename());
1060 m_pwndLeftView
->BuildAllScreen2ViewVector();
1061 m_pwndLeftView
->DocumentUpdated();
1062 m_pwndRightView
->DocumentUpdated();
1063 m_pwndBottomView
->DocumentUpdated();
1064 m_wndLocatorBar
.DocumentUpdated();
1065 m_wndLineDiffBar
.DocumentUpdated();
1067 SetActiveView(pwndActiveView
);
1069 if ((line
>= -1) && m_pwndRightView
->m_pViewData
)
1071 int n
= line
== -1 ? min( nOldLineNumber
, nOldLine
) : line
;
1073 n
= m_pwndRightView
->m_pViewData
->FindLineNumber(n
);
1077 m_pwndRightView
->ScrollAllToLine(n
);
1081 if ((ptOldCaretPos
.x
>= 0) || (ptOldCaretPos
.y
>= 0))
1083 m_pwndLeftView
->SetCaretPosition(p
);
1084 m_pwndRightView
->SetCaretPosition(p
);
1085 m_pwndBottomView
->SetCaretPosition(p
);
1086 m_pwndBottomView
->ScrollToChar(0);
1087 m_pwndLeftView
->ScrollToChar(0);
1088 m_pwndRightView
->ScrollToChar(0);
1092 CRegDWORD regFirstDiff
= CRegDWORD(_T("Software\\TortoiseGitMerge\\FirstDiffOnLoad"), TRUE
);
1093 CRegDWORD regFirstConflict
= CRegDWORD(_T("Software\\TortoiseGitMerge\\FirstConflictOnLoad"), TRUE
);
1094 bool bGoFirstDiff
= (0 != (DWORD
)regFirstDiff
);
1095 bool bGoFirstConflict
= (0 != (DWORD
)regFirstConflict
);
1096 if (bGoFirstConflict
&& (CheckResolved()>=0))
1098 pwndActiveView
->GoToFirstConflict();
1099 // Ignore the first few Mouse Move messages, so that the line diff stays on
1100 // the first diff line until the user actually moves the mouse
1101 m_nMoveMovesToIgnore
= MOVESTOIGNORE
;
1103 else if (bGoFirstDiff
)
1105 pwndActiveView
->GoToFirstDifference();
1106 // Ignore the first few Mouse Move messages, so that the line diff stays on
1107 // the first diff line until the user actually moves the mouse
1108 m_nMoveMovesToIgnore
= MOVESTOIGNORE
;
1112 // Avoid incorrect rendering of active pane.
1113 m_pwndBottomView
->ScrollToChar(0);
1114 m_pwndLeftView
->ScrollToChar(0);
1115 m_pwndRightView
->ScrollToChar(0);
1119 if (m_bHasConflicts
&& !m_bSaveRequiredOnConflicts
)
1120 m_bSaveRequired
= false;
1121 CUndo::GetInstance().Clear();
1125 void CMainFrame::UpdateLayout()
1127 if (m_bInitSplitter
)
1129 m_wndSplitter
.CenterSplitter();
1130 m_wndSplitter2
.CenterSplitter();
1134 void CMainFrame::OnSize(UINT nType
, int cx
, int cy
)
1136 CFrameWndEx::OnSize(nType
, cx
, cy
);
1137 if (m_bInitSplitter
&& nType
!= SIZE_MINIMIZED
)
1139 if (m_wndSplitter
.GetSafeHwnd())
1141 if (m_wndSplitter
.HasOldRowSize() && (m_wndSplitter
.GetOldRowCount() == 2))
1143 int oldTotal
= m_wndSplitter
.GetOldRowSize(0) + m_wndSplitter
.GetOldRowSize(1);
1146 int cxCur0
, cxCur1
, cxMin0
, cxMin1
;
1147 m_wndSplitter
.GetRowInfo(0, cxCur0
, cxMin0
);
1148 m_wndSplitter
.GetRowInfo(1, cxCur1
, cxMin1
);
1149 cxCur0
= m_wndSplitter
.GetOldRowSize(0) * (cxCur0
+ cxCur1
) / oldTotal
;
1150 cxCur1
= m_wndSplitter
.GetOldRowSize(1) * (cxCur0
+ cxCur1
) / oldTotal
;
1151 m_wndSplitter
.SetRowInfo(0, cxCur0
, 0);
1152 m_wndSplitter
.SetRowInfo(1, cxCur1
, 0);
1153 m_wndSplitter
.RecalcLayout();
1157 if (m_wndSplitter2
.HasOldColSize() && (m_wndSplitter2
.GetOldColCount() == 2))
1159 int oldTotal
= m_wndSplitter2
.GetOldColSize(0) + m_wndSplitter2
.GetOldColSize(1);
1162 int cyCur0
, cyCur1
, cyMin0
, cyMin1
;
1163 m_wndSplitter2
.GetColumnInfo(0, cyCur0
, cyMin0
);
1164 m_wndSplitter2
.GetColumnInfo(1, cyCur1
, cyMin1
);
1165 cyCur0
= m_wndSplitter2
.GetOldColSize(0) * (cyCur0
+ cyCur1
) / oldTotal
;
1166 cyCur1
= m_wndSplitter2
.GetOldColSize(1) * (cyCur0
+ cyCur1
) / oldTotal
;
1167 m_wndSplitter2
.SetColumnInfo(0, cyCur0
, 0);
1168 m_wndSplitter2
.SetColumnInfo(1, cyCur1
, 0);
1169 m_wndSplitter2
.RecalcLayout();
1174 if ((nType
== SIZE_RESTORED
)&&m_bCheckReload
)
1176 m_bCheckReload
= false;
1180 // workaround for ribbon interface when the task bar is on the left or top
1181 // The bug has been fixed in VS2013
1182 // http://connect.microsoft.com/VisualStudio/feedback/details/791229/cmfcribbonbar-app-does-not-maximize-correctly-if-windows-7-taskbar-is-docked-on-left
1183 if (nType
== SIZE_MAXIMIZED
)
1185 HMONITOR hMon
= MonitorFromWindow(this->m_hWnd
, MONITOR_DEFAULTTONEAREST
);
1187 mix
.cbSize
= sizeof(MONITORINFOEX
);
1188 bool primary
= true; // assume primary monitor
1189 CRect
rect(0, 0, 0, 0);
1190 if (GetMonitorInfo(hMon
, &mix
))
1192 primary
= (mix
.dwFlags
== MONITORINFOF_PRIMARY
);
1197 ::SystemParametersInfo(SPI_GETWORKAREA
, 0, &rect
, 0);
1202 GetWindowPlacement(&wp
);
1203 if (wp
.ptMaxPosition
.x
|| wp
.ptMaxPosition
.y
)
1205 wp
.ptMaxPosition
.x
= wp
.ptMaxPosition
.y
= 0;
1206 SetWindowPlacement(&wp
);
1217 void CMainFrame::OnViewWhitespaces()
1219 CRegDWORD regViewWhitespaces
= CRegDWORD(_T("Software\\TortoiseGitMerge\\ViewWhitespaces"), 1);
1220 BOOL bViewWhitespaces
= regViewWhitespaces
;
1222 bViewWhitespaces
= m_pwndLeftView
->m_bViewWhitespace
;
1224 bViewWhitespaces
= !bViewWhitespaces
;
1225 regViewWhitespaces
= bViewWhitespaces
;
1228 m_pwndLeftView
->m_bViewWhitespace
= bViewWhitespaces
;
1229 m_pwndLeftView
->Invalidate();
1231 if (m_pwndRightView
)
1233 m_pwndRightView
->m_bViewWhitespace
= bViewWhitespaces
;
1234 m_pwndRightView
->Invalidate();
1236 if (m_pwndBottomView
)
1238 m_pwndBottomView
->m_bViewWhitespace
= bViewWhitespaces
;
1239 m_pwndBottomView
->Invalidate();
1243 void CMainFrame::OnUpdateViewWhitespaces(CCmdUI
*pCmdUI
)
1246 pCmdUI
->SetCheck(m_pwndLeftView
->m_bViewWhitespace
);
1249 void CMainFrame::OnViewCollapsed()
1251 m_regCollapsed
= !(DWORD
)m_regCollapsed
;
1252 m_bCollapsed
= !!(DWORD
)m_regCollapsed
;
1254 OnViewTextFoldUnfold();
1255 m_wndLocatorBar
.Invalidate();
1258 void CMainFrame::OnUpdateViewCollapsed(CCmdUI
*pCmdUI
)
1260 pCmdUI
->SetCheck(m_bCollapsed
);
1263 void CMainFrame::OnViewWraplonglines()
1265 m_bWrapLines
= !(DWORD
)m_regWrapLines
;
1266 m_regWrapLines
= m_bWrapLines
;
1268 if (m_pwndLeftView
) m_pwndLeftView
->WrapChanged();
1269 if (m_pwndRightView
) m_pwndRightView
->WrapChanged();
1270 if (m_pwndBottomView
) m_pwndBottomView
->WrapChanged();
1271 OnViewTextFoldUnfold();
1272 m_wndLocatorBar
.DocumentUpdated();
1275 void CMainFrame::OnViewTextFoldUnfold()
1277 OnViewTextFoldUnfold(m_pwndLeftView
);
1278 OnViewTextFoldUnfold(m_pwndRightView
);
1279 OnViewTextFoldUnfold(m_pwndBottomView
);
1282 void CMainFrame::OnViewTextFoldUnfold(CBaseView
* view
)
1286 view
->BuildAllScreen2ViewVector();
1287 view
->UpdateCaret();
1289 view
->EnsureCaretVisible();
1292 void CMainFrame::OnUpdateViewWraplonglines(CCmdUI
*pCmdUI
)
1294 pCmdUI
->SetCheck(m_bWrapLines
);
1297 void CMainFrame::OnViewOnewaydiff()
1299 if (CheckForSave(CHFSR_RELOAD
)==IDCANCEL
)
1301 m_bOneWay
= !m_bOneWay
;
1302 ShowDiffBar(!m_bOneWay
);
1306 void CMainFrame::ShowDiffBar(bool bShow
)
1310 // restore the line diff bar
1311 m_wndLineDiffBar
.ShowPane(m_bLineDiff
, false, true);
1312 m_wndLineDiffBar
.DocumentUpdated();
1313 m_wndLocatorBar
.ShowPane(m_bLocatorBar
, false, true);
1314 m_wndLocatorBar
.DocumentUpdated();
1318 // in one way view, hide the line diff bar
1319 m_wndLineDiffBar
.ShowPane(false, false, true);
1320 m_wndLineDiffBar
.DocumentUpdated();
1324 int CMainFrame::CheckResolved()
1326 //only in three way diffs can be conflicts!
1327 m_bHasConflicts
= true;
1328 if (IsViewGood(m_pwndBottomView
))
1330 CViewData
* viewdata
= m_pwndBottomView
->m_pViewData
;
1333 for (int i
=0; i
<viewdata
->GetCount(); i
++)
1335 const DiffStates state
= viewdata
->GetState(i
);
1336 if ((DIFFSTATE_CONFLICTED
== state
)||(DIFFSTATE_CONFLICTED_IGNORED
== state
))
1341 m_bHasConflicts
= false;
1345 int CMainFrame::SaveFile(const CString
& sFilePath
)
1347 CBaseView
* pView
= NULL
;
1348 CViewData
* pViewData
= NULL
;
1349 CFileTextLines
* pOriginFile
= &m_Data
.m_arBaseFile
;
1350 if (IsViewGood(m_pwndBottomView
))
1352 pView
= m_pwndBottomView
;
1353 pViewData
= m_pwndBottomView
->m_pViewData
;
1355 else if (IsViewGood(m_pwndRightView
))
1357 pView
= m_pwndRightView
;
1358 pViewData
= m_pwndRightView
->m_pViewData
;
1359 if (m_Data
.IsYourFileInUse())
1360 pOriginFile
= &m_Data
.m_arYourFile
;
1361 else if (m_Data
.IsTheirFileInUse())
1362 pOriginFile
= &m_Data
.m_arTheirFile
;
1370 if ((pViewData
)&&(pOriginFile
))
1372 CFileTextLines file
;
1373 pOriginFile
->CopySettings(&file
);
1374 CFileTextLines::SaveParams saveParams
;
1375 saveParams
.m_LineEndings
= pView
->GetLineEndings();
1376 saveParams
.m_UnicodeType
= pView
->GetTextType();
1377 file
.SetSaveParams(saveParams
);
1378 for (int i
=0; i
<pViewData
->GetCount(); i
++)
1380 //only copy non-removed lines
1381 DiffStates state
= pViewData
->GetState(i
);
1384 case DIFFSTATE_CONFLICTED
:
1385 case DIFFSTATE_CONFLICTED_IGNORED
:
1392 } while((last
<pViewData
->GetCount()) && ((pViewData
->GetState(last
)==DIFFSTATE_CONFLICTED
)||(pViewData
->GetState(last
)==DIFFSTATE_CONFLICTED_IGNORED
)));
1393 // TortoiseGitMerge changes here
1394 file
.Add(_T("<<<<<<< .mine"), m_pwndRightView
->GetLineEndings());
1395 for (int j
=first
; j
<last
; j
++)
1397 EOL lineending
= m_pwndRightView
->m_pViewData
->GetLineEnding(j
);
1398 if (lineending
== EOL_NOENDING
)
1399 lineending
= m_pwndRightView
->GetLineEndings();
1400 file
.Add(m_pwndRightView
->m_pViewData
->GetLine(j
), lineending
);
1402 file
.Add(_T("======="), m_pwndRightView
->GetLineEndings());
1403 for (int j
=first
; j
<last
; j
++)
1405 EOL lineending
= m_pwndLeftView
->m_pViewData
->GetLineEnding(j
);
1406 if (lineending
== EOL_NOENDING
)
1407 lineending
= m_pwndLeftView
->GetLineEndings();
1408 file
.Add(m_pwndLeftView
->m_pViewData
->GetLine(j
), lineending
);
1410 file
.Add(_T(">>>>>>> .theirs"), m_pwndRightView
->GetLineEndings());
1414 case DIFFSTATE_EMPTY
:
1415 case DIFFSTATE_CONFLICTEMPTY
:
1416 case DIFFSTATE_IDENTICALREMOVED
:
1417 case DIFFSTATE_REMOVED
:
1418 case DIFFSTATE_THEIRSREMOVED
:
1419 case DIFFSTATE_YOURSREMOVED
:
1420 case DIFFSTATE_CONFLICTRESOLVEDEMPTY
:
1421 // do not save removed lines
1424 file
.Add(pViewData
->GetLine(i
), pViewData
->GetLineEnding(i
));
1428 if (!file
.Save(sFilePath
, false, false))
1430 CMessageBox::Show(m_hWnd
, file
.GetErrorString(), _T("TortoiseGitMerge"), MB_ICONERROR
);
1433 if (sFilePath
== m_Data
.m_baseFile
.GetFilename())
1435 m_Data
.m_baseFile
.StoreFileAttributes();
1437 if (sFilePath
== m_Data
.m_theirFile
.GetFilename())
1439 m_Data
.m_theirFile
.StoreFileAttributes();
1441 if (sFilePath
== m_Data
.m_yourFile
.GetFilename())
1443 m_Data
.m_yourFile
.StoreFileAttributes();
1445 /*if (sFilePath == m_Data.m_mergedFile.GetFilename())
1447 m_Data.m_mergedFile.StoreFileAttributes();
1449 m_dlgFilePatches
.SetFileStatusAsPatched(sFilePath
);
1450 if (IsViewGood(m_pwndBottomView
))
1451 m_pwndBottomView
->SetModified(FALSE
);
1452 else if (IsViewGood(m_pwndRightView
))
1453 m_pwndRightView
->SetModified(FALSE
);
1454 CUndo::GetInstance().MarkAsOriginalState(
1456 IsViewGood(m_pwndRightView
) && (pViewData
== m_pwndRightView
->m_pViewData
),
1457 IsViewGood(m_pwndBottomView
) && (pViewData
== m_pwndBottomView
->m_pViewData
));
1458 if (file
.GetCount() == 1 && file
.GetAt(0).IsEmpty() && file
.GetLineEnding(0) == EOL_NOENDING
)
1460 return file
.GetCount();
1465 void CMainFrame::OnFileSave()
1467 // when multiple files are set as writable we have to ask what file to save
1468 int nEditableViewCount
=
1469 (CBaseView::IsViewGood(m_pwndLeftView
) && m_pwndLeftView
->IsWritable() ? 1 : 0)
1470 + (CBaseView::IsViewGood(m_pwndRightView
) && m_pwndRightView
->IsWritable() ? 1 : 0)
1471 + (CBaseView::IsViewGood(m_pwndBottomView
) && m_pwndBottomView
->IsWritable() ? 1 : 0);
1472 bool bLeftIsModified
= CBaseView::IsViewGood(m_pwndLeftView
) && m_pwndLeftView
->IsModified();
1473 bool bRightIsModified
= CBaseView::IsViewGood(m_pwndRightView
) && m_pwndRightView
->IsModified();
1474 bool bBottomIsModified
= CBaseView::IsViewGood(m_pwndBottomView
) && m_pwndBottomView
->IsModified();
1475 int nModifiedViewCount
=
1476 (bLeftIsModified
? 1 : 0)
1477 + (bRightIsModified
? 1 : 0)
1478 + (bBottomIsModified
? 1 : 0);
1479 if (nEditableViewCount
>1)
1481 if (nModifiedViewCount
== 1)
1483 if (bLeftIsModified
)
1484 m_pwndLeftView
->SaveFile(SAVE_REMOVEDLINES
);
1488 else if (nModifiedViewCount
>0)
1492 if (m_bUseTaskDialog
)
1494 CTaskDialog
taskdlg(CString(MAKEINTRESOURCE(IDS_SAVE_MORE
)),
1495 CString(MAKEINTRESOURCE(IDS_SAVE
)),
1496 CString(MAKEINTRESOURCE(IDS_APPNAME
)),
1498 TDF_ENABLE_HYPERLINKS
|TDF_USE_COMMAND_LINKS
|TDF_ALLOW_DIALOG_CANCELLATION
|TDF_POSITION_RELATIVE_TO_WINDOW
);
1500 if (m_pwndLeftView
->m_pWorkingFile
->InUse() && !m_pwndLeftView
->m_pWorkingFile
->IsReadonly())
1501 sTaskTemp
.Format(IDS_ASKFORSAVE_SAVELEFT
, (LPCTSTR
)m_pwndLeftView
->m_pWorkingFile
->GetFilename());
1503 sTaskTemp
= CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_SAVELEFTAS
));
1504 taskdlg
.AddCommandControl(201, sTaskTemp
, bLeftIsModified
);// left
1505 if (bLeftIsModified
) {
1506 taskdlg
.SetDefaultCommandControl(201);
1508 if (m_pwndRightView
->m_pWorkingFile
->InUse() && !m_pwndRightView
->m_pWorkingFile
->IsReadonly())
1509 sTaskTemp
.Format(IDS_ASKFORSAVE_SAVERIGHT
, (LPCTSTR
)m_pwndRightView
->m_pWorkingFile
->GetFilename());
1511 sTaskTemp
= CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_SAVERIGHTAS
));
1512 taskdlg
.AddCommandControl(202, sTaskTemp
, bRightIsModified
); // right
1513 if (bRightIsModified
) {
1514 taskdlg
.SetDefaultCommandControl(202);
1516 taskdlg
.AddCommandControl(203, CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_SAVEALL2
)), nModifiedViewCount
>1); // both
1517 if (nModifiedViewCount
>1) {
1518 taskdlg
.SetDefaultCommandControl(203);
1520 taskdlg
.SetCommonButtons(TDCBF_CANCEL_BUTTON
);
1521 taskdlg
.SetMainIcon(TD_WARNING_ICON
);
1522 ret
= (UINT
)taskdlg
.DoModal(m_hWnd
);
1526 m_pwndLeftView
->SaveFile(SAVE_REMOVEDLINES
);
1529 m_pwndLeftView
->SaveFile(SAVE_REMOVEDLINES
);
1531 m_pwndRightView
->SaveFile();
1539 // only target view was modified
1544 void CMainFrame::PatchSave()
1546 bool bDoesNotExist
= !PathFileExists(m_Data
.m_mergedFile
.GetFilename());
1547 if (m_Data
.m_bPatchRequired
)
1549 m_Patch
.PatchPath(m_Data
.m_mergedFile
.GetFilename());
1551 if (!PathIsDirectory(m_Data
.m_mergedFile
.GetFilename()))
1553 int saveret
= SaveFile(m_Data
.m_mergedFile
.GetFilename());
1556 // file was saved with 0 lines, remove it.
1557 m_Patch
.RemoveFile(m_Data
.m_mergedFile
.GetFilename());
1559 DeleteFile(m_Data
.m_mergedFile
.GetFilename());
1561 m_Data
.m_mergedFile
.StoreFileAttributes();
1562 if (m_Data
.m_mergedFile
.GetFilename() == m_Data
.m_yourFile
.GetFilename())
1563 m_Data
.m_yourFile
.StoreFileAttributes();
1564 if ((bDoesNotExist
)&&(DWORD(CRegDWORD(_T("Software\\TortoiseGitMerge\\AutoAdd"), TRUE
))))
1566 // call TortoiseProc to add the new file to version control
1567 CString cmd
= _T("/command:add /noui /path:\"");
1568 cmd
+= m_Data
.m_mergedFile
.GetFilename() + _T("\"");
1569 CAppUtils::RunTortoiseGitProc(cmd
);
1574 bool CMainFrame::FileSave(bool bCheckResolved
/*=true*/)
1576 if (!m_Data
.m_mergedFile
.InUse())
1577 return FileSaveAs(bCheckResolved
);
1578 // check if the file has the readonly attribute set
1579 bool bDoesNotExist
= false;
1580 DWORD fAttribs
= GetFileAttributes(m_Data
.m_mergedFile
.GetFilename());
1581 if ((fAttribs
!= INVALID_FILE_ATTRIBUTES
)&&(fAttribs
& FILE_ATTRIBUTE_READONLY
))
1582 return FileSaveAs(bCheckResolved
);
1583 if (fAttribs
== INVALID_FILE_ATTRIBUTES
)
1585 bDoesNotExist
= (GetLastError() == ERROR_FILE_NOT_FOUND
);
1587 if (bCheckResolved
&& HasConflictsWontKeep())
1590 if (((DWORD
)CRegDWORD(_T("Software\\TortoiseGitMerge\\Backup"))) != 0)
1592 MoveFileEx(m_Data
.m_mergedFile
.GetFilename(), m_Data
.m_mergedFile
.GetFilename() + _T(".bak"), MOVEFILE_COPY_ALLOWED
| MOVEFILE_REPLACE_EXISTING
| MOVEFILE_WRITE_THROUGH
);
1594 if (m_Data
.m_bPatchRequired
)
1596 m_Patch
.PatchPath(m_Data
.m_mergedFile
.GetFilename());
1598 int saveret
= SaveFile(m_Data
.m_mergedFile
.GetFilename());
1601 // file was saved with 0 lines!
1602 // ask the user if the file should be deleted
1603 bool bDelete
= false;
1604 if (m_bUseTaskDialog
)
1607 msg
.Format(IDS_DELETEWHENEMPTY
, (LPCTSTR
)CPathUtils::GetFileNameFromPath(m_Data
.m_mergedFile
.GetFilename()));
1608 CTaskDialog
taskdlg(msg
,
1609 CString(MAKEINTRESOURCE(IDS_DELETEWHENEMPTY_TASK2
)),
1610 CString(MAKEINTRESOURCE(IDS_APPNAME
)),
1612 TDF_ENABLE_HYPERLINKS
|TDF_USE_COMMAND_LINKS
|TDF_ALLOW_DIALOG_CANCELLATION
|TDF_POSITION_RELATIVE_TO_WINDOW
);
1613 taskdlg
.AddCommandControl(1, CString(MAKEINTRESOURCE(IDS_DELETEWHENEMPTY_TASK3
)));
1614 taskdlg
.AddCommandControl(2, CString(MAKEINTRESOURCE(IDS_DELETEWHENEMPTY_TASK4
)));
1615 taskdlg
.SetCommonButtons(TDCBF_CANCEL_BUTTON
);
1616 taskdlg
.SetDefaultCommandControl(1);
1617 taskdlg
.SetMainIcon(TD_WARNING_ICON
);
1618 bDelete
= (taskdlg
.DoModal(m_hWnd
) == 1);
1623 sTemp
.Format(IDS_DELETEWHENEMPTY
, (LPCTSTR
)m_Data
.m_mergedFile
.GetFilename());
1624 bDelete
= (CMessageBox::ShowCheck(m_hWnd
, sTemp
, _T("TortoiseGitMerge"), MB_YESNO
, _T("DeleteFileWhenEmpty")) == IDYES
);
1628 m_Patch
.RemoveFile(m_Data
.m_mergedFile
.GetFilename());
1629 DeleteFile(m_Data
.m_mergedFile
.GetFilename());
1632 else if (saveret
< 0)
1634 // error while saving the file
1638 // if we're in conflict resolve mode (three pane view), check if there are no more conflicts
1639 // and if there aren't, ask to mark the file as resolved
1640 if (IsViewGood(m_pwndBottomView
) && !m_bHasConflicts
&& bCheckResolved
)
1642 CString projectRoot
;
1643 if (g_GitAdminDir
.HasAdminDir(m_Data
.m_mergedFile
.GetFilename(), false, &projectRoot
))
1645 CString subpath
= m_Data
.m_mergedFile
.GetFilename();
1646 subpath
.Replace(_T('\\'), _T('/'));
1647 if (subpath
.GetLength() >= projectRoot
.GetLength())
1649 if (subpath
[projectRoot
.GetLength()] == _T('/'))
1650 subpath
= subpath
.Right(subpath
.GetLength() - projectRoot
.GetLength() - 1);
1652 subpath
= subpath
.Right(subpath
.GetLength() - projectRoot
.GetLength());
1655 CAutoRepository
repository(projectRoot
);
1656 bool hasConflictInIndex
= false;
1663 if (git_repository_index(index
.GetPointer(), repository
))
1666 CStringA path
= CUnicodeUtils::GetMulti(subpath
, CP_UTF8
);
1667 const git_index_entry
* entry
= git_index_get_bypath(index
, path
, 1);
1668 hasConflictInIndex
= entry
!= nullptr;
1671 if (hasConflictInIndex
)
1673 bool bResolve
= false;
1674 if (m_bUseTaskDialog
)
1677 msg
.Format(IDS_MARKASRESOLVED
, (LPCTSTR
)CPathUtils::GetFileNameFromPath(m_Data
.m_mergedFile
.GetFilename()));
1678 CTaskDialog
taskdlg(msg
,
1679 CString(MAKEINTRESOURCE(IDS_MARKASRESOLVED_TASK2
)),
1680 CString(MAKEINTRESOURCE(IDS_APPNAME
)),
1682 TDF_ENABLE_HYPERLINKS
|TDF_USE_COMMAND_LINKS
|TDF_ALLOW_DIALOG_CANCELLATION
|TDF_POSITION_RELATIVE_TO_WINDOW
);
1683 taskdlg
.AddCommandControl(1, CString(MAKEINTRESOURCE(IDS_MARKASRESOLVED_TASK3
)));
1684 taskdlg
.AddCommandControl(2, CString(MAKEINTRESOURCE(IDS_MARKASRESOLVED_TASK4
)));
1685 taskdlg
.SetCommonButtons(TDCBF_CANCEL_BUTTON
);
1686 taskdlg
.SetDefaultCommandControl(1);
1687 taskdlg
.SetMainIcon(TD_WARNING_ICON
);
1688 bResolve
= (taskdlg
.DoModal(m_hWnd
) == 1);
1693 sTemp
.Format(IDS_MARKASRESOLVED
, (LPCTSTR
)CPathUtils::GetFileNameFromPath(m_Data
.m_mergedFile
.GetFilename()));
1694 bResolve
= (CMessageBox::Show(m_hWnd
, sTemp
, _T("TortoiseGitMerge"), MB_YESNO
| MB_ICONQUESTION
) == IDYES
);
1704 m_bSaveRequired
= false;
1705 m_Data
.m_mergedFile
.StoreFileAttributes();
1707 if ((bDoesNotExist
)&&(DWORD(CRegDWORD(_T("Software\\TortoiseGitMerge\\AutoAdd"), TRUE
))))
1709 // call TortoiseProc to add the new file to version control
1710 CString cmd
= _T("/command:add /noui /path:\"");
1711 cmd
+= m_Data
.m_mergedFile
.GetFilename() + _T("\"");
1712 if(!CAppUtils::RunTortoiseGitProc(cmd
))
1718 void CMainFrame::OnFileSaveAs()
1720 if (m_bUseTaskDialog
)
1722 // ask what file to save as
1723 bool bHaveConflict
= (CheckResolved() >= 0);
1724 CTaskDialog
taskdlg(
1725 CString(MAKEINTRESOURCE(bHaveConflict
? IDS_ASKFORSAVEAS_MORECONFLICT
: IDS_ASKFORSAVEAS_MORE
)),
1726 CString(MAKEINTRESOURCE(IDS_ASKFORSAVEAS
)),
1727 CString(MAKEINTRESOURCE(IDS_APPNAME
)),
1729 TDF_ENABLE_HYPERLINKS
|TDF_USE_COMMAND_LINKS
|TDF_ALLOW_DIALOG_CANCELLATION
|TDF_POSITION_RELATIVE_TO_WINDOW
);
1730 // default can be last view (target) as was in 1.7 or actual (where is cursor) as is in most text editor
1731 if (IsViewGood(m_pwndLeftView
))
1733 taskdlg
.AddCommandControl(201, CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_SAVELEFTAS
))); // left
1734 taskdlg
.SetDefaultCommandControl(201);
1736 if (IsViewGood(m_pwndRightView
))
1738 taskdlg
.AddCommandControl(202, CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_SAVERIGHTAS
))); // right
1739 taskdlg
.SetDefaultCommandControl(202);
1741 if (IsViewGood(m_pwndBottomView
))
1743 taskdlg
.AddCommandControl(203, CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_SAVEBOTTOMAS
))); // bottom
1744 taskdlg
.SetDefaultCommandControl(203);
1748 taskdlg
.AddCommandControl(204, CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_NEEDRESOLVE
))); // resolve
1749 taskdlg
.SetDefaultCommandControl(204);
1751 taskdlg
.SetCommonButtons(TDCBF_CANCEL_BUTTON
);
1752 taskdlg
.SetMainIcon(bHaveConflict
? TD_WARNING_ICON
: TD_INFORMATION_ICON
);
1753 int nCommand
= (int)taskdlg
.DoModal(m_hWnd
);
1758 if (TryGetFileName(sFileName
))
1760 // in 2, 3 view display we want to keep removed lines
1761 m_pwndLeftView
->SaveFileTo(sFileName
, IsViewGood(m_pwndRightView
) ? SAVE_REMOVEDLINES
: 0);
1765 if (TryGetFileName(sFileName
))
1767 m_pwndRightView
->SaveFileTo(sFileName
);
1773 case 204: // continue resolving
1774 if (m_pwndBottomView
)
1776 m_pwndBottomView
->GoToLine(CheckResolved());
1783 int nEditableViewCount
=
1784 (CBaseView::IsViewGood(m_pwndLeftView
) && m_pwndLeftView
->IsWritable() ? 1 : 0)
1785 + (CBaseView::IsViewGood(m_pwndRightView
) && m_pwndRightView
->IsWritable() ? 1 : 0)
1786 + (CBaseView::IsViewGood(m_pwndBottomView
) && m_pwndBottomView
->IsWritable() ? 1 : 0);
1787 bool bLeftIsModified
= CBaseView::IsViewGood(m_pwndLeftView
) && m_pwndLeftView
->IsModified();
1788 bool bRightIsModified
= CBaseView::IsViewGood(m_pwndRightView
) && m_pwndRightView
->IsModified();
1789 bool bBottomIsModified
= CBaseView::IsViewGood(m_pwndBottomView
) && m_pwndBottomView
->IsModified();
1790 int nModifiedViewCount
=
1791 (bLeftIsModified
? 1 : 0)
1792 + (bRightIsModified
? 1 : 0)
1793 + (bBottomIsModified
? 1 : 0);
1794 if (nEditableViewCount
>1)
1796 if (nModifiedViewCount
== 1)
1798 if (bLeftIsModified
)
1801 if (TryGetFileName(sFileName
))
1803 m_pwndLeftView
->SaveFileTo(sFileName
);
1813 if (TryGetFileName(sFileName
))
1815 m_pwndLeftView
->SaveFileTo(sFileName
);
1822 bool CMainFrame::FileSaveAs(bool bCheckResolved
/*=true*/)
1824 if (bCheckResolved
&& HasConflictsWontKeep())
1828 if(!TryGetFileName(fileName
))
1835 void CMainFrame::OnUpdateFileSave(CCmdUI
*pCmdUI
)
1837 BOOL bEnable
= FALSE
;
1838 if (m_Data
.m_mergedFile
.InUse())
1840 if (IsViewGood(m_pwndBottomView
)&&(m_pwndBottomView
->m_pViewData
))
1842 else if ( (IsViewGood(m_pwndRightView
)&&(m_pwndRightView
->m_pViewData
)) &&
1843 (m_pwndRightView
->IsModified() || (m_Data
.m_yourFile
.GetWindowName().Right(9).Compare(_T(": patched"))==0)) )
1845 else if (IsViewGood(m_pwndLeftView
)
1846 && (m_pwndLeftView
->m_pViewData
)
1847 && (m_pwndLeftView
->IsModified()))
1850 pCmdUI
->Enable(bEnable
);
1853 void CMainFrame::OnUpdateFileSaveAs(CCmdUI
*pCmdUI
)
1855 // any file is open we can save it as
1856 BOOL bEnable
= FALSE
;
1857 if (IsViewGood(m_pwndBottomView
)&&(m_pwndBottomView
->m_pViewData
))
1859 else if (IsViewGood(m_pwndRightView
)&&(m_pwndRightView
->m_pViewData
))
1861 else if (IsViewGood(m_pwndLeftView
)&&(m_pwndLeftView
->m_pViewData
))
1863 pCmdUI
->Enable(bEnable
);
1866 void CMainFrame::OnUpdateViewOnewaydiff(CCmdUI
*pCmdUI
)
1868 pCmdUI
->SetCheck(!m_bOneWay
);
1869 BOOL bEnable
= TRUE
;
1870 if (IsViewGood(m_pwndBottomView
))
1874 pCmdUI
->Enable(bEnable
);
1877 void CMainFrame::OnViewOptions()
1880 sTemp
.LoadString(IDS_SETTINGSTITLE
);
1881 CSettings
dlg(sTemp
);
1883 if (dlg
.IsReloadNeeded())
1885 if (CheckForSave(CHFSR_OPTIONS
)==IDCANCEL
)
1887 CDiffColors::GetInstance().LoadRegistry();
1891 CDiffColors::GetInstance().LoadRegistry();
1892 if (m_pwndBottomView
)
1893 m_pwndBottomView
->Invalidate();
1895 m_pwndLeftView
->Invalidate();
1896 if (m_pwndRightView
)
1897 m_pwndRightView
->Invalidate();
1900 void CMainFrame::OnClose()
1902 if (CheckForSave(CHFSR_CLOSE
)!=IDCANCEL
)
1906 // before it is destroyed, save the position of the window
1907 wp
.length
= sizeof wp
;
1909 if (GetWindowPlacement(&wp
))
1913 // never restore to Iconic state
1914 wp
.showCmd
= SW_SHOW
;
1916 if ((wp
.flags
& WPF_RESTORETOMAXIMIZED
) != 0)
1917 // if maximized and maybe iconic restore maximized state
1918 wp
.showCmd
= SW_SHOWMAXIMIZED
;
1921 WriteWindowPlacement(&wp
);
1927 void CMainFrame::OnActivate(UINT nValue
, CWnd
* /*pwnd*/, BOOL
/*bActivated?*/)
1929 if (nValue
!= 0) // activated
1933 m_bCheckReload
= TRUE
;
1937 // use a timer to give other messages time to get processed
1938 // first, like e.g. the WM_CLOSE message in case the user
1939 // clicked the close button and that brought the window
1940 // to the front - in that case checking for reload wouldn't
1942 SetTimer(IDT_RELOADCHECKTIMER
, 300, NULL
);
1947 void CMainFrame::OnViewLinedown()
1949 OnViewLineUpDown(1);
1952 void CMainFrame::OnViewLineup()
1954 OnViewLineUpDown(-1);
1957 void CMainFrame::OnViewLineUpDown(int direction
)
1960 m_pwndLeftView
->ScrollToLine(m_pwndLeftView
->m_nTopLine
+direction
);
1961 if (m_pwndRightView
)
1962 m_pwndRightView
->ScrollToLine(m_pwndRightView
->m_nTopLine
+direction
);
1963 if (m_pwndBottomView
)
1964 m_pwndBottomView
->ScrollToLine(m_pwndBottomView
->m_nTopLine
+direction
);
1965 m_wndLocatorBar
.Invalidate();
1966 m_nMoveMovesToIgnore
= MOVESTOIGNORE
;
1969 void CMainFrame::OnViewLineleft()
1971 OnViewLineLeftRight(-1);
1974 void CMainFrame::OnViewLineright()
1976 OnViewLineLeftRight(1);
1979 void CMainFrame::OnViewLineLeftRight(int direction
)
1982 m_pwndLeftView
->ScrollSide(direction
);
1983 if (m_pwndRightView
)
1984 m_pwndRightView
->ScrollSide(direction
);
1985 if (m_pwndBottomView
)
1986 m_pwndBottomView
->ScrollSide(direction
);
1989 void CMainFrame::OnEditUseTheirs()
1991 if (m_pwndBottomView
)
1992 m_pwndBottomView
->UseTheirTextBlock();
1994 void CMainFrame::OnUpdateEditUsetheirblock(CCmdUI
*pCmdUI
)
1996 pCmdUI
->Enable(m_pwndBottomView
&& m_pwndBottomView
->HasSelection());
1999 void CMainFrame::OnEditUseMine()
2001 if (m_pwndBottomView
)
2002 m_pwndBottomView
->UseMyTextBlock();
2004 void CMainFrame::OnUpdateEditUsemyblock(CCmdUI
*pCmdUI
)
2006 OnUpdateEditUsetheirblock(pCmdUI
);
2009 void CMainFrame::OnEditUseTheirsThenMine()
2011 if (m_pwndBottomView
)
2012 m_pwndBottomView
->UseTheirAndYourBlock();
2015 void CMainFrame::OnUpdateEditUsetheirthenmyblock(CCmdUI
*pCmdUI
)
2017 OnUpdateEditUsetheirblock(pCmdUI
);
2020 void CMainFrame::OnEditUseMineThenTheirs()
2022 if (m_pwndBottomView
)
2023 m_pwndBottomView
->UseYourAndTheirBlock();
2026 void CMainFrame::OnUpdateEditUseminethentheirblock(CCmdUI
*pCmdUI
)
2028 OnUpdateEditUsetheirblock(pCmdUI
);
2031 void CMainFrame::OnEditUseleftblock()
2033 if (m_pwndBottomView
->IsWindowVisible())
2034 m_pwndBottomView
->UseRightBlock();
2036 m_pwndRightView
->UseLeftBlock();
2039 void CMainFrame::OnUpdateEditUseleftblock(CCmdUI
*pCmdUI
)
2041 pCmdUI
->Enable(IsViewGood(m_pwndRightView
) && m_pwndRightView
->IsTarget() && m_pwndRightView
->HasSelection());
2044 void CMainFrame::OnUpdateUseBlock(CCmdUI
*pCmdUI
)
2046 pCmdUI
->Enable(TRUE
);
2049 void CMainFrame::OnEditUseleftfile()
2051 if (m_pwndBottomView
->IsWindowVisible())
2052 m_pwndBottomView
->UseRightFile();
2054 m_pwndRightView
->UseLeftFile();
2057 void CMainFrame::OnUpdateEditUseleftfile(CCmdUI
*pCmdUI
)
2059 pCmdUI
->Enable(IsViewGood(m_pwndRightView
) && m_pwndRightView
->IsTarget());
2062 void CMainFrame::OnEditUseblockfromleftbeforeright()
2064 if (m_pwndRightView
)
2065 m_pwndRightView
->UseBothLeftFirst();
2068 void CMainFrame::OnUpdateEditUseblockfromleftbeforeright(CCmdUI
*pCmdUI
)
2070 OnUpdateEditUseleftblock(pCmdUI
);
2073 void CMainFrame::OnEditUseblockfromrightbeforeleft()
2075 if (m_pwndRightView
)
2076 m_pwndRightView
->UseBothRightFirst();
2079 void CMainFrame::OnUpdateEditUseblockfromrightbeforeleft(CCmdUI
*pCmdUI
)
2081 OnUpdateEditUseleftblock(pCmdUI
);
2084 void CMainFrame::OnFileReload()
2086 if (CheckForSave(CHFSR_RELOAD
)==IDCANCEL
)
2088 CDiffColors::GetInstance().LoadRegistry();
2092 void CMainFrame::ActivateFrame(int nCmdShow
)
2094 // nCmdShow is the normal show mode this frame should be in
2095 // translate default nCmdShow (-1)
2098 if (!IsWindowVisible())
2099 nCmdShow
= SW_SHOWNORMAL
;
2100 else if (IsIconic())
2101 nCmdShow
= SW_RESTORE
;
2104 // bring to top before showing
2105 BringToTop(nCmdShow
);
2109 // show the window as specified
2112 if ( !ReadWindowPlacement(&wp
) )
2114 ShowWindow(nCmdShow
);
2118 if ( nCmdShow
!= SW_SHOWNORMAL
)
2119 wp
.showCmd
= nCmdShow
;
2121 SetWindowPlacement(&wp
);
2124 // and finally, bring to top after showing
2125 BringToTop(nCmdShow
);
2129 BOOL
CMainFrame::ReadWindowPlacement(WINDOWPLACEMENT
* pwp
)
2131 CRegString placement
= CRegString(_T("Software\\TortoiseGitMerge\\WindowPos"));
2132 CString sPlacement
= placement
;
2133 if (sPlacement
.IsEmpty())
2135 int nRead
= _stscanf_s(sPlacement
, _T("%u,%u,%d,%d,%d,%d,%d,%d,%d,%d"),
2136 &pwp
->flags
, &pwp
->showCmd
,
2137 &pwp
->ptMinPosition
.x
, &pwp
->ptMinPosition
.y
,
2138 &pwp
->ptMaxPosition
.x
, &pwp
->ptMaxPosition
.y
,
2139 &pwp
->rcNormalPosition
.left
, &pwp
->rcNormalPosition
.top
,
2140 &pwp
->rcNormalPosition
.right
, &pwp
->rcNormalPosition
.bottom
);
2143 pwp
->length
= sizeof(WINDOWPLACEMENT
);
2148 void CMainFrame::WriteWindowPlacement(WINDOWPLACEMENT
* pwp
)
2150 CRegString placement
= CRegString(_T("Software\\TortoiseGitMerge\\WindowPos"));
2151 TCHAR szBuffer
[_countof("-32767")*8 + sizeof("65535")*2];
2153 _stprintf_s(szBuffer
, _T("%u,%u,%d,%d,%d,%d,%d,%d,%d,%d"),
2154 pwp
->flags
, pwp
->showCmd
,
2155 pwp
->ptMinPosition
.x
, pwp
->ptMinPosition
.y
,
2156 pwp
->ptMaxPosition
.x
, pwp
->ptMaxPosition
.y
,
2157 pwp
->rcNormalPosition
.left
, pwp
->rcNormalPosition
.top
,
2158 pwp
->rcNormalPosition
.right
, pwp
->rcNormalPosition
.bottom
);
2159 placement
= szBuffer
;
2162 void CMainFrame::OnUpdateMergeMarkasresolved(CCmdUI
*pCmdUI
)
2166 BOOL bEnable
= FALSE
;
2167 if ((!m_bReadOnly
)&&(m_Data
.m_mergedFile
.InUse()))
2169 if (IsViewGood(m_pwndBottomView
)&&(m_pwndBottomView
->m_pViewData
))
2174 pCmdUI
->Enable(bEnable
);
2177 void CMainFrame::OnMergeMarkasresolved()
2179 if(HasConflictsWontKeep())
2182 // now check if the file has already been saved and if not, save it.
2183 if (m_Data
.m_mergedFile
.InUse())
2185 if (IsViewGood(m_pwndBottomView
)&&(m_pwndBottomView
->m_pViewData
))
2188 m_bSaveRequired
= false;
2194 BOOL
CMainFrame::MarkAsResolved()
2198 if (!IsViewGood(m_pwndBottomView
))
2201 CString cmd
= _T("/command:resolve /path:\"");
2202 cmd
+= m_Data
.m_mergedFile
.GetFilename();
2203 cmd
+= _T("\" /closeonend:1 /noquestion /skipcheck /silent");
2207 s
.Format(L
" /resolvemsghwnd:%I64d /resolvemsgwparam:%I64d /resolvemsglparam:%I64d", (__int64
)resolveMsgWnd
, (__int64
)resolveMsgWParam
, (__int64
)resolveMsgLParam
);
2210 if(!CAppUtils::RunTortoiseGitProc(cmd
))
2212 m_bSaveRequired
= false;
2216 void CMainFrame::OnUpdateMergeNextconflict(CCmdUI
*pCmdUI
)
2219 if (HasNextConflict(m_pwndBottomView
))
2221 else if (HasNextConflict(m_pwndRightView
))
2223 else if (HasNextConflict(m_pwndLeftView
))
2225 pCmdUI
->Enable(bShow
);
2228 bool CMainFrame::HasNextConflict(CBaseView
* view
)
2232 if (!view
->IsTarget())
2234 return view
->HasNextConflict();
2237 void CMainFrame::OnUpdateMergePreviousconflict(CCmdUI
*pCmdUI
)
2240 if (HasPrevConflict(m_pwndBottomView
))
2242 else if (HasPrevConflict(m_pwndRightView
))
2244 else if (HasPrevConflict(m_pwndLeftView
))
2246 pCmdUI
->Enable(bShow
);
2249 bool CMainFrame::HasPrevConflict(CBaseView
* view
)
2253 if (!view
->IsTarget())
2255 return view
->HasPrevConflict();
2258 void CMainFrame::OnUpdateNavigateNextdifference(CCmdUI
*pCmdUI
)
2260 CBaseView
* baseView
= GetActiveBaseView();
2263 bShow
= baseView
->HasNextDiff();
2264 pCmdUI
->Enable(bShow
);
2267 void CMainFrame::OnUpdateNavigatePreviousdifference(CCmdUI
*pCmdUI
)
2269 CBaseView
* baseView
= GetActiveBaseView();
2272 bShow
= baseView
->HasPrevDiff();
2273 pCmdUI
->Enable(bShow
);
2276 void CMainFrame::OnUpdateNavigateNextinlinediff(CCmdUI
*pCmdUI
)
2279 if (HasNextInlineDiff(m_pwndBottomView
))
2281 else if (HasNextInlineDiff(m_pwndRightView
))
2283 else if (HasNextInlineDiff(m_pwndLeftView
))
2285 pCmdUI
->Enable(bShow
);
2288 bool CMainFrame::HasNextInlineDiff(CBaseView
* view
)
2292 if (!view
->IsTarget())
2294 return view
->HasNextInlineDiff();
2297 void CMainFrame::OnUpdateNavigatePrevinlinediff(CCmdUI
*pCmdUI
)
2300 if (HasPrevInlineDiff(m_pwndBottomView
))
2302 else if (HasPrevInlineDiff(m_pwndRightView
))
2304 else if (HasPrevInlineDiff(m_pwndLeftView
))
2306 pCmdUI
->Enable(bShow
);
2309 bool CMainFrame::HasPrevInlineDiff(CBaseView
* view
)
2313 if (!view
->IsTarget())
2315 return view
->HasPrevInlineDiff();
2318 void CMainFrame::OnMoving(UINT fwSide
, LPRECT pRect
)
2320 // if the pathfilelist dialog is attached to the mainframe,
2321 // move it along with the mainframe
2322 if (::IsWindow(m_dlgFilePatches
.m_hWnd
))
2325 m_dlgFilePatches
.GetWindowRect(&patchrect
);
2326 if (::IsWindow(m_hWnd
))
2329 GetWindowRect(&thisrect
);
2330 if (patchrect
.right
== thisrect
.left
)
2332 m_dlgFilePatches
.SetWindowPos(NULL
, patchrect
.left
- (thisrect
.left
- pRect
->left
), patchrect
.top
- (thisrect
.top
- pRect
->top
),
2333 0, 0, SWP_NOACTIVATE
| SWP_NOOWNERZORDER
| SWP_NOSIZE
| SWP_NOZORDER
);
2337 __super::OnMoving(fwSide
, pRect
);
2340 void CMainFrame::OnUpdateEditCopy(CCmdUI
*pCmdUI
)
2343 if ((m_pwndBottomView
)&&(m_pwndBottomView
->HasSelection()))
2345 else if ((m_pwndRightView
)&&(m_pwndRightView
->HasSelection()))
2347 else if ((m_pwndLeftView
)&&(m_pwndLeftView
->HasSelection()))
2349 pCmdUI
->Enable(bShow
);
2352 void CMainFrame::OnUpdateEditPaste(CCmdUI
*pCmdUI
)
2354 BOOL bWritable
= FALSE
;
2355 if ((m_pwndBottomView
)&&(m_pwndBottomView
->IsWritable()))
2357 else if ((m_pwndRightView
)&&(m_pwndRightView
->IsWritable()))
2359 else if ((m_pwndLeftView
)&&(m_pwndLeftView
->IsWritable()))
2361 pCmdUI
->Enable(bWritable
&& ::IsClipboardFormatAvailable(CF_TEXT
));
2364 void CMainFrame::OnViewSwitchleft()
2366 if (CheckForSave(CHFSR_SWITCH
)!=IDCANCEL
)
2368 CWorkingFile file
= m_Data
.m_baseFile
;
2369 m_Data
.m_baseFile
= m_Data
.m_yourFile
;
2370 m_Data
.m_yourFile
= file
;
2371 if (m_Data
.m_mergedFile
.GetFilename().CompareNoCase(m_Data
.m_yourFile
.GetFilename())==0)
2373 m_Data
.m_mergedFile
= m_Data
.m_baseFile
;
2375 else if (m_Data
.m_mergedFile
.GetFilename().CompareNoCase(m_Data
.m_baseFile
.GetFilename())==0)
2377 m_Data
.m_mergedFile
= m_Data
.m_yourFile
;
2383 void CMainFrame::OnUpdateViewSwitchleft(CCmdUI
*pCmdUI
)
2385 BOOL bEnable
= !IsViewGood(m_pwndBottomView
);
2386 pCmdUI
->Enable(bEnable
);
2389 void CMainFrame::OnUpdateViewShowfilelist(CCmdUI
*pCmdUI
)
2391 BOOL bEnable
= m_dlgFilePatches
.HasFiles();
2392 pCmdUI
->Enable(bEnable
);
2393 pCmdUI
->SetCheck(m_dlgFilePatches
.IsWindowVisible());
2396 void CMainFrame::OnViewShowfilelist()
2398 m_dlgFilePatches
.ShowWindow(m_dlgFilePatches
.IsWindowVisible() ? SW_HIDE
: SW_SHOW
);
2401 void CMainFrame::OnEditUndo()
2403 if (CUndo::GetInstance().CanUndo())
2405 CUndo::GetInstance().Undo(m_pwndLeftView
, m_pwndRightView
, m_pwndBottomView
);
2409 void CMainFrame::OnUpdateEditUndo(CCmdUI
*pCmdUI
)
2411 pCmdUI
->Enable(CUndo::GetInstance().CanUndo());
2414 void CMainFrame::OnEditEnable()
2416 CBaseView
* pView
= GetActiveBaseView();
2417 if (pView
&& pView
->IsReadonlyChangable())
2419 bool isReadOnly
= pView
->IsReadonly();
2420 pView
->SetReadonly(!isReadOnly
);
2424 void CMainFrame::OnUpdateEditEnable(CCmdUI
*pCmdUI
)
2426 CBaseView
* pView
= GetActiveBaseView();
2429 pCmdUI
->Enable(pView
->IsReadonlyChangable() || !pView
->IsReadonly());
2430 pCmdUI
->SetCheck(!pView
->IsReadonly());
2434 pCmdUI
->Enable(FALSE
);
2438 void CMainFrame::OnIndicatorLeftview()
2442 if (IsViewGood(m_pwndLeftView
))
2444 m_pwndLeftView
->AskUserForNewLineEndingsAndTextType(IDS_STATUSBAR_LEFTVIEW
);
2448 void CMainFrame::OnIndicatorRightview()
2452 if (IsViewGood(m_pwndRightView
))
2454 m_pwndRightView
->AskUserForNewLineEndingsAndTextType(IDS_STATUSBAR_RIGHTVIEW
);
2458 void CMainFrame::OnIndicatorBottomview()
2462 if (IsViewGood(m_pwndBottomView
))
2464 m_pwndBottomView
->AskUserForNewLineEndingsAndTextType(IDS_STATUSBAR_BOTTOMVIEW
);
2468 int CMainFrame::CheckForReload()
2470 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
2476 bool bSourceChanged
=
2477 m_Data
.m_baseFile
.HasSourceFileChanged()
2478 || m_Data
.m_yourFile
.HasSourceFileChanged()
2479 || m_Data
.m_theirFile
.HasSourceFileChanged()
2480 /*|| m_Data.m_mergedFile.HasSourceFileChanged()*/;
2481 if (!bSourceChanged
)
2488 if (m_bUseTaskDialog
)
2490 CString msg
= HasUnsavedEdits() ? CString(MAKEINTRESOURCE(IDS_WARNMODIFIEDOUTSIDELOOSECHANGES
)) : CString(MAKEINTRESOURCE(IDS_WARNMODIFIEDOUTSIDE
));
2491 CTaskDialog
taskdlg(msg
,
2492 CString(MAKEINTRESOURCE(IDS_WARNMODIFIEDOUTSIDE_TASK2
)),
2493 L
"TortoiseGitMerge",
2495 TDF_ENABLE_HYPERLINKS
|TDF_USE_COMMAND_LINKS
|TDF_ALLOW_DIALOG_CANCELLATION
|TDF_POSITION_RELATIVE_TO_WINDOW
);
2497 if (HasUnsavedEdits())
2498 sTask3
.LoadString(IDS_WARNMODIFIEDOUTSIDE_TASK3
);
2500 sTask3
.LoadString(IDS_WARNMODIFIEDOUTSIDE_TASK4
);
2501 taskdlg
.AddCommandControl(IDYES
, sTask3
);
2502 taskdlg
.AddCommandControl(IDNO
, CString(MAKEINTRESOURCE(IDS_WARNMODIFIEDOUTSIDE_TASK5
)));
2503 taskdlg
.SetCommonButtons(TDCBF_CANCEL_BUTTON
);
2504 taskdlg
.SetDefaultCommandControl(IDYES
);
2505 taskdlg
.SetMainIcon(TD_WARNING_ICON
);
2506 ret
= (UINT
)taskdlg
.DoModal(m_hWnd
);
2510 int idsMessage
= HasUnsavedEdits() ? IDS_WARNMODIFIEDOUTSIDELOOSECHANGES
: IDS_WARNMODIFIEDOUTSIDE
;
2511 ret
= CMessageBox::Show(m_hWnd
, idsMessage
, IDS_APPNAME
, MB_YESNO
| MB_ICONQUESTION
);
2516 CDiffColors::GetInstance().LoadRegistry();
2521 if (IsViewGood(m_pwndBottomView
)) // three pane view
2523 /*if (m_Data.m_sourceFile.HasSourceFileChanged())
2524 m_pwndBottomView->SetModified();
2525 if (m_Data.m_mergedFile.HasSourceFileChanged())
2526 m_pwndBottomView->SetModified();//*/
2527 if (m_Data
.m_yourFile
.HasSourceFileChanged())
2528 m_pwndRightView
->SetModified();
2529 if (m_Data
.m_theirFile
.HasSourceFileChanged())
2530 m_pwndLeftView
->SetModified();
2532 else if (IsViewGood(m_pwndRightView
)) // two pane view
2534 if (m_Data
.m_baseFile
.HasSourceFileChanged())
2535 m_pwndLeftView
->SetModified();
2536 if (m_Data
.m_yourFile
.HasSourceFileChanged())
2537 m_pwndRightView
->SetModified();
2541 if (m_Data
.m_yourFile
.HasSourceFileChanged())
2542 m_pwndLeftView
->SetModified();
2545 // no reload just store updated file time
2546 m_Data
.m_baseFile
.StoreFileAttributes();
2547 m_Data
.m_theirFile
.StoreFileAttributes();
2548 m_Data
.m_yourFile
.StoreFileAttributes();
2549 //m_Data.m_mergedFile.StoreFileAttributes();
2555 int CMainFrame::CheckForSave(ECheckForSaveReason eReason
)
2557 int idTitle
= IDS_WARNMODIFIEDLOOSECHANGES
;
2558 int idNoSave
= IDS_ASKFORSAVE_TASK7
;
2559 int idCancelAction
= IDS_ASKFORSAVE_CANCEL_OPEN
;
2563 //idTitle = IDS_WARNMODIFIEDLOOSECHANGES;
2564 idNoSave
= IDS_ASKFORSAVE_TASK4
;
2565 idCancelAction
= IDS_ASKFORSAVE_TASK5
;
2568 //idTitle = IDS_WARNMODIFIEDLOOSECHANGES;
2569 //idNoSave = IDS_ASKFORSAVE_TASK7;
2570 idCancelAction
= IDS_ASKFORSAVE_TASK8
;
2573 //idTitle = IDS_WARNMODIFIEDLOOSECHANGES;
2574 //idNoSave = IDS_ASKFORSAVE_TASK7;
2575 idCancelAction
= IDS_ASKFORSAVE_CANCEL_OPEN
;
2578 idTitle
= IDS_WARNMODIFIEDLOOSECHANGESOPTIONS
;
2579 //idNoSave = IDS_ASKFORSAVE_TASK7;
2580 idCancelAction
= IDS_ASKFORSAVE_CANCEL_OPTIONS
;
2583 //idTitle = IDS_WARNMODIFIEDLOOSECHANGES;
2584 idNoSave
= IDS_ASKFORSAVE_NOSAVE_OPEN
;
2585 idCancelAction
= IDS_ASKFORSAVE_CANCEL_OPEN
;
2589 CString
sTitle(MAKEINTRESOURCE(idTitle
));
2590 CString
sSubTitle(MAKEINTRESOURCE(IDS_ASKFORSAVE_TASK2
));
2591 CString
sNoSave(MAKEINTRESOURCE(idNoSave
));
2592 CString
sCancelAction(MAKEINTRESOURCE(idCancelAction
));
2593 CString
sAppName(MAKEINTRESOURCE(IDS_APPNAME
));
2595 // TODO simplify logic, reduce code duplication
2596 if (CBaseView::IsViewGood(m_pwndBottomView
))
2598 // three-way diff - by design only bottom can be changed
2599 // use 1.7 way to do that
2601 else if (CBaseView::IsViewGood(m_pwndRightView
))
2604 // 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
2605 if (HasUnsavedEdits(m_pwndLeftView
))
2609 if (m_bUseTaskDialog
)
2611 CTaskDialog
taskdlg(sTitle
,
2615 TDF_ENABLE_HYPERLINKS
|TDF_USE_COMMAND_LINKS
|TDF_ALLOW_DIALOG_CANCELLATION
|TDF_POSITION_RELATIVE_TO_WINDOW
);
2617 if (m_pwndLeftView
->m_pWorkingFile
->InUse() && !m_pwndLeftView
->m_pWorkingFile
->IsReadonly())
2618 sTaskTemp
.Format(IDS_ASKFORSAVE_SAVELEFT
, (LPCTSTR
)m_pwndLeftView
->m_pWorkingFile
->GetFilename());
2620 sTaskTemp
= CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_SAVELEFTAS
));
2621 taskdlg
.AddCommandControl(201, sTaskTemp
); // left
2622 taskdlg
.SetDefaultCommandControl(201);
2623 if (HasUnsavedEdits(m_pwndRightView
))
2625 if (m_pwndRightView
->m_pWorkingFile
->InUse() && !m_pwndRightView
->m_pWorkingFile
->IsReadonly())
2626 sTaskTemp
.Format(IDS_ASKFORSAVE_SAVERIGHT
, (LPCTSTR
)m_pwndRightView
->m_pWorkingFile
->GetFilename());
2628 sTaskTemp
= CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_SAVERIGHTAS
));
2629 taskdlg
.AddCommandControl(202, sTaskTemp
); // right
2630 taskdlg
.AddCommandControl(203, CString(MAKEINTRESOURCE(IDS_ASKFORSAVE_SAVEALL2
))); // both
2631 taskdlg
.SetDefaultCommandControl(203);
2633 taskdlg
.AddCommandControl(IDNO
, sNoSave
); // none
2634 taskdlg
.AddCommandControl(IDCANCEL
, sCancelAction
); // cancel
2635 taskdlg
.SetCommonButtons(TDCBF_CANCEL_BUTTON
);
2636 taskdlg
.SetMainIcon(TD_WARNING_ICON
);
2637 ret
= (UINT
)taskdlg
.DoModal(m_hWnd
);
2641 m_pwndLeftView
->SaveFile(SAVE_REMOVEDLINES
);
2644 m_pwndLeftView
->SaveFile(SAVE_REMOVEDLINES
);
2646 m_pwndRightView
->SaveFile();
2653 // show separate questions
2654 // first show question for left view
2655 ret
= MessageBox(sTitle
, 0, MB_YESNOCANCEL
| MB_ICONQUESTION
);
2656 if (ret
== IDCANCEL
)
2662 if (m_pwndLeftView
->SaveFile(SAVE_REMOVEDLINES
)<0)
2667 // right file is handled old way
2672 // only secondary (left) view
2674 // only right view - 1.7 implementation is used
2676 else if (CBaseView::IsViewGood(m_pwndLeftView
))
2678 // only one view - only one to save
2679 // 1.7 FileSave don't support this mode
2680 if (HasUnsavedEdits(m_pwndLeftView
))
2683 if (m_bUseTaskDialog
)
2685 CTaskDialog
taskdlg(sTitle
,
2689 TDF_ENABLE_HYPERLINKS
|TDF_USE_COMMAND_LINKS
|TDF_ALLOW_DIALOG_CANCELLATION
|TDF_POSITION_RELATIVE_TO_WINDOW
);
2691 if (m_Data
.m_mergedFile
.InUse())
2692 sTask3
.Format(IDS_ASKFORSAVE_TASK3
, (LPCTSTR
)m_Data
.m_mergedFile
.GetFilename());
2694 sTask3
.LoadString(IDS_ASKFORSAVE_TASK6
);
2695 taskdlg
.AddCommandControl(IDYES
, sTask3
);
2696 taskdlg
.AddCommandControl(IDNO
, sNoSave
);
2697 taskdlg
.AddCommandControl(IDCANCEL
, sCancelAction
);
2698 taskdlg
.SetCommonButtons(TDCBF_CANCEL_BUTTON
);
2699 taskdlg
.SetDefaultCommandControl(IDYES
);
2700 taskdlg
.SetMainIcon(TD_WARNING_ICON
);
2701 ret
= (UINT
)taskdlg
.DoModal(m_hWnd
);
2705 ret
= MessageBox(sTitle
, 0, MB_YESNOCANCEL
| MB_ICONQUESTION
);
2710 if (m_pwndLeftView
->SaveFile()<0)
2718 return IDNO
; // nothing to save
2721 // 1.7 implementation
2723 if (HasUnsavedEdits())
2725 if (m_bUseTaskDialog
)
2727 CTaskDialog
taskdlg(sTitle
,
2731 TDF_ENABLE_HYPERLINKS
|TDF_USE_COMMAND_LINKS
|TDF_ALLOW_DIALOG_CANCELLATION
|TDF_POSITION_RELATIVE_TO_WINDOW
);
2733 if (m_Data
.m_mergedFile
.InUse())
2734 sTask3
.Format(IDS_ASKFORSAVE_TASK3
, (LPCTSTR
)m_Data
.m_mergedFile
.GetFilename());
2736 sTask3
.LoadString(IDS_ASKFORSAVE_TASK6
);
2737 taskdlg
.AddCommandControl(IDYES
, sTask3
);
2738 taskdlg
.AddCommandControl(IDNO
, sNoSave
);
2739 taskdlg
.AddCommandControl(IDCANCEL
, sCancelAction
);
2740 taskdlg
.SetCommonButtons(TDCBF_CANCEL_BUTTON
);
2741 taskdlg
.SetDefaultCommandControl(IDYES
);
2742 taskdlg
.SetMainIcon(TD_WARNING_ICON
);
2743 ret
= (UINT
)taskdlg
.DoModal(m_hWnd
);
2747 ret
= MessageBox(sTitle
, 0, MB_YESNOCANCEL
| MB_ICONQUESTION
);
2759 bool CMainFrame::HasUnsavedEdits() const
2761 return HasUnsavedEdits(m_pwndBottomView
) || HasUnsavedEdits(m_pwndRightView
) || m_bSaveRequired
;
2764 bool CMainFrame::HasUnsavedEdits(const CBaseView
* view
)
2766 if (!CBaseView::IsViewGood(view
))
2768 return view
->IsModified();
2771 bool CMainFrame::IsViewGood(const CBaseView
* view
)
2773 return CBaseView::IsViewGood(view
);
2776 void CMainFrame::OnViewInlinediffword()
2778 m_bInlineWordDiff
= !m_bInlineWordDiff
;
2781 m_pwndLeftView
->SetInlineWordDiff(m_bInlineWordDiff
);
2782 m_pwndLeftView
->BuildAllScreen2ViewVector();
2783 m_pwndLeftView
->DocumentUpdated();
2785 if (m_pwndRightView
)
2787 m_pwndRightView
->SetInlineWordDiff(m_bInlineWordDiff
);
2788 m_pwndRightView
->BuildAllScreen2ViewVector();
2789 m_pwndRightView
->DocumentUpdated();
2791 if (m_pwndBottomView
)
2793 m_pwndBottomView
->SetInlineWordDiff(m_bInlineWordDiff
);
2794 m_pwndBottomView
->BuildAllScreen2ViewVector();
2795 m_pwndBottomView
->DocumentUpdated();
2797 m_wndLineDiffBar
.DocumentUpdated();
2800 void CMainFrame::OnUpdateViewInlinediffword(CCmdUI
*pCmdUI
)
2802 pCmdUI
->Enable(m_bInlineDiff
&& IsViewGood(m_pwndLeftView
) && IsViewGood(m_pwndRightView
));
2803 pCmdUI
->SetCheck(m_bInlineWordDiff
);
2806 void CMainFrame::OnViewInlinediff()
2808 m_bInlineDiff
= !m_bInlineDiff
;
2811 m_pwndLeftView
->SetInlineDiff(m_bInlineDiff
);
2812 m_pwndLeftView
->BuildAllScreen2ViewVector();
2813 m_pwndLeftView
->DocumentUpdated();
2815 if (m_pwndRightView
)
2817 m_pwndRightView
->SetInlineDiff(m_bInlineDiff
);
2818 m_pwndRightView
->BuildAllScreen2ViewVector();
2819 m_pwndRightView
->DocumentUpdated();
2821 if (m_pwndBottomView
)
2823 m_pwndBottomView
->SetInlineDiff(m_bInlineDiff
);
2824 m_pwndBottomView
->BuildAllScreen2ViewVector();
2825 m_pwndBottomView
->DocumentUpdated();
2827 m_wndLineDiffBar
.DocumentUpdated();
2830 void CMainFrame::OnUpdateViewInlinediff(CCmdUI
*pCmdUI
)
2832 pCmdUI
->Enable(IsViewGood(m_pwndLeftView
) && IsViewGood(m_pwndRightView
));
2833 pCmdUI
->SetCheck(m_bInlineDiff
);
2836 void CMainFrame::OnUpdateEditCreateunifieddifffile(CCmdUI
*pCmdUI
)
2838 // "create unified diff file" is only available if two files
2839 // are diffed, not three.
2840 bool bEnabled
= true;
2841 if (!IsViewGood(m_pwndLeftView
))
2843 else if (!IsViewGood(m_pwndRightView
))
2845 else if (IsViewGood(m_pwndBottomView
)) //no negation here
2847 pCmdUI
->Enable(bEnabled
);
2850 void CMainFrame::OnEditCreateunifieddifffile()
2852 CString origFile
, modifiedFile
;
2853 // the original file is the one on the left
2855 origFile
= m_pwndLeftView
->m_sFullFilePath
;
2856 if (m_pwndRightView
)
2857 modifiedFile
= m_pwndRightView
->m_sFullFilePath
;
2858 if (origFile
.IsEmpty() || modifiedFile
.IsEmpty())
2862 if(!TryGetFileName(outputFile
))
2865 CAppUtils::CreateUnifiedDiff(origFile
, modifiedFile
, outputFile
, true);
2868 void CMainFrame::OnUpdateEditTabspace(CCmdUI
*pCmdUI
)
2870 pCmdUI
->Enable(true);
2871 int nTabMode
= m_regTabMode
;
2872 pCmdUI
->SetCheck(nTabMode
& TABMODE_USESPACES
);
2875 void CMainFrame::OnEditTabspace()
2877 int nTabMode
= m_regTabMode
;
2878 nTabMode
^= TABMODE_USESPACES
;
2879 m_regTabMode
= nTabMode
;
2880 if (IsViewGood(m_pwndLeftView
))
2881 m_pwndLeftView
->m_nTabMode
= nTabMode
;
2882 if (IsViewGood(m_pwndRightView
))
2883 m_pwndRightView
->m_nTabMode
= nTabMode
;
2884 if (IsViewGood(m_pwndBottomView
))
2885 m_pwndBottomView
->m_nTabMode
= nTabMode
;
2888 void CMainFrame::OnUpdateEditSmartTab(CCmdUI
*pCmdUI
)
2890 pCmdUI
->Enable(true);
2891 int nTabMode
= m_regTabMode
;
2892 pCmdUI
->SetCheck(nTabMode
& TABMODE_SMARTINDENT
);
2895 void CMainFrame::OnEditSmartTab()
2897 int nTabMode
= m_regTabMode
;
2898 nTabMode
^= TABMODE_SMARTINDENT
;
2899 m_regTabMode
= nTabMode
;
2900 if (IsViewGood(m_pwndLeftView
))
2901 m_pwndLeftView
->m_nTabMode
= nTabMode
;
2902 if (IsViewGood(m_pwndRightView
))
2903 m_pwndRightView
->m_nTabMode
= nTabMode
;
2904 if (IsViewGood(m_pwndBottomView
))
2905 m_pwndBottomView
->m_nTabMode
= nTabMode
;
2908 void CMainFrame::OnUpdateViewLinediffbar(CCmdUI
*pCmdUI
)
2910 pCmdUI
->SetCheck(m_bLineDiff
);
2914 void CMainFrame::OnViewLinediffbar()
2916 m_bLineDiff
= !m_bLineDiff
;
2917 m_wndLineDiffBar
.ShowPane(m_bLineDiff
, false, true);
2918 m_wndLineDiffBar
.DocumentUpdated();
2919 m_wndLocatorBar
.ShowPane(m_bLocatorBar
, false, true);
2920 m_wndLocatorBar
.DocumentUpdated();
2923 void CMainFrame::OnUpdateViewLocatorbar(CCmdUI
*pCmdUI
)
2925 pCmdUI
->SetCheck(m_bLocatorBar
);
2929 void CMainFrame::OnViewLocatorbar()
2931 m_bLocatorBar
= !m_bLocatorBar
;
2932 m_wndLocatorBar
.ShowPane(m_bLocatorBar
, false, true);
2933 m_wndLocatorBar
.DocumentUpdated();
2934 m_wndLineDiffBar
.ShowPane(m_bLineDiff
, false, true);
2935 m_wndLineDiffBar
.DocumentUpdated();
2938 void CMainFrame::OnViewComparewhitespaces()
2940 if (CheckForSave(CHFSR_OPTIONS
)==IDCANCEL
)
2942 CRegDWORD regIgnoreWS
= CRegDWORD(_T("Software\\TortoiseGitMerge\\IgnoreWS"));
2947 void CMainFrame::OnUpdateViewComparewhitespaces(CCmdUI
*pCmdUI
)
2949 CRegDWORD regIgnoreWS
= CRegDWORD(_T("Software\\TortoiseGitMerge\\IgnoreWS"));
2950 DWORD dwIgnoreWS
= regIgnoreWS
;
2951 pCmdUI
->SetCheck(dwIgnoreWS
== 0);
2954 void CMainFrame::OnViewIgnorewhitespacechanges()
2956 if (CheckForSave(CHFSR_OPTIONS
)==IDCANCEL
)
2958 CRegDWORD regIgnoreWS
= CRegDWORD(_T("Software\\TortoiseGitMerge\\IgnoreWS"));
2963 void CMainFrame::OnUpdateViewIgnorewhitespacechanges(CCmdUI
*pCmdUI
)
2965 CRegDWORD regIgnoreWS
= CRegDWORD(_T("Software\\TortoiseGitMerge\\IgnoreWS"));
2966 DWORD dwIgnoreWS
= regIgnoreWS
;
2967 pCmdUI
->SetCheck(dwIgnoreWS
== 2);
2970 void CMainFrame::OnViewIgnoreallwhitespacechanges()
2972 if (CheckForSave(CHFSR_OPTIONS
)==IDCANCEL
)
2974 CRegDWORD regIgnoreWS
= CRegDWORD(_T("Software\\TortoiseGitMerge\\IgnoreWS"));
2979 void CMainFrame::OnUpdateViewIgnoreallwhitespacechanges(CCmdUI
*pCmdUI
)
2981 CRegDWORD regIgnoreWS
= CRegDWORD(_T("Software\\TortoiseGitMerge\\IgnoreWS"));
2982 DWORD dwIgnoreWS
= regIgnoreWS
;
2983 pCmdUI
->SetCheck(dwIgnoreWS
== 1);
2986 void CMainFrame::OnViewMovedBlocks()
2988 m_bViewMovedBlocks
= !(DWORD
)m_regViewModedBlocks
;
2989 m_regViewModedBlocks
= m_bViewMovedBlocks
;
2993 void CMainFrame::OnUpdateViewMovedBlocks(CCmdUI
*pCmdUI
)
2995 pCmdUI
->SetCheck(m_bViewMovedBlocks
);
2996 BOOL bEnable
= TRUE
;
2997 if (IsViewGood(m_pwndBottomView
))
3001 pCmdUI
->Enable(bEnable
);
3004 bool CMainFrame::HasConflictsWontKeep()
3006 const int nConflictLine
= CheckResolved();
3007 if (nConflictLine
< 0)
3011 sTemp
.Format(IDS_ERR_MAINFRAME_FILEHASCONFLICTS
, m_pwndBottomView
->m_pViewData
->GetLineNumber(nConflictLine
)+1);
3013 if (m_bUseTaskDialog
)
3015 CTaskDialog
taskdlg(sTemp
,
3016 CString(MAKEINTRESOURCE(IDS_ERR_MAINFRAME_FILEHASCONFLICTS_TASK2
)),
3017 L
"TortoiseGitMerge",
3019 TDF_ENABLE_HYPERLINKS
|TDF_USE_COMMAND_LINKS
|TDF_ALLOW_DIALOG_CANCELLATION
|TDF_POSITION_RELATIVE_TO_WINDOW
);
3020 taskdlg
.AddCommandControl(1, CString(MAKEINTRESOURCE(IDS_ERR_MAINFRAME_FILEHASCONFLICTS_TASK3
)));
3021 taskdlg
.AddCommandControl(2, CString(MAKEINTRESOURCE(IDS_ERR_MAINFRAME_FILEHASCONFLICTS_TASK4
)));
3022 taskdlg
.SetCommonButtons(TDCBF_CANCEL_BUTTON
);
3023 taskdlg
.SetDefaultCommandControl(2);
3024 taskdlg
.SetMainIcon(TD_ERROR_ICON
);
3025 bSave
= (taskdlg
.DoModal(m_hWnd
) == 1);
3029 bSave
= (MessageBox(sTemp
, 0, MB_ICONERROR
| MB_YESNO
)==IDYES
);
3035 if (m_pwndBottomView
)
3036 m_pwndBottomView
->GoToLine(nConflictLine
);
3040 bool CMainFrame::TryGetFileName(CString
& result
)
3042 return CCommonAppUtils::FileOpenSave(result
, NULL
, IDS_SAVEASTITLE
, IDS_COMMONFILEFILTER
, false, m_hWnd
);
3045 CBaseView
* CMainFrame::GetActiveBaseView() const
3047 CView
* activeView
= GetActiveView();
3048 CBaseView
* activeBase
= dynamic_cast<CBaseView
*>( activeView
);
3052 void CMainFrame::SetWindowTitle()
3054 // try to find a suitable window title
3055 CString sYour
= m_Data
.m_yourFile
.GetDescriptiveName();
3056 if (sYour
.Find(_T(" - "))>=0)
3057 sYour
= sYour
.Left(sYour
.Find(_T(" - ")));
3058 if (sYour
.Find(_T(" : "))>=0)
3059 sYour
= sYour
.Left(sYour
.Find(_T(" : ")));
3060 CString sTheir
= m_Data
.m_theirFile
.GetDescriptiveName();
3061 if (sTheir
.IsEmpty())
3062 sTheir
= m_Data
.m_baseFile
.GetDescriptiveName();
3063 if (sTheir
.Find(_T(" - "))>=0)
3064 sTheir
= sTheir
.Left(sTheir
.Find(_T(" - ")));
3065 if (sTheir
.Find(_T(" : "))>=0)
3066 sTheir
= sTheir
.Left(sTheir
.Find(_T(" : ")));
3068 if (!sYour
.IsEmpty() && !sTheir
.IsEmpty())
3070 if (sYour
.CompareNoCase(sTheir
)==0)
3071 SetWindowText(sYour
+ _T(" - TortoiseGitMerge"));
3072 else if ((sYour
.GetLength() < 10) &&
3073 (sTheir
.GetLength() < 10))
3074 SetWindowText(sYour
+ _T(" - ") + sTheir
+ _T(" - TortoiseGitMerge"));
3077 // we have two very long descriptive texts here, which
3078 // means we have to find a way to use them as a window
3079 // title in a shorter way.
3080 // for simplicity, we just use the one from "yourfile"
3081 SetWindowText(sYour
+ _T(" - TortoiseGitMerge"));
3084 else if (!sYour
.IsEmpty())
3085 SetWindowText(sYour
+ _T(" - TortoiseGitMerge"));
3086 else if (!sTheir
.IsEmpty())
3087 SetWindowText(sTheir
+ _T(" - TortoiseGitMerge"));
3089 SetWindowText(L
"TortoiseGitMerge");
3092 void CMainFrame::OnTimer(UINT_PTR nIDEvent
)
3096 case IDT_RELOADCHECKTIMER
:
3097 KillTimer(nIDEvent
);
3102 __super::OnTimer(nIDEvent
);
3105 void CMainFrame::LoadIgnoreCommentData()
3107 static bool bLoaded
= false;
3110 CString sPath
= CPathUtils::GetAppDataDirectory() + L
"ignorecomments.txt";
3111 if (!PathFileExists(sPath
))
3113 // ignore comments file does not exist (yet), so create a default one
3114 HRSRC hRes
= FindResource(NULL
, MAKEINTRESOURCE(IDR_IGNORECOMMENTSTXT
), L
"config");
3117 HGLOBAL hResourceLoaded
= LoadResource(NULL
, hRes
);
3118 if (hResourceLoaded
)
3120 char * lpResLock
= (char *) LockResource(hResourceLoaded
);
3121 DWORD dwSizeRes
= SizeofResource(NULL
, hRes
);
3124 HANDLE hFile
= CreateFile(sPath
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3125 if (hFile
!= INVALID_HANDLE_VALUE
)
3127 DWORD dwWritten
= 0;
3128 WriteFile(hFile
, lpResLock
, dwSizeRes
, &dwWritten
, NULL
);
3136 if (file
.Open(sPath
, CFile::modeRead
))
3139 while (file
.ReadString(sLine
))
3141 int eqpos
= sLine
.Find('=');
3144 CString sExts
= sLine
.Left(eqpos
);
3145 CString sComments
= sLine
.Mid(eqpos
+1);
3147 int pos
= sComments
.Find(',');
3148 CString sLineStart
= sComments
.Left(pos
);
3149 pos
= sComments
.Find(',', pos
);
3150 int pos2
= sComments
.Find(',', pos
+1);
3151 CString sBlockStart
= sComments
.Mid(pos
+1, pos2
-pos
-1);
3152 CString sBlockEnd
= sComments
.Mid(pos2
+1);
3154 auto commentTuple
= std::make_tuple(sLineStart
, sBlockStart
, sBlockEnd
);
3160 temp
= sExts
.Tokenize(_T(","),pos
);
3165 ASSERT(m_IgnoreCommentsMap
.find(temp
) == m_IgnoreCommentsMap
.end());
3166 m_IgnoreCommentsMap
[temp
] = commentTuple
;
3174 void CMainFrame::OnViewIgnorecomments()
3176 if (CheckForSave(CHFSR_OPTIONS
)==IDCANCEL
)
3178 m_regIgnoreComments
= !DWORD(m_regIgnoreComments
);
3182 void CMainFrame::OnUpdateViewIgnorecomments(CCmdUI
*pCmdUI
)
3184 // only enable if we have comments defined for this file extension
3185 CString sExt
= CPathUtils::GetFileExtFromPath(m_Data
.m_baseFile
.GetFilename()).MakeLower();
3186 sExt
.TrimLeft(L
".");
3187 auto sC
= m_IgnoreCommentsMap
.find(sExt
);
3188 if (sC
== m_IgnoreCommentsMap
.end())
3190 sExt
= CPathUtils::GetFileExtFromPath(m_Data
.m_yourFile
.GetFilename()).MakeLower();
3191 sExt
.TrimLeft(L
".");
3192 sC
= m_IgnoreCommentsMap
.find(sExt
);
3193 if (sC
== m_IgnoreCommentsMap
.end())
3195 sExt
= CPathUtils::GetFileExtFromPath(m_Data
.m_theirFile
.GetFilename()).MakeLower();
3196 sExt
.TrimLeft(L
".");
3197 sC
= m_IgnoreCommentsMap
.find(sExt
);
3200 pCmdUI
->Enable(sC
!= m_IgnoreCommentsMap
.end());
3202 pCmdUI
->SetCheck(DWORD(m_regIgnoreComments
) != 0);
3206 void CMainFrame::OnRegexfilter(UINT cmd
)
3208 if ((cmd
== ID_REGEXFILTER
)||(cmd
== (ID_REGEXFILTER
+1)))
3210 CRegexFiltersDlg
dlg(this);
3211 dlg
.SetIniFile(&m_regexIni
);
3212 if (dlg
.DoModal() == IDOK
)
3214 FILE * pFile
= NULL
;
3215 _tfopen_s(&pFile
, CPathUtils::GetAppDataDirectory() + L
"regexfilters.ini", _T("wb"));
3216 m_regexIni
.SaveFile(pFile
);
3219 BuildRegexSubitems();
3223 if (cmd
== (UINT
)m_regexIndex
)
3225 if (CheckForSave(CHFSR_OPTIONS
)==IDCANCEL
)
3227 m_Data
.SetRegexTokens(std::wregex(), L
"");
3233 CSimpleIni::TNamesDepend sections
;
3234 m_regexIni
.GetAllSections(sections
);
3235 int index
= ID_REGEXFILTER
+ 2;
3237 for (const auto& section
: sections
)
3239 if (cmd
== (UINT
)index
)
3241 if (CheckForSave(CHFSR_OPTIONS
)==IDCANCEL
)
3245 std::wregex
rx(m_regexIni
.GetValue(section
, L
"regex", L
""));
3246 m_Data
.SetRegexTokens(rx
, m_regexIni
.GetValue(section
, L
"replace", L
""));
3248 catch (std::exception
&ex
)
3250 MessageBox(_T("Regex is invalid!\r\n") + CString(ex
.what()));
3252 m_regexIndex
= index
;
3262 void CMainFrame::OnUpdateViewRegexFilter( CCmdUI
*pCmdUI
)
3265 pCmdUI
->SetCheck(pCmdUI
->m_nID
== (UINT
)m_regexIndex
);
3268 void CMainFrame::BuildRegexSubitems()
3270 CArray
<CMFCRibbonBaseElement
*, CMFCRibbonBaseElement
*> arButtons
;
3271 m_wndRibbonBar
.GetElementsByID(ID_REGEXFILTER
, arButtons
);
3272 if (arButtons
.GetCount() == 1)
3274 CMFCRibbonButton
* pButton
= (CMFCRibbonButton
*)arButtons
.GetAt(0);
3277 pButton
->RemoveAllSubItems();
3278 pButton
->AddSubItem(new CMFCRibbonButton(ID_REGEXFILTER
+1, CString(MAKEINTRESOURCE(IDS_CONFIGUREREGEXES
)), 47));
3280 CString sIniPath
= CPathUtils::GetAppDataDirectory() + L
"regexfilters.ini";
3281 if (!PathFileExists(sIniPath
))
3283 // ini file does not exist (yet), so create a default one
3284 HRSRC hRes
= FindResource(NULL
, MAKEINTRESOURCE(IDR_REGEXFILTERINI
), L
"config");
3287 HGLOBAL hResourceLoaded
= LoadResource(NULL
, hRes
);
3288 if (hResourceLoaded
)
3290 char * lpResLock
= (char *) LockResource(hResourceLoaded
);
3291 DWORD dwSizeRes
= SizeofResource(NULL
, hRes
);
3294 HANDLE hFile
= CreateFile(sIniPath
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3295 if (hFile
!= INVALID_HANDLE_VALUE
)
3297 DWORD dwWritten
= 0;
3298 WriteFile(hFile
, lpResLock
, dwSizeRes
, &dwWritten
, NULL
);
3306 m_regexIni
.LoadFile(sIniPath
);
3307 CSimpleIni::TNamesDepend sections
;
3308 m_regexIni
.GetAllSections(sections
);
3309 if (!sections
.empty())
3310 pButton
->AddSubItem(new CMFCRibbonSeparator(TRUE
));
3312 for (const auto& section
: sections
)
3314 pButton
->AddSubItem(new CMFCRibbonButton(ID_REGEXFILTER
+cmdIndex
, section
, 46));
3321 void CMainFrame::FillEncodingButton( CMFCRibbonButton
* pButton
, int start
)
3323 pButton
->SetDefaultCommand(FALSE
);
3324 pButton
->AddSubItem(new CMFCRibbonButton(start
+ CFileTextLines::UnicodeType::ASCII
, L
"ASCII" ));
3325 pButton
->AddSubItem(new CMFCRibbonButton(start
+ CFileTextLines::UnicodeType::BINARY
, L
"BINARY" ));
3326 pButton
->AddSubItem(new CMFCRibbonButton(start
+ CFileTextLines::UnicodeType::UTF16_LE
, L
"UTF-16LE" ));
3327 pButton
->AddSubItem(new CMFCRibbonButton(start
+ CFileTextLines::UnicodeType::UTF16_LEBOM
, L
"UTF-16LE BOM"));
3328 pButton
->AddSubItem(new CMFCRibbonButton(start
+ CFileTextLines::UnicodeType::UTF16_BE
, L
"UTF-16BE" ));
3329 pButton
->AddSubItem(new CMFCRibbonButton(start
+ CFileTextLines::UnicodeType::UTF16_BEBOM
, L
"UTF-16BE BOM"));
3330 pButton
->AddSubItem(new CMFCRibbonButton(start
+ CFileTextLines::UnicodeType::UTF32_LE
, L
"UTF-32LE" ));
3331 pButton
->AddSubItem(new CMFCRibbonButton(start
+ CFileTextLines::UnicodeType::UTF32_BE
, L
"UTF-32BE" ));
3332 pButton
->AddSubItem(new CMFCRibbonButton(start
+ CFileTextLines::UnicodeType::UTF8
, L
"UTF-8" ));
3333 pButton
->AddSubItem(new CMFCRibbonButton(start
+ CFileTextLines::UnicodeType::UTF8BOM
, L
"UTF-8 BOM" ));
3336 void CMainFrame::FillEOLButton( CMFCRibbonButton
* pButton
, int start
)
3338 pButton
->SetDefaultCommand(FALSE
);
3339 pButton
->AddSubItem(new CMFCRibbonButton(start
+ EOL::EOL_LF
, L
"LF" ));
3340 pButton
->AddSubItem(new CMFCRibbonButton(start
+ EOL::EOL_CRLF
, L
"CRLF"));
3341 pButton
->AddSubItem(new CMFCRibbonButton(start
+ EOL::EOL_LFCR
, L
"LRCR"));
3342 pButton
->AddSubItem(new CMFCRibbonButton(start
+ EOL::EOL_CR
, L
"CR" ));
3343 pButton
->AddSubItem(new CMFCRibbonButton(start
+ EOL::EOL_VT
, L
"VT" ));
3344 pButton
->AddSubItem(new CMFCRibbonButton(start
+ EOL::EOL_FF
, L
"FF" ));
3345 pButton
->AddSubItem(new CMFCRibbonButton(start
+ EOL::EOL_NEL
, L
"NEL" ));
3346 pButton
->AddSubItem(new CMFCRibbonButton(start
+ EOL::EOL_LS
, L
"LS" ));
3347 pButton
->AddSubItem(new CMFCRibbonButton(start
+ EOL::EOL_PS
, L
"PS" ));
3350 void CMainFrame::OnEncodingLeft( UINT cmd
)
3354 m_pwndLeftView
->SetTextType(CFileTextLines::UnicodeType(cmd
-ID_INDICATOR_LEFTENCODINGSTART
));
3355 m_pwndLeftView
->RefreshViews();
3359 void CMainFrame::OnEncodingRight( UINT cmd
)
3361 if (m_pwndRightView
)
3363 m_pwndRightView
->SetTextType(CFileTextLines::UnicodeType(cmd
-ID_INDICATOR_RIGHTENCODINGSTART
));
3364 m_pwndRightView
->RefreshViews();
3368 void CMainFrame::OnEncodingBottom( UINT cmd
)
3370 if (m_pwndBottomView
)
3372 m_pwndBottomView
->SetTextType(CFileTextLines::UnicodeType(cmd
-ID_INDICATOR_BOTTOMENCODINGSTART
));
3373 m_pwndBottomView
->RefreshViews();
3377 void CMainFrame::OnEOLLeft( UINT cmd
)
3381 m_pwndLeftView
->ReplaceLineEndings(EOL(cmd
-ID_INDICATOR_LEFTEOLSTART
));
3382 m_pwndLeftView
->RefreshViews();
3386 void CMainFrame::OnEOLRight( UINT cmd
)
3388 if (m_pwndRightView
)
3390 m_pwndRightView
->ReplaceLineEndings(EOL(cmd
-ID_INDICATOR_RIGHTEOLSTART
));
3391 m_pwndRightView
->RefreshViews();
3395 void CMainFrame::OnEOLBottom( UINT cmd
)
3397 if (m_pwndBottomView
)
3399 m_pwndBottomView
->ReplaceLineEndings(EOL(cmd
-ID_INDICATOR_BOTTOMEOLSTART
));
3400 m_pwndBottomView
->RefreshViews();
3404 void CMainFrame::OnUpdateEncodingLeft( CCmdUI
*pCmdUI
)
3408 pCmdUI
->SetCheck(CFileTextLines::UnicodeType(pCmdUI
->m_nID
- ID_INDICATOR_LEFTENCODINGSTART
) == m_pwndLeftView
->GetTextType());
3409 pCmdUI
->Enable(m_pwndLeftView
->IsWritable());
3412 pCmdUI
->Enable(FALSE
);
3415 void CMainFrame::OnUpdateEncodingRight( CCmdUI
*pCmdUI
)
3417 if (m_pwndRightView
)
3419 pCmdUI
->SetCheck(CFileTextLines::UnicodeType(pCmdUI
->m_nID
- ID_INDICATOR_RIGHTENCODINGSTART
) == m_pwndRightView
->GetTextType());
3420 pCmdUI
->Enable(m_pwndRightView
->IsWritable());
3423 pCmdUI
->Enable(FALSE
);
3426 void CMainFrame::OnUpdateEncodingBottom( CCmdUI
*pCmdUI
)
3428 if (m_pwndBottomView
)
3430 pCmdUI
->SetCheck(CFileTextLines::UnicodeType(pCmdUI
->m_nID
- ID_INDICATOR_BOTTOMENCODINGSTART
) == m_pwndBottomView
->GetTextType());
3431 pCmdUI
->Enable(m_pwndBottomView
->IsWritable());
3434 pCmdUI
->Enable(FALSE
);
3437 void CMainFrame::OnUpdateEOLLeft( CCmdUI
*pCmdUI
)
3441 pCmdUI
->SetCheck(EOL(pCmdUI
->m_nID
- ID_INDICATOR_LEFTEOLSTART
) == m_pwndLeftView
->GetLineEndings());
3442 pCmdUI
->Enable(m_pwndLeftView
->IsWritable());
3445 pCmdUI
->Enable(FALSE
);
3448 void CMainFrame::OnUpdateEOLRight( CCmdUI
*pCmdUI
)
3450 if (m_pwndRightView
)
3452 pCmdUI
->SetCheck(EOL(pCmdUI
->m_nID
- ID_INDICATOR_RIGHTEOLSTART
) == m_pwndRightView
->GetLineEndings());
3453 pCmdUI
->Enable(m_pwndRightView
->IsWritable());
3456 pCmdUI
->Enable(FALSE
);
3459 void CMainFrame::OnUpdateEOLBottom( CCmdUI
*pCmdUI
)
3461 if (m_pwndBottomView
)
3463 pCmdUI
->SetCheck(EOL(pCmdUI
->m_nID
- ID_INDICATOR_BOTTOMEOLSTART
) == m_pwndBottomView
->GetLineEndings());
3464 pCmdUI
->Enable(m_pwndBottomView
->IsWritable());
3467 pCmdUI
->Enable(FALSE
);