1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2014 - TortoiseGit
4 // Copyright (C) 2003-2008 - TortoiseSVN
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include "TortoiseProc.h"
22 #include "UnicodeUtils.h"
23 #include "MessageBox.h"
26 #include "SysImageList.h"
28 #include "StringUtils.h"
29 #include "PathUtils.h"
30 #include "BrowseFolder.h"
31 #include "FileDiffDlg.h"
33 #include "LoglistCommonResource.h"
34 #include "LoglistUtils.h"
35 #include "BrowseRefsDlg.h"
37 #include "RefLogDlg.h"
38 #include "GitStatusListCtrl.h"
39 #include "FormatMessageWrapper.h"
45 #define ID_CLIPBOARD_PATH 5
46 #define ID_CLIPBOARD_ALL 6
48 #define ID_GNUDIFFCOMPARE 8
51 #define ID_LOGSUBMODULE 11
53 BOOL
CFileDiffDlg::m_bAscending
= TRUE
;
54 int CFileDiffDlg::m_nSortedColumn
= -1;
56 UINT
CFileDiffDlg::WM_DISABLEBUTTONS
= RegisterWindowMessage(_T("TORTOISEGIT_FILEDIFF_DISABLEBUTTONS"));
57 UINT
CFileDiffDlg::WM_DIFFFINISHED
= RegisterWindowMessage(_T("TORTOISEGIT_FILEDIFF_DIFFFINISHED"));
59 IMPLEMENT_DYNAMIC(CFileDiffDlg
, CResizableStandAloneDialog
)
60 CFileDiffDlg::CFileDiffDlg(CWnd
* pParent
/*=NULL*/)
61 : CResizableStandAloneDialog(CFileDiffDlg::IDD
, pParent
)
66 , m_bThreadRunning(FALSE
)
67 , m_bIgnoreSpaceAtEol(false)
68 , m_bIgnoreSpaceChange(false)
69 , m_bIgnoreAllSpace(false)
70 , m_bIgnoreBlankLines(false)
76 CFileDiffDlg::~CFileDiffDlg()
80 void CFileDiffDlg::DoDataExchange(CDataExchange
* pDX
)
82 CResizableStandAloneDialog::DoDataExchange(pDX
);
83 DDX_Control(pDX
, IDC_FILELIST
, m_cFileList
);
84 DDX_Control(pDX
, IDC_SWITCHLEFTRIGHT
, m_SwitchButton
);
85 DDX_Control(pDX
, IDC_REV1BTN
, m_cRev1Btn
);
86 DDX_Control(pDX
, IDC_REV2BTN
, m_cRev2Btn
);
87 DDX_Control(pDX
, IDC_FILTER
, m_cFilter
);
88 DDX_Control(pDX
, IDC_REV1EDIT
, m_ctrRev1Edit
);
89 DDX_Control(pDX
, IDC_REV2EDIT
, m_ctrRev2Edit
);
93 BEGIN_MESSAGE_MAP(CFileDiffDlg
, CResizableStandAloneDialog
)
94 ON_NOTIFY(NM_DBLCLK
, IDC_FILELIST
, OnNMDblclkFilelist
)
95 ON_NOTIFY(LVN_GETINFOTIP
, IDC_FILELIST
, OnLvnGetInfoTipFilelist
)
96 ON_NOTIFY(NM_CUSTOMDRAW
, IDC_FILELIST
, OnNMCustomdrawFilelist
)
99 ON_EN_SETFOCUS(IDC_SECONDURL
, &CFileDiffDlg::OnEnSetfocusSecondurl
)
100 ON_EN_SETFOCUS(IDC_FIRSTURL
, &CFileDiffDlg::OnEnSetfocusFirsturl
)
101 ON_BN_CLICKED(IDC_SWITCHLEFTRIGHT
, &CFileDiffDlg::OnBnClickedSwitchleftright
)
102 ON_NOTIFY(HDN_ITEMCLICK
, 0, &CFileDiffDlg::OnHdnItemclickFilelist
)
103 ON_BN_CLICKED(IDC_REV1BTN
, &CFileDiffDlg::OnBnClickedRev1btn
)
104 ON_BN_CLICKED(IDC_REV2BTN
, &CFileDiffDlg::OnBnClickedRev2btn
)
105 ON_MESSAGE(WM_FILTEREDIT_CANCELCLICKED
, OnClickedCancelFilter
)
106 ON_EN_CHANGE(IDC_FILTER
, &CFileDiffDlg::OnEnChangeFilter
)
108 ON_MESSAGE(ENAC_UPDATE
, &CFileDiffDlg::OnEnUpdate
)
109 ON_MESSAGE(MSG_REF_LOADED
, OnRefLoad
)
110 ON_REGISTERED_MESSAGE(WM_DISABLEBUTTONS
, OnDisableButtons
)
111 ON_REGISTERED_MESSAGE(WM_DIFFFINISHED
, OnDiffFinished
)
112 ON_BN_CLICKED(IDC_DIFFOPTION
, OnBnClickedDiffoption
)
113 ON_BN_CLICKED(IDC_LOG
, &CFileDiffDlg::OnBnClickedLog
)
117 void CFileDiffDlg::SetDiff(const CTGitPath
* path
, const GitRev
&rev1
, const GitRev
&rev2
)
123 m_sFilter
= path
->GetGitPathString();
129 void CFileDiffDlg::SetDiff(const CTGitPath
* path
, const CString
&hash1
, const CString
&hash2
)
135 m_sFilter
= path
->GetGitPathString();
140 if(hash1
== GIT_REV_ZERO
)
142 m_rev1
.m_CommitHash
.Empty();
143 m_rev1
.GetSubject() = CString(MAKEINTRESOURCE(IDS_git_DEPTH_WORKING
));
149 m_rev1
.GetCommit(hash1
);
151 catch (const char *msg
)
153 MessageBox(_T("Could not get commit ") + hash1
+ _T("\nlibgit reports:\n") + CString(msg
), _T("TortoiseGit"), MB_ICONERROR
);
159 if(hash2
== GIT_REV_ZERO
)
161 m_rev2
.m_CommitHash
.Empty();
162 m_rev2
.GetSubject() = CString(MAKEINTRESOURCE(IDS_git_DEPTH_WORKING
));
168 m_rev2
.GetCommit(hash2
);
170 catch (const char *msg
)
172 MessageBox(_T("Could not get commit ") + hash2
+ _T("\nlibgit reports:\n") + CString(msg
), _T("TortoiseGit"), MB_ICONERROR
);
177 void CFileDiffDlg::SetDiff(const CTGitPath
* path
, const GitRev
&rev1
)
183 m_sFilter
= path
->GetGitPathString();
186 m_rev2
.m_CommitHash
.Empty();
187 m_rev2
.GetSubject() = CString(MAKEINTRESOURCE(IDS_PROC_PREVIOUSVERSION
));
189 //this->GetDlgItem()->EnableWindow(FALSE);
192 BOOL
CFileDiffDlg::OnInitDialog()
194 CResizableStandAloneDialog::OnInitDialog();
197 CString sWindowTitle
;
198 GetWindowText(sWindowTitle
);
199 CString pathText
= g_Git
.m_CurrentDir
;
200 if (!m_path1
.IsEmpty())
201 pathText
= g_Git
.CombinePath(m_path1
);
202 CAppUtils::SetWindowTitle(m_hWnd
, pathText
, sWindowTitle
);
204 this->m_ctrRev1Edit
.Init();
205 this->m_ctrRev2Edit
.Init();
207 m_tooltips
.Create(this);
208 m_tooltips
.AddTool(IDC_SWITCHLEFTRIGHT
, IDS_FILEDIFF_SWITCHLEFTRIGHT_TT
);
210 m_cFileList
.SetRedraw(false);
211 m_cFileList
.DeleteAllItems();
212 DWORD exStyle
= LVS_EX_FULLROWSELECT
| LVS_EX_DOUBLEBUFFER
| LVS_EX_INFOTIP
;
213 m_cFileList
.SetExtendedStyle(exStyle
);
215 m_nIconFolder
= SYS_IMAGE_LIST().GetDirIconIndex();
216 m_cFileList
.SetImageList(&SYS_IMAGE_LIST(), LVSIL_SMALL
);
218 m_SwitchButton
.SetImage((HICON
)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_SWITCHLEFTRIGHT
), IMAGE_ICON
, 16, 16, LR_DEFAULTCOLOR
));
219 m_SwitchButton
.Invalidate();
221 m_cFilter
.SetCancelBitmaps(IDI_CANCELNORMAL
, IDI_CANCELPRESSED
);
222 m_cFilter
.SetInfoIcon(IDI_FILTEREDIT
);
223 temp
.LoadString(IDS_FILEDIFF_FILTERCUE
);
225 m_cFilter
.SetCueBanner(temp
);
226 if (!m_sFilter
.IsEmpty())
227 m_cFilter
.SetWindowText(m_sFilter
);
229 int c
= ((CHeaderCtrl
*)(m_cFileList
.GetDlgItem(0)))->GetItemCount()-1;
231 m_cFileList
.DeleteColumn(c
--);
233 temp
.LoadString(IDS_FILEDIFF_FILE
);
234 m_cFileList
.InsertColumn(0, temp
);
235 temp
.LoadString(IDS_FILEDIFF_EXT
);
236 m_cFileList
.InsertColumn(1, temp
);
237 temp
.LoadString(IDS_FILEDIFF_ACTION
);
238 m_cFileList
.InsertColumn(2, temp
);
240 temp
.LoadString(IDS_FILEDIFF_STATADD
);
241 m_cFileList
.InsertColumn(3, temp
);
242 temp
.LoadString(IDS_FILEDIFF_STATDEL
);
243 m_cFileList
.InsertColumn(4, temp
);
246 int maxcol
= ((CHeaderCtrl
*)(m_cFileList
.GetDlgItem(0)))->GetItemCount()-1;
248 for (col
= mincol
; col
<= maxcol
; col
++)
250 m_cFileList
.SetColumnWidth(col
,LVSCW_AUTOSIZE_USEHEADER
);
253 m_cFileList
.SetRedraw(true);
255 AddAnchor(IDC_DIFFSTATIC1
, TOP_LEFT
, TOP_RIGHT
);
256 AddAnchor(IDC_SWITCHLEFTRIGHT
, TOP_RIGHT
);
257 AddAnchor(IDC_FIRSTURL
, TOP_LEFT
, TOP_RIGHT
);
258 AddAnchor(IDC_REV1BTN
, TOP_RIGHT
);
259 //AddAnchor(IDC_DIFFSTATIC2, TOP_LEFT, TOP_RIGHT);
260 AddAnchor(IDC_SECONDURL
, TOP_LEFT
, TOP_RIGHT
);
261 AddAnchor(IDC_REV2BTN
, TOP_RIGHT
);
262 AddAnchor(IDC_FILTER
, TOP_LEFT
, TOP_RIGHT
);
263 AddAnchor(IDC_FILELIST
, TOP_LEFT
, BOTTOM_RIGHT
);
264 AddAnchor(IDC_REV1GROUP
,TOP_LEFT
,TOP_RIGHT
);
265 AddAnchor(IDC_REV2GROUP
,TOP_LEFT
,TOP_RIGHT
);
266 AddAnchor(IDC_REV1EDIT
,TOP_LEFT
);
267 AddAnchor(IDC_REV2EDIT
,TOP_LEFT
);
268 AddAnchor(IDC_DIFFOPTION
, TOP_RIGHT
);
269 AddAnchor(IDC_LOG
, TOP_RIGHT
);
271 EnableSaveRestore(_T("FileDiffDlg"));
273 m_bIsBare
= GitAdminDir().IsBareRepo(g_Git
.m_CurrentDir
);
275 if(this->m_strRev1
.IsEmpty())
276 this->m_ctrRev1Edit
.SetWindowText(this->m_rev1
.m_CommitHash
.ToString());
279 bool rev1fail
= false;
282 rev1fail
= !!m_rev1
.GetCommit(m_strRev1
);
284 catch (const char *msg
)
287 MessageBox(_T("Could not get commit ") + m_strRev1
+ _T("\nlibgit reports:\n") + CString(msg
), _T("TortoiseGit"), MB_ICONERROR
);
292 msg
.Format(IDS_PROC_REFINVALID
, m_strRev1
);
293 this->m_FileListText
+= msg
;
296 this->m_ctrRev1Edit
.SetWindowText(m_strRev1
);
299 if(this->m_strRev2
.IsEmpty())
300 this->m_ctrRev2Edit
.SetWindowText(this->m_rev2
.m_CommitHash
.ToString());
303 bool rev2fail
= false;
306 rev2fail
= !!m_rev2
.GetCommit(m_strRev2
);
308 catch (const char *msg
)
311 MessageBox(_T("Could not get commit ") + m_strRev2
+ _T("\nlibgit reports:\n") + CString(msg
), _T("TortoiseGit"), MB_ICONERROR
);
316 msg
.Format(IDS_PROC_REFINVALID
, m_strRev2
);
317 this->m_FileListText
+= msg
;
320 this->m_ctrRev2Edit
.SetWindowText(m_strRev2
);
325 InterlockedExchange(&m_bThreadRunning
, TRUE
);
326 if (AfxBeginThread(DiffThreadEntry
, this)==NULL
)
328 InterlockedExchange(&m_bThreadRunning
, FALSE
);
329 CMessageBox::Show(NULL
, IDS_ERR_THREADSTARTFAILED
, IDS_APPNAME
, MB_OK
| MB_ICONERROR
);
332 InterlockedExchange(&m_bLoadingRef
, TRUE
);
333 if (AfxBeginThread(LoadRefThreadEntry
, this)==NULL
)
335 InterlockedExchange(&m_bLoadingRef
, FALSE
);
336 CMessageBox::Show(NULL
, IDS_ERR_THREADSTARTFAILED
, IDS_APPNAME
, MB_OK
| MB_ICONERROR
);
339 this->m_cRev1Btn
.AddEntry(CString(MAKEINTRESOURCE(IDS_REFBROWSE
)));
340 this->m_cRev1Btn
.AddEntry(CString(MAKEINTRESOURCE(IDS_LOG
)));
341 this->m_cRev1Btn
.AddEntry(CString(MAKEINTRESOURCE(IDS_REFLOG
)));
343 this->m_cRev2Btn
.AddEntry(CString(MAKEINTRESOURCE(IDS_REFBROWSE
)));
344 this->m_cRev2Btn
.AddEntry(CString(MAKEINTRESOURCE(IDS_LOG
)));
345 this->m_cRev2Btn
.AddEntry(CString(MAKEINTRESOURCE(IDS_REFLOG
)));
347 // Start with focus on file list
348 GetDlgItem(IDC_FILELIST
)->SetFocus();
350 if(m_rev2
.m_CommitHash
.IsEmpty())
351 m_SwitchButton
.EnableWindow(FALSE
);
353 KillTimer(IDT_INPUT
);
357 UINT
CFileDiffDlg::DiffThreadEntry(LPVOID pVoid
)
359 return ((CFileDiffDlg
*)pVoid
)->DiffThread();
362 UINT
CFileDiffDlg::DiffThread()
364 SendMessage(WM_DISABLEBUTTONS
);
366 if( m_rev1
.m_CommitHash
.IsEmpty() || m_rev2
.m_CommitHash
.IsEmpty())
367 g_Git
.RefreshGitIndex();
369 g_Git
.GetCommitDiffList(m_rev1
.m_CommitHash
.ToString(), m_rev2
.m_CommitHash
.ToString(), m_arFileList
, m_bIgnoreSpaceAtEol
, m_bIgnoreSpaceChange
, m_bIgnoreAllSpace
, m_bIgnoreBlankLines
);
372 SendMessage(WM_DIFFFINISHED
);
374 InterlockedExchange(&m_bThreadRunning
, FALSE
);
378 LRESULT
CFileDiffDlg::OnDisableButtons(WPARAM
, LPARAM
)
381 m_cFileList
.ShowText(CString(MAKEINTRESOURCE(IDS_FILEDIFF_WAIT
)));
382 m_cFileList
.DeleteAllItems();
383 m_arFileList
.Clear();
384 EnableInputControl(false);
388 LRESULT
CFileDiffDlg::OnDiffFinished(WPARAM
, LPARAM
)
391 m_cFilter
.GetWindowText(sFilterText
);
392 m_cFileList
.SetRedraw(false);
394 if (!m_arFileList
.IsEmpty())
396 // Highlight first entry in file list
397 m_cFileList
.SetSelectionMark(0);
398 m_cFileList
.SetItemState(0, LVIS_SELECTED
, LVIS_SELECTED
);
402 int maxcol
= ((CHeaderCtrl
*)(m_cFileList
.GetDlgItem(0)))->GetItemCount()-1;
404 for (col
= mincol
; col
<= maxcol
; ++col
)
406 m_cFileList
.SetColumnWidth(col
, LVSCW_AUTOSIZE_USEHEADER
);
409 m_cFileList
.ClearText();
410 if (m_arFileList
.IsEmpty())
411 m_cFileList
.ShowText(CString(MAKEINTRESOURCE(IDS_COMPAREREV_NODIFF
)));
412 m_cFileList
.SetRedraw(true);
414 InvalidateRect(NULL
);
416 EnableInputControl(true);
420 int CFileDiffDlg::AddEntry(const CTGitPath
* fd
)
425 int index
= m_cFileList
.GetItemCount();
428 if (fd
->IsDirectory())
429 icon_idx
= m_nIconFolder
;
431 icon_idx
= SYS_IMAGE_LIST().GetPathIconIndex(fd
->GetGitPathString());
433 ret
= m_cFileList
.InsertItem(index
, fd
->GetGitPathString(), icon_idx
);
434 m_cFileList
.SetItemText(index
, 1, ((CTGitPath
*)fd
)->GetFileExtension());
435 m_cFileList
.SetItemText(index
, 2, ((CTGitPath
*)fd
)->GetActionName());
436 m_cFileList
.SetItemText(index
, 3, ((CTGitPath
*)fd
)->m_StatAdd
);
437 m_cFileList
.SetItemText(index
, 4, ((CTGitPath
*)fd
)->m_StatDel
);
442 void CFileDiffDlg::EnableInputControl(bool b
)
444 this->m_ctrRev1Edit
.EnableWindow(b
);
445 this->m_ctrRev2Edit
.EnableWindow(b
);
446 this->m_cRev1Btn
.EnableWindow(b
);
447 this->m_cRev2Btn
.EnableWindow(b
);
448 m_cFilter
.EnableWindow(b
);
449 m_SwitchButton
.EnableWindow(b
);
450 GetDlgItem(IDC_LOG
)->EnableWindow(b
&& !(m_rev1
.m_CommitHash
.IsEmpty() || m_rev2
.m_CommitHash
.IsEmpty()));
453 void CFileDiffDlg::DoDiff(int selIndex
, bool blame
)
456 CTGitPath
* fd2
= m_arFilteredList
[selIndex
];
457 CTGitPath
* fd1
= fd2
;
458 if (m_rev1
.m_CommitHash
.IsEmpty() && g_Git
.IsInitRepos())
460 CGitDiff::DiffNull(fd2
, GIT_REV_ZERO
);
463 if (fd2
->m_Action
& CTGitPath::LOGACTIONS_ADDED
)
465 CGitDiff::DiffNull(fd2
, m_rev1
.m_CommitHash
.ToString(), true);
468 if (fd2
->m_Action
& CTGitPath::LOGACTIONS_DELETED
)
470 CGitDiff::DiffNull(fd2
, m_rev2
.m_CommitHash
.ToString(), false);
473 if (fd2
->m_Action
& CTGitPath::LOGACTIONS_REPLACED
)
474 fd1
= new CTGitPath(fd2
->GetGitOldPathString());
475 diff
.Diff(fd2
, fd1
, this->m_rev1
.m_CommitHash
.ToString(), this->m_rev2
.m_CommitHash
.ToString(), blame
, FALSE
);
481 void CFileDiffDlg::OnNMDblclkFilelist(NMHDR
*pNMHDR
, LRESULT
*pResult
)
484 LPNMLISTVIEW pNMLV
= reinterpret_cast<LPNMLISTVIEW
>(pNMHDR
);
485 int selIndex
= pNMLV
->iItem
;
488 if (selIndex
>= (int)m_arFilteredList
.size())
491 DoDiff(selIndex
, m_bBlame
);
494 void CFileDiffDlg::OnLvnGetInfoTipFilelist(NMHDR
*pNMHDR
, LRESULT
*pResult
)
497 LPNMLVGETINFOTIP pGetInfoTip
= reinterpret_cast<LPNMLVGETINFOTIP
>(pNMHDR
);
498 if (pGetInfoTip
->iItem
>= (int)m_arFilteredList
.size())
501 CString path
= m_path1
.GetGitPathString() + _T("/") + m_arFilteredList
[pGetInfoTip
->iItem
]->GetGitPathString();
502 if (pGetInfoTip
->cchTextMax
> path
.GetLength())
503 _tcsncpy_s(pGetInfoTip
->pszText
, pGetInfoTip
->cchTextMax
, path
, pGetInfoTip
->cchTextMax
);
508 void CFileDiffDlg::OnNMCustomdrawFilelist(NMHDR
*pNMHDR
, LRESULT
*pResult
)
510 NMLVCUSTOMDRAW
* pLVCD
= reinterpret_cast<NMLVCUSTOMDRAW
*>( pNMHDR
);
511 // Take the default processing unless we set this to something else below.
512 *pResult
= CDRF_DODEFAULT
;
514 // First thing - check the draw stage. If it's the control's prepaint
515 // stage, then tell Windows we want messages for every item.
517 if ( CDDS_PREPAINT
== pLVCD
->nmcd
.dwDrawStage
)
519 *pResult
= CDRF_NOTIFYITEMDRAW
;
521 else if ( CDDS_ITEMPREPAINT
== pLVCD
->nmcd
.dwDrawStage
)
523 // This is the prepaint stage for an item. Here's where we set the
524 // item's text color. Our return value will tell Windows to draw the
525 // item itself, but it will use the new color we set here.
527 // Tell Windows to paint the control itself.
528 *pResult
= CDRF_DODEFAULT
;
530 COLORREF crText
= GetSysColor(COLOR_WINDOWTEXT
);
532 if (m_arFilteredList
.size() > pLVCD
->nmcd
.dwItemSpec
)
534 CTGitPath
* fd
= m_arFilteredList
[pLVCD
->nmcd
.dwItemSpec
];
535 switch (fd
->m_Action
)
537 case CTGitPath::LOGACTIONS_ADDED
:
538 crText
= m_colors
.GetColor(CColors::Added
);
540 case CTGitPath::LOGACTIONS_DELETED
:
541 crText
= m_colors
.GetColor(CColors::Deleted
);
543 case CTGitPath::LOGACTIONS_MODIFIED
:
544 crText
= m_colors
.GetColor(CColors::Modified
);
547 crText
= m_colors
.GetColor(CColors::PropertyChanged
);
551 // Store the color back in the NMLVCUSTOMDRAW struct.
552 pLVCD
->clrText
= crText
;
556 UINT
CFileDiffDlg::LoadRefThread()
558 g_Git
.GetBranchList(m_Reflist
,NULL
,CGit::BRANCH_ALL_F
);
559 g_Git
.GetTagList(m_Reflist
);
561 this->PostMessage(MSG_REF_LOADED
);
562 InterlockedExchange(&m_bLoadingRef
, FALSE
);
566 void CFileDiffDlg::OnContextMenu(CWnd
* pWnd
, CPoint point
)
568 if ((pWnd
==0)||(pWnd
!= &m_cFileList
))
570 if (m_cFileList
.GetSelectedCount() == 0)
572 // if the context menu is invoked through the keyboard, we have to use
573 // a calculated position on where to anchor the menu on
574 if ((point
.x
== -1) && (point
.y
== -1))
577 m_cFileList
.GetItemRect(m_cFileList
.GetSelectionMark(), &rect
, LVIR_LABEL
);
578 m_cFileList
.ClientToScreen(&rect
);
579 point
= rect
.CenterPoint();
582 if (popup
.CreatePopupMenu())
585 POSITION firstPos
= m_cFileList
.GetFirstSelectedItemPosition();
587 firstEntry
= m_cFileList
.GetNextSelectedItem(firstPos
);
590 popup
.AppendMenuIcon(ID_COMPARE
, IDS_LOG_POPUP_COMPARETWO
, IDI_DIFF
);
591 popup
.AppendMenuIcon(ID_GNUDIFFCOMPARE
, IDS_LOG_POPUP_GNUDIFF
, IDI_DIFF
);
592 popup
.AppendMenu(MF_SEPARATOR
, NULL
);
595 menuText
.Format(IDS_FILEDIFF_POPREVERTTOREV
, m_rev1
.m_CommitHash
.ToString().Left(g_Git
.GetShortHASHLength()));
596 popup
.AppendMenuIcon(ID_REVERT1
, menuText
, IDI_REVERT
);
597 menuText
.Format(IDS_FILEDIFF_POPREVERTTOREV
, m_rev2
.m_CommitHash
.ToString().Left(g_Git
.GetShortHASHLength()));
598 popup
.AppendMenuIcon(ID_REVERT2
, menuText
, IDI_REVERT
);
599 popup
.AppendMenu(MF_SEPARATOR
, NULL
);
601 popup
.AppendMenuIcon(ID_LOG
, IDS_FILEDIFF_LOG
, IDI_LOG
);
602 if (firstEntry
>= 0 && !m_arFilteredList
[firstEntry
]->IsDirectory())
606 popup
.AppendMenuIcon(ID_BLAME
, IDS_FILEDIFF_POPBLAME
, IDI_BLAME
);
607 popup
.AppendMenu(MF_SEPARATOR
, NULL
);
609 popup
.AppendMenuIcon(ID_EXPORT
, IDS_FILEDIFF_POPEXPORT
, IDI_EXPORT
);
611 else if (firstEntry
>= 0)
612 popup
.AppendMenuIcon(ID_LOGSUBMODULE
, IDS_MENULOGSUBMODULE
, IDI_LOG
);
613 popup
.AppendMenu(MF_SEPARATOR
, NULL
);
614 popup
.AppendMenuIcon(ID_SAVEAS
, IDS_FILEDIFF_POPSAVELIST
, IDI_SAVEAS
);
615 popup
.AppendMenuIcon(ID_CLIPBOARD_PATH
, IDS_STATUSLIST_CONTEXT_COPY
, IDI_COPYCLIP
);
616 popup
.AppendMenuIcon(ID_CLIPBOARD_ALL
, IDS_STATUSLIST_CONTEXT_COPYEXT
, IDI_COPYCLIP
);
618 int cmd
= popup
.TrackPopupMenu(TPM_RETURNCMD
| TPM_LEFTALIGN
| TPM_NONOTIFY
, point
.x
, point
.y
, this, 0);
619 m_bCancelled
= false;
624 POSITION pos
= m_cFileList
.GetFirstSelectedItemPosition();
627 int index
= m_cFileList
.GetNextSelectedItem(pos
);
628 DoDiff(index
, false);
632 case ID_GNUDIFFCOMPARE
:
634 POSITION pos
= m_cFileList
.GetFirstSelectedItemPosition();
637 CTGitPath
*fd2
= m_arFilteredList
[m_cFileList
.GetNextSelectedItem(pos
)];
638 CTGitPath
*fd1
= fd2
;
639 if (fd2
->m_Action
& CTGitPath::LOGACTIONS_REPLACED
)
640 fd1
= new CTGitPath(fd2
->GetGitOldPathString());
641 CAppUtils::StartShowUnifiedDiff(m_hWnd
, *fd2
, m_rev2
.m_CommitHash
.ToString(), *fd1
, m_rev1
.m_CommitHash
.ToString());
648 RevertSelectedItemToVersion(m_rev1
.m_CommitHash
.ToString());
651 RevertSelectedItemToVersion(m_rev2
.m_CommitHash
.ToString());
655 POSITION pos
= m_cFileList
.GetFirstSelectedItemPosition();
658 int index
= m_cFileList
.GetNextSelectedItem(pos
);
659 CAppUtils::LaunchTortoiseBlame(m_arFilteredList
[index
]->GetWinPathString(), m_rev1
.m_CommitHash
.ToString());
664 case ID_LOGSUBMODULE
:
666 POSITION pos
= m_cFileList
.GetFirstSelectedItemPosition();
669 int index
= m_cFileList
.GetNextSelectedItem(pos
);
670 CString cmd
= _T("/command:log");
671 if (cmd
== ID_LOGSUBMODULE
)
672 cmd
+= _T(" /submodule");
673 cmd
+= _T(" /path:\"")+m_arFilteredList
[index
]->GetWinPathString()+_T("\" ");
674 cmd
+= _T(" /endrev:")+m_rev1
.m_CommitHash
.ToString();
675 CAppUtils::RunTortoiseGitProc(cmd
);
681 if (m_cFileList
.GetSelectedCount() > 0)
686 if (!CAppUtils::FileOpenSave(pathSave
, NULL
, IDS_REPOBROWSE_SAVEAS
, IDS_TEXTFILEFILTER
, false, m_hWnd
, _T(".txt")))
690 savePath
= CTGitPath(pathSave
);
692 // now open the selected file for writing
695 CStdioFile
file(savePath
.GetWinPathString(), CFile::typeBinary
| CFile::modeReadWrite
| CFile::modeCreate
);
696 if (m_path1
.IsEmpty() && m_path2
.IsEmpty())
697 temp
.Format(IDS_FILEDIFF_CHANGEDLISTINTROROOT
, m_rev1
.m_CommitHash
.ToString(), m_rev2
.m_CommitHash
.ToString());
699 temp
.Format(IDS_FILEDIFF_CHANGEDLISTINTRO
, m_path1
.GetGitPathString(), m_rev1
.m_CommitHash
.ToString(), m_path2
.GetGitPathString(), m_rev2
.m_CommitHash
.ToString());
700 file
.WriteString(temp
+ _T("\r\n"));
701 POSITION pos
= m_cFileList
.GetFirstSelectedItemPosition();
704 int index
= m_cFileList
.GetNextSelectedItem(pos
);
705 CTGitPath
* fd
= m_arFilteredList
[index
];
706 file
.WriteString(fd
->GetGitPathString());
707 file
.WriteString(_T("\r\n"));
711 catch (CFileException
* pE
)
718 case ID_CLIPBOARD_PATH
:
720 CopySelectionToClipboard();
724 case ID_CLIPBOARD_ALL
:
726 CopySelectionToClipboard(TRUE
);
731 // export all changed files to a folder
732 CBrowseFolder browseFolder
;
733 browseFolder
.m_style
= BIF_EDITBOX
| BIF_NEWDIALOGSTYLE
| BIF_RETURNFSANCESTORS
| BIF_RETURNONLYFSDIRS
;
734 if (browseFolder
.Show(GetSafeHwnd(), m_strExportDir
) == CBrowseFolder::OK
)
736 POSITION pos
= m_cFileList
.GetFirstSelectedItemPosition();
739 int index
= m_cFileList
.GetNextSelectedItem(pos
);
740 CTGitPath
* fd
= m_arFilteredList
[index
];
741 // we cannot export directories or folders
742 if (fd
->m_Action
== CTGitPath::LOGACTIONS_DELETED
|| fd
->IsDirectory())
744 CAppUtils::CreateMultipleDirectory(m_strExportDir
+ _T("\\") + fd
->GetContainingDirectory().GetWinPathString());
745 CString filename
= m_strExportDir
+ _T("\\") + fd
->GetWinPathString();
746 if(m_rev1
.m_CommitHash
.ToString() == GIT_REV_ZERO
)
748 if(!CopyFile(g_Git
.CombinePath(fd
), filename
, false))
750 MessageBox(CFormatMessageWrapper(), _T("TortoiseGit"), MB_OK
| MB_ICONERROR
);
756 if(g_Git
.GetOneFile(m_rev1
.m_CommitHash
, *fd
, filename
))
759 out
.Format(IDS_STATUSLIST_CHECKOUTFILEFAILED
, fd
->GetGitPathString(), m_rev1
.m_CommitHash
.ToString(), filename
);
760 if (CMessageBox::Show(nullptr, g_Git
.GetGitLastErr(out
, CGit::GIT_CMD_GETONEFILE
), _T("TortoiseGit"), 2, IDI_WARNING
, CString(MAKEINTRESOURCE(IDS_IGNOREBUTTON
)), CString(MAKEINTRESOURCE(IDS_ABORTBUTTON
))) == 2)
774 BOOL
CFileDiffDlg::OnSetCursor(CWnd
* pWnd
, UINT nHitTest
, UINT message
)
776 if (pWnd
!= &m_cFileList
)
777 return CResizableStandAloneDialog::OnSetCursor(pWnd
, nHitTest
, message
);
778 if (m_bThreadRunning
== 0)
780 HCURSOR hCur
= LoadCursor(NULL
, MAKEINTRESOURCE(IDC_ARROW
));
782 return CResizableStandAloneDialog::OnSetCursor(pWnd
, nHitTest
, message
);
784 HCURSOR hCur
= LoadCursor(NULL
, MAKEINTRESOURCE(IDC_WAIT
));
789 void CFileDiffDlg::OnEnSetfocusFirsturl()
791 GetDlgItem(IDC_FIRSTURL
)->HideCaret();
794 void CFileDiffDlg::OnEnSetfocusSecondurl()
796 GetDlgItem(IDC_SECONDURL
)->HideCaret();
800 void CFileDiffDlg::OnBnClickedSwitchleftright()
803 if (m_bThreadRunning
)
807 CString sFilterString
;
808 m_cFilter
.GetWindowText(sFilterString
);
810 m_cFileList
.SetRedraw(false);
811 m_cFileList
.DeleteAllItems();
812 for (int i
=0; i
<(int)m_arFileList
.GetCount(); ++i
)
814 CTGitPath fd
= m_arFileList
[i
];
815 if (fd
.m_Action
== CTGitPath::LOGACTIONS_ADDED
)
816 fd
.m_Action
= CTGitPath::LOGACTIONS_DELETED
;
817 else if (fd
.m_Action
== CTGitPath::LOGACTIONS_DELETED
)
818 fd
.m_Action
= CTGitPath::LOGACTIONS_ADDED
;
819 std::swap(fd
.m_StatAdd
, fd
.m_StatDel
);
820 (CTGitPath
&)m_arFileList
[i
] = fd
;
822 Filter(sFilterString
);
825 m_cFileList
.SetRedraw(true);
826 CTGitPath path
= m_path1
;
834 this->m_ctrRev1Edit
.GetWindowText(str1
);
835 this->m_ctrRev2Edit
.GetWindowText(str2
);
837 this->m_ctrRev1Edit
.SetWindowText(str2
);
838 this->m_ctrRev2Edit
.SetWindowText(str1
);
841 //KillTimer(IDT_INPUT);
844 void CFileDiffDlg::SetURLLabels(int mask
)
847 // m_cRev1Btn.SetWindowText(m_rev1.m_CommitHash.ToString().Left(6));
848 // m_cRev2Btn.SetWindowText(m_rev2.m_CommitHash.ToString().Left(6));
852 SetDlgItemText(IDC_FIRSTURL
, m_rev1
.m_CommitHash
.ToString().Left(8)+_T(": ")+m_rev1
.GetSubject());
853 if (!m_rev1
.m_CommitHash
.IsEmpty())
854 m_tooltips
.AddTool(IDC_FIRSTURL
,
855 CLoglistUtils::FormatDateAndTime(m_rev1
.GetAuthorDate(), DATE_SHORTDATE
) + _T(" ") + m_rev1
.GetAuthorName());
861 SetDlgItemText(IDC_SECONDURL
,m_rev2
.m_CommitHash
.ToString().Left(8)+_T(": ")+m_rev2
.GetSubject());
862 if (!m_rev2
.m_CommitHash
.IsEmpty())
863 m_tooltips
.AddTool(IDC_SECONDURL
,
864 CLoglistUtils::FormatDateAndTime(m_rev2
.GetAuthorDate(), DATE_SHORTDATE
) + _T(" ") + m_rev2
.GetAuthorName());
867 this->GetDlgItem(IDC_REV2GROUP
)->SetWindowText(CString(MAKEINTRESOURCE(IDS_PROC_FILEDIFF_VERSION2BASE
)));
868 this->GetDlgItem(IDC_REV1GROUP
)->SetWindowText(CString(MAKEINTRESOURCE(IDS_PROC_FILEDIFF_VERSION1
)));
870 if( (mask
&0x3) == 0x3 && !m_rev1
.m_CommitHash
.IsEmpty() && !m_rev2
.m_CommitHash
.IsEmpty())
871 if(m_rev2
.GetCommitterDate() > m_rev1
.GetCommitterDate())
873 this->GetDlgItem(IDC_REV2GROUP
)->SetWindowText(CString(MAKEINTRESOURCE(IDS_PROC_FILEDIFF_VERSION2BASENEWER
)));
875 else if (m_rev2
.GetCommitterDate() < m_rev1
.GetCommitterDate())
877 this->GetDlgItem(IDC_REV1GROUP
)->SetWindowText(CString(MAKEINTRESOURCE(IDS_PROC_FILEDIFF_VERSION1NEWER
)));
881 void CFileDiffDlg::ClearURLabels(int mask
)
885 SetDlgItemText(IDC_FIRSTURL
, _T(""));
886 m_tooltips
.AddTool(IDC_FIRSTURL
, _T(""));
891 SetDlgItemText(IDC_SECONDURL
, _T(""));
892 m_tooltips
.AddTool(IDC_SECONDURL
, _T(""));
895 BOOL
CFileDiffDlg::PreTranslateMessage(MSG
* pMsg
)
897 m_tooltips
.RelayEvent(pMsg
);
898 if (pMsg
->message
== WM_KEYDOWN
)
900 switch (pMsg
->wParam
)
904 if (GetFocus() != GetDlgItem(IDC_FILELIST
))
906 if (GetAsyncKeyState(VK_CONTROL
)&0x8000)
908 // select all entries
909 for (int i
=0; i
<m_cFileList
.GetItemCount(); ++i
)
911 m_cFileList
.SetItemState(i
, LVIS_SELECTED
, LVIS_SELECTED
);
920 if (GetFocus() != GetDlgItem(IDC_FILELIST
))
922 if (GetAsyncKeyState(VK_CONTROL
)&0x8000)
924 CopySelectionToClipboard();
931 if (GetFocus() == GetDlgItem(IDC_FILELIST
))
933 // Return pressed in file list. Show diff, as for double click
934 int selIndex
= m_cFileList
.GetSelectionMark();
935 if ((selIndex
>= 0) && (selIndex
< (int)m_arFileList
.GetCount()))
936 DoDiff(selIndex
, m_bBlame
);
948 return __super::PreTranslateMessage(pMsg
);
951 void CFileDiffDlg::OnCancel()
953 if (m_bThreadRunning
)
961 void CFileDiffDlg::OnHdnItemclickFilelist(NMHDR
*pNMHDR
, LRESULT
*pResult
)
963 LPNMHEADER phdr
= reinterpret_cast<LPNMHEADER
>(pNMHDR
);
964 if (m_bThreadRunning
)
967 if (m_nSortedColumn
== phdr
->iItem
)
968 m_bAscending
= !m_bAscending
;
971 m_nSortedColumn
= phdr
->iItem
;
975 m_cFileList
.SetRedraw(FALSE
);
976 m_cFileList
.DeleteAllItems();
977 m_cFilter
.GetWindowText(temp
);
980 CHeaderCtrl
* pHeader
= m_cFileList
.GetHeaderCtrl();
981 HDITEM HeaderItem
= {0};
982 HeaderItem
.mask
= HDI_FORMAT
;
983 for (int i
=0; i
<pHeader
->GetItemCount(); ++i
)
985 pHeader
->GetItem(i
, &HeaderItem
);
986 HeaderItem
.fmt
&= ~(HDF_SORTDOWN
| HDF_SORTUP
);
987 pHeader
->SetItem(i
, &HeaderItem
);
989 pHeader
->GetItem(m_nSortedColumn
, &HeaderItem
);
990 HeaderItem
.fmt
|= (m_bAscending
? HDF_SORTUP
: HDF_SORTDOWN
);
991 pHeader
->SetItem(m_nSortedColumn
, &HeaderItem
);
993 m_cFileList
.SetRedraw(TRUE
);
998 void CFileDiffDlg::Sort()
1000 if(m_arFileList
.GetCount() < 2)
1005 std::sort(m_arFileList
.m_paths
.begin(), m_arFileList
.m_paths
.end(), &CFileDiffDlg::SortCompare
);
1008 bool CFileDiffDlg::SortCompare(const CTGitPath
& Data1
, const CTGitPath
& Data2
)
1012 switch (m_nSortedColumn
)
1014 case 0: //path column
1015 result
= Data1
.GetWinPathString().Compare(Data2
.GetWinPathString());
1017 case 1: //extension column
1018 result
= Data1
.GetFileExtension().Compare(Data2
.GetFileExtension());
1020 case 2: //action column
1021 result
= Data1
.m_Action
- Data2
.m_Action
;
1024 d1
= CSorter::A2L(Data1
.m_StatAdd
);
1025 d2
= CSorter::A2L(Data2
.m_StatAdd
);
1029 d1
= CSorter::A2L(Data1
.m_StatDel
);;
1030 d2
= CSorter::A2L(Data2
.m_StatDel
);
1036 // sort by path name as second priority
1037 if (m_nSortedColumn
!= 0 && result
== 0)
1038 result
= Data1
.GetWinPathString().Compare(Data2
.GetWinPathString());
1046 void CFileDiffDlg::OnBnClickedRev1btn()
1048 ClickRevButton(&this->m_cRev1Btn
,&this->m_rev1
, &this->m_ctrRev1Edit
);
1051 void CFileDiffDlg::ClickRevButton(CMenuButton
*button
, GitRev
*rev
, CACEdit
*edit
)
1053 INT_PTR entry
=button
->GetCurrentEntry();
1054 if(entry
== 0) /* Browse Refence*/
1057 CString str
= CBrowseRefsDlg::PickRef();
1061 if(FillRevFromString(rev
,str
))
1064 edit
->SetWindowText(str
);
1068 if(entry
== 1) /*Log*/
1071 dlg
.SetSelect(true);
1072 if(dlg
.DoModal() == IDOK
)
1074 if( dlg
.GetSelectedHash().IsEmpty() )
1077 if(FillRevFromString(rev
,dlg
.GetSelectedHash()))
1080 edit
->SetWindowText(dlg
.GetSelectedHash());
1087 if(entry
== 2) /*RefLog*/
1090 if(dlg
.DoModal() == IDOK
)
1092 if(FillRevFromString(rev
,dlg
.m_SelectedHash
))
1095 edit
->SetWindowText(dlg
.m_SelectedHash
);
1104 InterlockedExchange(&m_bThreadRunning
, TRUE
);
1105 if (AfxBeginThread(DiffThreadEntry
, this)==NULL
)
1107 InterlockedExchange(&m_bThreadRunning
, FALSE
);
1108 CMessageBox::Show(NULL
, IDS_ERR_THREADSTARTFAILED
, IDS_APPNAME
, MB_OK
| MB_ICONERROR
);
1110 KillTimer(IDT_INPUT
);
1113 void CFileDiffDlg::OnBnClickedRev2btn()
1115 ClickRevButton(&this->m_cRev2Btn
,&this->m_rev2
, &this->m_ctrRev2Edit
);
1118 LRESULT
CFileDiffDlg::OnClickedCancelFilter(WPARAM
/*wParam*/, LPARAM
/*lParam*/)
1120 if (m_bThreadRunning
)
1122 SetTimer(IDT_FILTER
, 1000, NULL
);
1126 KillTimer(IDT_FILTER
);
1128 m_cFileList
.SetRedraw(FALSE
);
1129 m_arFilteredList
.clear();
1130 m_cFileList
.DeleteAllItems();
1134 m_cFileList
.SetRedraw(TRUE
);
1138 void CFileDiffDlg::OnEnChangeFilter()
1140 SetTimer(IDT_FILTER
, 1000, NULL
);
1143 void CFileDiffDlg::OnTimer(UINT_PTR nIDEvent
)
1145 if (m_bThreadRunning
)
1148 if( nIDEvent
== IDT_FILTER
)
1150 CString sFilterText
;
1151 KillTimer(IDT_FILTER
);
1152 m_cFilter
.GetWindowText(sFilterText
);
1154 m_cFileList
.SetRedraw(FALSE
);
1155 m_cFileList
.DeleteAllItems();
1157 Filter(sFilterText
);
1159 m_cFileList
.SetRedraw(TRUE
);
1161 __super::OnTimer(nIDEvent
);
1164 if( nIDEvent
== IDT_INPUT
)
1166 KillTimer(IDT_INPUT
);
1167 TRACE(_T("Input Timer\r\n"));
1172 this->m_ctrRev1Edit
.GetWindowText(str
);
1175 if (!gitrev
.GetCommit(str
))
1181 catch (const char *msg
)
1183 CMessageBox::Show(m_hWnd
, _T("Could not get commit ") + str
+ _T("\nlibgit reports:\n") + CString(msg
), _T("TortoiseGit"), MB_ICONERROR
);
1186 this->m_ctrRev2Edit
.GetWindowText(str
);
1190 if (!gitrev
.GetCommit(str
))
1196 catch (const char *msg
)
1198 CMessageBox::Show(m_hWnd
, _T("Could not get commit ") + str
+ _T("\nlibgit reports:\n") + CString(msg
), _T("TortoiseGit"), MB_ICONERROR
);
1201 this->SetURLLabels(mask
);
1206 InterlockedExchange(&m_bThreadRunning
, TRUE
);
1207 if (AfxBeginThread(DiffThreadEntry
, this)==NULL
)
1209 InterlockedExchange(&m_bThreadRunning
, FALSE
);
1210 CMessageBox::Show(NULL
, IDS_ERR_THREADSTARTFAILED
, IDS_APPNAME
, MB_OK
| MB_ICONERROR
);
1216 void CFileDiffDlg::Filter(CString sFilterText
)
1218 sFilterText
.MakeLower();
1220 m_arFilteredList
.clear();
1222 for (int i
=0;i
<m_arFileList
.GetCount();i
++)
1224 CString sPath
= m_arFileList
[i
].GetGitPathString();
1226 if (sPath
.Find(sFilterText
) >= 0)
1228 m_arFilteredList
.push_back((CTGitPath
*)&(m_arFileList
[i
]));
1231 for (std::vector
<CTGitPath
*>::const_iterator it
= m_arFilteredList
.begin(); it
!= m_arFilteredList
.end(); ++it
)
1237 void CFileDiffDlg::CopySelectionToClipboard(BOOL isFull
)
1239 // copy all selected paths to the clipboard
1240 POSITION pos
= m_cFileList
.GetFirstSelectedItemPosition();
1242 CString sTextForClipboard
;
1243 while ((index
= m_cFileList
.GetNextSelectedItem(pos
)) >= 0)
1245 sTextForClipboard
+= m_cFileList
.GetItemText(index
, 0);
1246 sTextForClipboard
+= _T("\t");
1250 sTextForClipboard
+= _T("\r\n");
1255 sTextForClipboard
+= m_cFileList
.GetItemText(index
, 1);
1256 sTextForClipboard
+= _T("\t");
1257 sTextForClipboard
+= m_cFileList
.GetItemText(index
, 2);
1258 sTextForClipboard
+= _T("\t");
1259 sTextForClipboard
+= m_cFileList
.GetItemText(index
, 3);
1260 sTextForClipboard
+= _T("\t");
1261 sTextForClipboard
+= m_cFileList
.GetItemText(index
, 4);
1262 sTextForClipboard
+= _T("\r\n");
1265 CStringUtils::WriteAsciiStringToClipboard(sTextForClipboard
);
1269 LRESULT
CFileDiffDlg::OnRefLoad(WPARAM
/*wParam*/, LPARAM
/*lParam*/)
1271 for (size_t i
= 0; i
< m_Reflist
.size(); ++i
)
1273 CString str
=m_Reflist
[i
];
1275 if(str
.Find(_T("remotes/")) == 0)
1278 m_ctrRev1Edit
.AddSearchString(str
);
1279 m_ctrRev2Edit
.AddSearchString(str
);
1284 BOOL
CFileDiffDlg::DestroyWindow()
1286 return CResizableStandAloneDialog::DestroyWindow();
1289 LRESULT
CFileDiffDlg::OnEnUpdate(WPARAM
/*wParam*/, LPARAM lParam
)
1291 if(lParam
== IDC_REV1EDIT
)
1293 OnTextUpdate(&this->m_ctrRev1Edit
);
1296 if(lParam
== IDC_REV2EDIT
)
1298 OnTextUpdate(&this->m_ctrRev2Edit
);
1299 ClearURLabels(1<<1);
1304 void CFileDiffDlg::OnTextUpdate(CACEdit
* /*pEdit*/)
1306 SetTimer(IDT_INPUT
, 1000, NULL
);
1307 this->m_cFileList
.ShowText(_T("Wait For input validate version"));
1310 int CFileDiffDlg::RevertSelectedItemToVersion(CString rev
)
1312 if (rev
.IsEmpty() || rev
== GIT_REV_ZERO
)
1315 POSITION pos
= m_cFileList
.GetFirstSelectedItemPosition();
1318 while ((index
= m_cFileList
.GetNextSelectedItem(pos
)) >= 0)
1321 CTGitPath
*fentry
= (CTGitPath
*)m_arFilteredList
[index
];
1322 cmd
.Format(_T("git.exe checkout %s -- \"%s\""), rev
, fentry
->GetGitPathString());
1323 if (g_Git
.Run(cmd
, &out
, CP_UTF8
))
1325 if (CMessageBox::Show(NULL
, out
, _T("TortoiseGit"), 2, IDI_WARNING
, CString(MAKEINTRESOURCE(IDS_IGNOREBUTTON
)), CString(MAKEINTRESOURCE(IDS_ABORTBUTTON
))) == 2)
1333 out
.Format(IDS_STATUSLIST_FILESREVERTED
, count
, rev
);
1334 CMessageBox::Show(NULL
, out
, _T("TortoiseGit"), MB_OK
);
1338 static void AppendMenuChecked(CMenu
&menu
, UINT nTextID
, UINT_PTR nItemID
, BOOL checked
= FALSE
, BOOL enabled
= TRUE
)
1341 text
.LoadString(nTextID
);
1342 menu
.AppendMenu(MF_STRING
| (enabled
? MF_ENABLED
: MF_DISABLED
) | (checked
? MF_CHECKED
: MF_UNCHECKED
), nItemID
, text
);
1345 #define DIFFOPTION_IGNORESPACEATEOL 1
1346 #define DIFFOPTION_IGNORESPACECHANGE 2
1347 #define DIFFOPTION_IGNOREALLSPACE 3
1348 #define DIFFOPTION_IGNORBLANKLINES 4
1350 void CFileDiffDlg::OnBnClickedDiffoption()
1353 if (popup
.CreatePopupMenu())
1355 AppendMenuChecked(popup
, IDS_DIFFOPTION_IGNORESPACEATEOL
, DIFFOPTION_IGNORESPACEATEOL
, m_bIgnoreSpaceAtEol
);
1356 AppendMenuChecked(popup
, IDS_DIFFOPTION_IGNORESPACECHANGE
, DIFFOPTION_IGNORESPACECHANGE
, m_bIgnoreSpaceChange
);
1357 AppendMenuChecked(popup
, IDS_DIFFOPTION_IGNOREALLSPACE
, DIFFOPTION_IGNOREALLSPACE
, m_bIgnoreAllSpace
);
1358 AppendMenuChecked(popup
, IDS_DIFFOPTION_IGNORBLANKLINES
, DIFFOPTION_IGNORBLANKLINES
, m_bIgnoreBlankLines
);
1362 GetDlgItem(IDC_DIFFOPTION
)->GetWindowRect(&rect
);
1363 int selection
= popup
.TrackPopupMenu(TPM_RETURNCMD
| TPM_LEFTALIGN
| TPM_NONOTIFY
, rect
.left
, rect
.bottom
, this, 0);
1366 case DIFFOPTION_IGNORESPACEATEOL
:
1367 m_bIgnoreSpaceAtEol
= !m_bIgnoreSpaceAtEol
;
1370 case DIFFOPTION_IGNORESPACECHANGE
:
1371 m_bIgnoreSpaceChange
= !m_bIgnoreSpaceChange
;
1374 case DIFFOPTION_IGNOREALLSPACE
:
1375 m_bIgnoreAllSpace
= !m_bIgnoreAllSpace
;
1378 case DIFFOPTION_IGNORBLANKLINES
:
1379 m_bIgnoreBlankLines
= !m_bIgnoreBlankLines
;
1389 void CFileDiffDlg::OnBnClickedLog()
1392 dlg
.SetRange(m_rev2
.m_CommitHash
.ToString() + _T("..") + m_rev1
.m_CommitHash
.ToString());