Dropped unused variables
[TortoiseGit.git] / src / TortoiseProc / FileDiffDlg.cpp
blobb0963ce3248d7dc7804aaba84aea62a50c9b10b2
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2013 - 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.
20 #include "stdafx.h"
21 #include "TortoiseProc.h"
22 #include "UnicodeUtils.h"
23 #include "MessageBox.h"
24 #include "AppUtils.h"
25 #include "TempFile.h"
26 #include "SysImageList.h"
27 #include "IconMenu.h"
28 //#include "GitProperties.h"
29 #include "StringUtils.h"
30 #include "PathUtils.h"
31 #include "BrowseFolder.h"
32 #include ".\filediffdlg.h"
33 #include "gitdiff.h"
34 #include "LoglistCommonResource.h"
35 #include "LoglistUtils.h"
36 #include "BrowseRefsDlg.h"
37 #include "LogDlg.h"
38 #include "RefLogDlg.h"
39 #include "GitStatusListCtrl.h"
40 #include "FormatMessageWrapper.h"
42 #define ID_COMPARE 1
43 #define ID_BLAME 2
44 #define ID_SAVEAS 3
45 #define ID_EXPORT 4
46 #define ID_CLIPBOARD_PATH 5
47 #define ID_CLIPBOARD_ALL 6
48 #define ID_LOG 7
49 #define ID_GNUDIFFCOMPARE 8
50 #define ID_REVERT1 9
51 #define ID_REVERT2 10
53 BOOL CFileDiffDlg::m_bAscending = FALSE;
54 int CFileDiffDlg::m_nSortedColumn = -1;
57 IMPLEMENT_DYNAMIC(CFileDiffDlg, CResizableStandAloneDialog)
58 CFileDiffDlg::CFileDiffDlg(CWnd* pParent /*=NULL*/)
59 : CResizableStandAloneDialog(CFileDiffDlg::IDD, pParent),
60 m_bBlame(false),
61 m_pProgDlg(NULL),
62 m_bCancelled(false)
64 m_bLoadingRef=FALSE;
67 CFileDiffDlg::~CFileDiffDlg()
71 void CFileDiffDlg::DoDataExchange(CDataExchange* pDX)
73 CResizableStandAloneDialog::DoDataExchange(pDX);
74 DDX_Control(pDX, IDC_FILELIST, m_cFileList);
75 DDX_Control(pDX, IDC_SWITCHLEFTRIGHT, m_SwitchButton);
76 DDX_Control(pDX, IDC_REV1BTN, m_cRev1Btn);
77 DDX_Control(pDX, IDC_REV2BTN, m_cRev2Btn);
78 DDX_Control(pDX, IDC_FILTER, m_cFilter);
79 DDX_Control(pDX, IDC_REV1EDIT, m_ctrRev1Edit);
80 DDX_Control(pDX, IDC_REV2EDIT, m_ctrRev2Edit);
84 BEGIN_MESSAGE_MAP(CFileDiffDlg, CResizableStandAloneDialog)
85 ON_NOTIFY(NM_DBLCLK, IDC_FILELIST, OnNMDblclkFilelist)
86 ON_NOTIFY(LVN_GETINFOTIP, IDC_FILELIST, OnLvnGetInfoTipFilelist)
87 ON_NOTIFY(NM_CUSTOMDRAW, IDC_FILELIST, OnNMCustomdrawFilelist)
88 ON_WM_CONTEXTMENU()
89 ON_WM_SETCURSOR()
90 ON_EN_SETFOCUS(IDC_SECONDURL, &CFileDiffDlg::OnEnSetfocusSecondurl)
91 ON_EN_SETFOCUS(IDC_FIRSTURL, &CFileDiffDlg::OnEnSetfocusFirsturl)
92 ON_BN_CLICKED(IDC_SWITCHLEFTRIGHT, &CFileDiffDlg::OnBnClickedSwitchleftright)
93 ON_NOTIFY(HDN_ITEMCLICK, 0, &CFileDiffDlg::OnHdnItemclickFilelist)
94 ON_BN_CLICKED(IDC_REV1BTN, &CFileDiffDlg::OnBnClickedRev1btn)
95 ON_BN_CLICKED(IDC_REV2BTN, &CFileDiffDlg::OnBnClickedRev2btn)
96 ON_MESSAGE(WM_FILTEREDIT_CANCELCLICKED, OnClickedCancelFilter)
97 ON_EN_CHANGE(IDC_FILTER, &CFileDiffDlg::OnEnChangeFilter)
98 ON_WM_TIMER()
99 ON_MESSAGE(ENAC_UPDATE, &CFileDiffDlg::OnEnUpdate)
100 ON_MESSAGE(MSG_REF_LOADED, OnRefLoad)
101 END_MESSAGE_MAP()
104 void CFileDiffDlg::SetDiff(CTGitPath * path, GitRev rev1, GitRev rev2)
106 if(path!=NULL)
108 m_path1 = *path;
109 m_path2 = *path;
110 m_sFilter = path->GetGitPathString();
112 m_rev1 = rev1;
113 m_rev2 = rev2;
116 void CFileDiffDlg::SetDiff(CTGitPath * path, CString hash1, CString hash2)
118 if(path!=NULL)
120 m_path1 = *path;
121 m_path2 = *path;
122 m_sFilter = path->GetGitPathString();
125 BYTE_VECTOR logout;
127 if(hash1 == GIT_REV_ZERO)
129 m_rev1.m_CommitHash.Empty();
130 m_rev1.GetSubject() = CString(MAKEINTRESOURCE(IDS_git_DEPTH_WORKING));
132 else
136 m_rev1.GetCommit(hash1);
138 catch (const char *msg)
140 MessageBox(_T("Could not get commit ") + hash1 + _T("\nlibgit reports:\n") + CString(msg), _T("TortoiseGit"), MB_ICONERROR);
144 logout.clear();
146 if(hash2 == GIT_REV_ZERO)
148 m_rev2.m_CommitHash.Empty();
149 m_rev2.GetSubject() = CString(MAKEINTRESOURCE(IDS_git_DEPTH_WORKING));
151 else
155 m_rev2.GetCommit(hash2);
157 catch (const char *msg)
159 MessageBox(_T("Could not get commit ") + hash2 + _T("\nlibgit reports:\n") + CString(msg), _T("TortoiseGit"), MB_ICONERROR);
164 void CFileDiffDlg::SetDiff(CTGitPath * path, GitRev rev1)
166 if(path!=NULL)
168 m_path1 = *path;
169 m_path2 = *path;
170 m_sFilter = path->GetGitPathString();
172 m_rev1 = rev1;
173 m_rev2.m_CommitHash.Empty();
174 m_rev2.GetSubject() = CString(MAKEINTRESOURCE(IDS_PROC_PREVIOUSVERSION));
176 //this->GetDlgItem()->EnableWindow(FALSE);
179 BOOL CFileDiffDlg::OnInitDialog()
181 CResizableStandAloneDialog::OnInitDialog();
182 CString temp;
184 CString sWindowTitle;
185 GetWindowText(sWindowTitle);
186 CAppUtils::SetWindowTitle(m_hWnd, g_Git.m_CurrentDir, sWindowTitle);
188 this->m_ctrRev1Edit.Init();
189 this->m_ctrRev2Edit.Init();
191 m_tooltips.Create(this);
192 m_tooltips.AddTool(IDC_SWITCHLEFTRIGHT, IDS_FILEDIFF_SWITCHLEFTRIGHT_TT);
194 m_cFileList.SetRedraw(false);
195 m_cFileList.DeleteAllItems();
196 DWORD exStyle = LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER | LVS_EX_INFOTIP;
197 m_cFileList.SetExtendedStyle(exStyle);
199 m_nIconFolder = SYS_IMAGE_LIST().GetDirIconIndex();
200 m_cFileList.SetImageList(&SYS_IMAGE_LIST(), LVSIL_SMALL);
202 m_SwitchButton.SetImage((HICON)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_SWITCHLEFTRIGHT), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR));
203 m_SwitchButton.Invalidate();
205 m_cFilter.SetCancelBitmaps(IDI_CANCELNORMAL, IDI_CANCELPRESSED);
206 m_cFilter.SetInfoIcon(IDI_FILTEREDIT);
207 temp.LoadString(IDS_FILEDIFF_FILTERCUE);
208 temp = _T(" ")+temp;
209 m_cFilter.SetCueBanner(temp);
210 if (!m_sFilter.IsEmpty())
211 m_cFilter.SetWindowText(m_sFilter);
213 int c = ((CHeaderCtrl*)(m_cFileList.GetDlgItem(0)))->GetItemCount()-1;
214 while (c>=0)
215 m_cFileList.DeleteColumn(c--);
217 temp.LoadString(IDS_FILEDIFF_FILE);
218 m_cFileList.InsertColumn(0, temp);
219 temp.LoadString(IDS_FILEDIFF_EXT);
220 m_cFileList.InsertColumn(1, temp);
221 temp.LoadString(IDS_FILEDIFF_ACTION);
222 m_cFileList.InsertColumn(2, temp);
224 temp.LoadString(IDS_FILEDIFF_STATADD);
225 m_cFileList.InsertColumn(3, temp);
226 temp.LoadString(IDS_FILEDIFF_STATDEL);
227 m_cFileList.InsertColumn(4, temp);
229 int mincol = 0;
230 int maxcol = ((CHeaderCtrl*)(m_cFileList.GetDlgItem(0)))->GetItemCount()-1;
231 int col;
232 for (col = mincol; col <= maxcol; col++)
234 m_cFileList.SetColumnWidth(col,LVSCW_AUTOSIZE_USEHEADER);
237 m_cFileList.SetRedraw(true);
239 AddAnchor(IDC_DIFFSTATIC1, TOP_LEFT, TOP_RIGHT);
240 AddAnchor(IDC_SWITCHLEFTRIGHT, TOP_RIGHT);
241 AddAnchor(IDC_FIRSTURL, TOP_LEFT, TOP_RIGHT);
242 AddAnchor(IDC_REV1BTN, TOP_RIGHT);
243 //AddAnchor(IDC_DIFFSTATIC2, TOP_LEFT, TOP_RIGHT);
244 AddAnchor(IDC_SECONDURL, TOP_LEFT, TOP_RIGHT);
245 AddAnchor(IDC_REV2BTN, TOP_RIGHT);
246 AddAnchor(IDC_FILTER, TOP_LEFT, TOP_RIGHT);
247 AddAnchor(IDC_FILELIST, TOP_LEFT, BOTTOM_RIGHT);
248 AddAnchor(IDC_REV1GROUP,TOP_LEFT,TOP_RIGHT);
249 AddAnchor(IDC_REV2GROUP,TOP_LEFT,TOP_RIGHT);
250 AddAnchor(IDC_REV1EDIT,TOP_LEFT);
251 AddAnchor(IDC_REV2EDIT,TOP_LEFT);
253 EnableSaveRestore(_T("FileDiffDlg"));
255 if(this->m_strRev1.IsEmpty())
256 this->m_ctrRev1Edit.SetWindowText(this->m_rev1.m_CommitHash.ToString());
257 else
259 bool rev1fail = false;
262 rev1fail = !!m_rev1.GetCommit(m_strRev1);
264 catch (const char *msg)
266 rev1fail = true;
267 MessageBox(_T("Could not get commit ") + m_strRev1 + _T("\nlibgit reports:\n") + CString(msg), _T("TortoiseGit"), MB_ICONERROR);
269 if (rev1fail)
271 CString msg;
272 msg.Format(IDS_PROC_REFINVALID, m_strRev1);
273 this->m_FileListText += msg;
276 this->m_ctrRev1Edit.SetWindowText(m_strRev1);
279 if(this->m_strRev2.IsEmpty())
280 this->m_ctrRev2Edit.SetWindowText(this->m_rev2.m_CommitHash.ToString());
281 else
283 bool rev2fail = false;
286 rev2fail = !!m_rev2.GetCommit(m_strRev2);
288 catch (const char *msg)
290 rev2fail = true;
291 MessageBox(_T("Could not get commit ") + m_strRev2 + _T("\nlibgit reports:\n") + CString(msg), _T("TortoiseGit"), MB_ICONERROR);
293 if (rev2fail)
295 CString msg;
296 msg.Format(IDS_PROC_REFINVALID, m_strRev2);
297 this->m_FileListText += msg;
300 this->m_ctrRev2Edit.SetWindowText(m_strRev2);
303 SetURLLabels();
305 InterlockedExchange(&m_bThreadRunning, TRUE);
306 if (AfxBeginThread(DiffThreadEntry, this)==NULL)
308 InterlockedExchange(&m_bThreadRunning, FALSE);
309 CMessageBox::Show(NULL, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
312 InterlockedExchange(&m_bLoadingRef, TRUE);
313 if (AfxBeginThread(LoadRefThreadEntry, this)==NULL)
315 InterlockedExchange(&m_bLoadingRef, FALSE);
316 CMessageBox::Show(NULL, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
319 this->m_cRev1Btn.AddEntry(CString(MAKEINTRESOURCE(IDS_REFBROWSE)));
320 this->m_cRev1Btn.AddEntry(CString(MAKEINTRESOURCE(IDS_LOG)));
321 this->m_cRev1Btn.AddEntry(CString(MAKEINTRESOURCE(IDS_REFLOG)));
323 this->m_cRev2Btn.AddEntry(CString(MAKEINTRESOURCE(IDS_REFBROWSE)));
324 this->m_cRev2Btn.AddEntry(CString(MAKEINTRESOURCE(IDS_LOG)));
325 this->m_cRev2Btn.AddEntry(CString(MAKEINTRESOURCE(IDS_REFLOG)));
327 // Start with focus on file list
328 GetDlgItem(IDC_FILELIST)->SetFocus();
330 if(m_rev2.m_CommitHash.IsEmpty())
331 m_SwitchButton.EnableWindow(FALSE);
333 KillTimer(IDT_INPUT);
334 return FALSE;
337 #if 0
338 svn_error_t* CFileDiffDlg::DiffSummarizeCallback(const CTGitPath& path,
339 svn_client_diff_summarize_kind_t kind,
340 bool propchanged, svn_node_kind_t node)
342 CTGitPath* fd;
343 fd.path = path;
344 fd.kind = kind;
345 fd.node = node;
346 fd.propchanged = propchanged;
347 m_arFileList.push_back(fd);
348 return Git_NO_ERROR;
350 #endif
352 UINT CFileDiffDlg::DiffThreadEntry(LPVOID pVoid)
354 return ((CFileDiffDlg*)pVoid)->DiffThread();
357 UINT CFileDiffDlg::DiffThread()
359 RefreshCursor();
360 m_cFileList.ShowText(CString(MAKEINTRESOURCE(IDS_FILEDIFF_WAIT)));
361 m_cFileList.DeleteAllItems();
362 m_arFileList.Clear();
363 EnableInputControl(false);
364 #if 0
365 bool bSuccess = true;
366 if (m_bDoPegDiff)
368 // bSuccess = DiffSummarizePeg(m_path1, m_peg, m_rev1, m_rev2, m_depth, m_bIgnoreancestry);
370 else
372 // bSuccess = DiffSummarize(m_path1, m_rev1, m_path2, m_rev2, m_depth, m_bIgnoreancestry);
374 // if (!bSuccess)
375 // {
376 // m_cFileList.ShowText(GetLastErrorMessage());
377 // InterlockedExchange(&m_bThreadRunning, FALSE);
378 // return 0;
379 // }
380 #endif
382 if( m_rev1.m_CommitHash.IsEmpty() || m_rev2.m_CommitHash.IsEmpty())
383 g_Git.RefreshGitIndex();
385 g_Git.GetCommitDiffList(m_rev1.m_CommitHash.ToString(),m_rev2.m_CommitHash.ToString(),m_arFileList);
387 CString sFilterText;
388 m_cFilter.GetWindowText(sFilterText);
389 m_cFileList.SetRedraw(false);
390 Filter(sFilterText);
391 if (m_arFileList.GetCount()>0)
393 // Highlight first entry in file list
394 m_cFileList.SetSelectionMark(0);
395 m_cFileList.SetItemState(0, LVIS_SELECTED, LVIS_SELECTED);
398 int mincol = 0;
399 int maxcol = ((CHeaderCtrl*)(m_cFileList.GetDlgItem(0)))->GetItemCount()-1;
400 int col;
401 for (col = mincol; col <= maxcol; col++)
403 m_cFileList.SetColumnWidth(col,LVSCW_AUTOSIZE_USEHEADER);
406 m_cFileList.ClearText();
407 m_cFileList.SetRedraw(true);
409 InterlockedExchange(&m_bThreadRunning, FALSE);
410 InvalidateRect(NULL);
411 RefreshCursor();
412 EnableInputControl(true);
413 return 0;
416 int CFileDiffDlg::AddEntry(const CTGitPath * fd)
418 int ret = -1;
419 if (fd)
421 int index = m_cFileList.GetItemCount();
423 int icon_idx = 0;
424 if (fd->IsDirectory())
425 icon_idx = m_nIconFolder;
426 else
427 icon_idx = SYS_IMAGE_LIST().GetPathIconIndex(fd->GetGitPathString());
429 ret = m_cFileList.InsertItem(index, fd->GetGitPathString(), icon_idx);
430 m_cFileList.SetItemText(index, 1, ((CTGitPath*)fd)->GetFileExtension());
431 m_cFileList.SetItemText(index, 2, ((CTGitPath*)fd)->GetActionName());
432 m_cFileList.SetItemText(index, 3, ((CTGitPath*)fd)->m_StatAdd);
433 m_cFileList.SetItemText(index, 4, ((CTGitPath*)fd)->m_StatDel);
435 return ret;
438 void CFileDiffDlg::EnableInputControl(bool b)
440 this->m_ctrRev1Edit.EnableWindow(b);
441 this->m_ctrRev2Edit.EnableWindow(b);
442 this->m_cRev1Btn.EnableWindow(b);
443 this->m_cRev2Btn.EnableWindow(b);
444 m_cFilter.EnableWindow(b);
445 m_SwitchButton.EnableWindow(b);
448 void CFileDiffDlg::DoDiff(int selIndex, bool blame)
450 CGitDiff diff;
451 CTGitPath* fd2 = m_arFilteredList[selIndex];
452 CTGitPath* fd1 = fd2;
453 if (fd2->m_Action & CTGitPath::LOGACTIONS_REPLACED)
454 fd1 = new CTGitPath(fd2->GetGitOldPathString());
455 diff.Diff(fd2, fd1, this->m_rev1.m_CommitHash.ToString(), this->m_rev2.m_CommitHash.ToString(), blame, FALSE);
459 void CFileDiffDlg::OnNMDblclkFilelist(NMHDR *pNMHDR, LRESULT *pResult)
461 *pResult = 0;
462 LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
463 int selIndex = pNMLV->iItem;
464 if (selIndex < 0)
465 return;
466 if (selIndex >= (int)m_arFilteredList.size())
467 return;
469 DoDiff(selIndex, m_bBlame);
472 void CFileDiffDlg::OnLvnGetInfoTipFilelist(NMHDR *pNMHDR, LRESULT *pResult)
475 LPNMLVGETINFOTIP pGetInfoTip = reinterpret_cast<LPNMLVGETINFOTIP>(pNMHDR);
476 if (pGetInfoTip->iItem >= (int)m_arFilteredList.size())
477 return;
479 CString path = m_path1.GetGitPathString() + _T("/") + m_arFilteredList[pGetInfoTip->iItem]->GetGitPathString();
480 if (pGetInfoTip->cchTextMax > path.GetLength())
481 _tcsncpy_s(pGetInfoTip->pszText, pGetInfoTip->cchTextMax, path, pGetInfoTip->cchTextMax);
483 *pResult = 0;
486 void CFileDiffDlg::OnNMCustomdrawFilelist(NMHDR *pNMHDR, LRESULT *pResult)
488 NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>( pNMHDR );
489 // Take the default processing unless we set this to something else below.
490 *pResult = CDRF_DODEFAULT;
492 // First thing - check the draw stage. If it's the control's prepaint
493 // stage, then tell Windows we want messages for every item.
495 if ( CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage )
497 *pResult = CDRF_NOTIFYITEMDRAW;
499 else if ( CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage )
501 // This is the prepaint stage for an item. Here's where we set the
502 // item's text color. Our return value will tell Windows to draw the
503 // item itself, but it will use the new color we set here.
505 // Tell Windows to paint the control itself.
506 *pResult = CDRF_DODEFAULT;
508 COLORREF crText = GetSysColor(COLOR_WINDOWTEXT);
510 if (m_arFilteredList.size() > pLVCD->nmcd.dwItemSpec)
512 CTGitPath * fd = m_arFilteredList[pLVCD->nmcd.dwItemSpec];
513 switch (fd->m_Action)
515 case CTGitPath::LOGACTIONS_ADDED:
516 crText = m_colors.GetColor(CColors::Added);
517 break;
518 case CTGitPath::LOGACTIONS_DELETED:
519 crText = m_colors.GetColor(CColors::Deleted);
520 break;
521 case CTGitPath::LOGACTIONS_MODIFIED:
522 crText = m_colors.GetColor(CColors::Modified);
523 break;
524 //case svn_client_diff_summarize_kind_normal:
525 default:
526 //if (fd.propchanged)
527 crText = m_colors.GetColor(CColors::PropertyChanged);
528 break;
531 // Store the color back in the NMLVCUSTOMDRAW struct.
532 pLVCD->clrText = crText;
536 UINT CFileDiffDlg::LoadRefThread()
538 g_Git.GetBranchList(m_Reflist,NULL,CGit::BRANCH_ALL_F);
539 g_Git.GetTagList(m_Reflist);
541 this->PostMessage(MSG_REF_LOADED);
542 InterlockedExchange(&m_bLoadingRef, FALSE);
543 return 0;
546 void CFileDiffDlg::OnContextMenu(CWnd* pWnd, CPoint point)
548 if ((pWnd==0)||(pWnd != &m_cFileList))
549 return;
550 if (m_cFileList.GetSelectedCount() == 0)
551 return;
552 // if the context menu is invoked through the keyboard, we have to use
553 // a calculated position on where to anchor the menu on
554 if ((point.x == -1) && (point.y == -1))
556 CRect rect;
557 m_cFileList.GetItemRect(m_cFileList.GetSelectionMark(), &rect, LVIR_LABEL);
558 m_cFileList.ClientToScreen(&rect);
559 point = rect.CenterPoint();
561 CIconMenu popup;
562 if (popup.CreatePopupMenu())
564 CString menuText;
565 popup.AppendMenuIcon(ID_COMPARE, IDS_LOG_POPUP_COMPARETWO, IDI_DIFF);
566 popup.AppendMenuIcon(ID_GNUDIFFCOMPARE, IDS_LOG_POPUP_GNUDIFF, IDI_DIFF);
567 popup.AppendMenu(MF_SEPARATOR, NULL);
568 menuText.Format(IDS_FILEDIFF_POPREVERTTOREV, m_rev1.m_CommitHash.ToString().Left(g_Git.GetShortHASHLength()));
569 popup.AppendMenuIcon(ID_REVERT1, menuText, IDI_REVERT);
570 menuText.Format(IDS_FILEDIFF_POPREVERTTOREV, m_rev2.m_CommitHash.ToString().Left(g_Git.GetShortHASHLength()));
571 popup.AppendMenuIcon(ID_REVERT2, menuText, IDI_REVERT);
572 popup.AppendMenu(MF_SEPARATOR, NULL);
573 popup.AppendMenuIcon(ID_LOG, IDS_FILEDIFF_LOG, IDI_LOG);
574 popup.AppendMenuIcon(ID_BLAME, IDS_FILEDIFF_POPBLAME, IDI_BLAME);
575 popup.AppendMenu(MF_SEPARATOR, NULL);
576 popup.AppendMenuIcon(ID_EXPORT, IDS_FILEDIFF_POPEXPORT, IDI_EXPORT);
577 popup.AppendMenu(MF_SEPARATOR, NULL);
578 popup.AppendMenuIcon(ID_SAVEAS, IDS_FILEDIFF_POPSAVELIST, IDI_SAVEAS);
579 popup.AppendMenuIcon(ID_CLIPBOARD_PATH, IDS_STATUSLIST_CONTEXT_COPY, IDI_COPYCLIP);
580 popup.AppendMenuIcon(ID_CLIPBOARD_ALL, IDS_STATUSLIST_CONTEXT_COPYEXT, IDI_COPYCLIP);
582 int cmd = popup.TrackPopupMenu(TPM_RETURNCMD | TPM_LEFTALIGN | TPM_NONOTIFY, point.x, point.y, this, 0);
583 m_bCancelled = false;
584 switch (cmd)
586 case ID_COMPARE:
588 POSITION pos = m_cFileList.GetFirstSelectedItemPosition();
589 while (pos)
591 int index = m_cFileList.GetNextSelectedItem(pos);
592 DoDiff(index, false);
595 break;
596 case ID_GNUDIFFCOMPARE:
598 POSITION pos = m_cFileList.GetFirstSelectedItemPosition();
599 while (pos)
601 CTGitPath *fd2 = m_arFilteredList[m_cFileList.GetNextSelectedItem(pos)];
602 CTGitPath *fd1 = fd2;
603 if (fd2->m_Action & CTGitPath::LOGACTIONS_REPLACED)
604 fd1 = new CTGitPath(fd2->GetGitOldPathString());
605 CAppUtils::StartShowUnifiedDiff(m_hWnd, *fd2, m_rev2.m_CommitHash.ToString(), *fd1, m_rev1.m_CommitHash.ToString());
608 break;
609 case ID_REVERT1:
610 RevertSelectedItemToVersion(m_rev1.m_CommitHash.ToString());
611 break;
612 case ID_REVERT2:
613 RevertSelectedItemToVersion(m_rev2.m_CommitHash.ToString());
614 break;
615 case ID_BLAME:
617 POSITION pos = m_cFileList.GetFirstSelectedItemPosition();
618 while (pos)
620 int index = m_cFileList.GetNextSelectedItem(pos);
621 CAppUtils::LaunchTortoiseBlame(m_arFilteredList[index]->GetWinPathString(), m_rev1.m_CommitHash.ToString());
624 break;
625 case ID_LOG:
627 POSITION pos = m_cFileList.GetFirstSelectedItemPosition();
628 while (pos)
630 int index = m_cFileList.GetNextSelectedItem(pos);
631 CString cmd = _T("/command:log");
632 cmd += _T(" /path:\"")+m_arFilteredList[index]->GetWinPathString()+_T("\" ");
633 cmd += _T(" /endrev:")+m_rev1.m_CommitHash.ToString();
634 CAppUtils::RunTortoiseGitProc(cmd);
637 break;
638 case ID_SAVEAS:
640 if (m_cFileList.GetSelectedCount() > 0)
642 CString temp;
643 CTGitPath savePath;
644 CString pathSave;
645 if (!CAppUtils::FileOpenSave(pathSave, NULL, IDS_REPOBROWSE_SAVEAS, IDS_COMMONFILEFILTER, false, m_hWnd))
647 break;
649 savePath = CTGitPath(pathSave);
651 // now open the selected file for writing
654 CStdioFile file(savePath.GetWinPathString(), CFile::typeBinary | CFile::modeReadWrite | CFile::modeCreate);
655 // temp.Format(IDS_FILEDIFF_CHANGEDLISTINTRO, (LPCTSTR)m_path1.GetGitPathString(), (LPCTSTR)m_rev1.ToString(), (LPCTSTR)m_path2.GetGitPathString(), (LPCTSTR)m_rev2.ToString());
656 file.WriteString(temp + _T("\n"));
657 POSITION pos = m_cFileList.GetFirstSelectedItemPosition();
658 while (pos)
660 int index = m_cFileList.GetNextSelectedItem(pos);
661 CTGitPath* fd = m_arFilteredList[index];
662 file.WriteString(fd->GetGitPathString());
663 file.WriteString(_T("\n"));
665 file.Close();
667 catch (CFileException* pE)
669 pE->ReportError();
673 break;
674 case ID_CLIPBOARD_PATH:
676 CopySelectionToClipboard();
678 break;
680 case ID_CLIPBOARD_ALL:
682 CopySelectionToClipboard(TRUE);
684 break;
685 case ID_EXPORT:
687 // export all changed files to a folder
688 CBrowseFolder browseFolder;
689 browseFolder.m_style = BIF_EDITBOX | BIF_NEWDIALOGSTYLE | BIF_RETURNFSANCESTORS | BIF_RETURNONLYFSDIRS;
690 if (browseFolder.Show(GetSafeHwnd(), m_strExportDir) == CBrowseFolder::OK)
692 POSITION pos = m_cFileList.GetFirstSelectedItemPosition();
693 while (pos)
695 int index = m_cFileList.GetNextSelectedItem(pos);
696 CTGitPath* fd = m_arFilteredList[index];
697 // we cannot export directories or folders
698 if (fd->m_Action == CTGitPath::LOGACTIONS_DELETED || fd->IsDirectory())
699 continue;
700 CAppUtils::CreateMultipleDirectory(m_strExportDir + _T("\\") + fd->GetDirectory().GetWinPathString());
701 CString filename = m_strExportDir + _T("\\") + fd->GetWinPathString();
702 if(m_rev1.m_CommitHash.ToString() == GIT_REV_ZERO)
704 if(!CopyFile(g_Git.m_CurrentDir + _T("\\") + fd->GetWinPath(), filename, false))
706 MessageBox(CFormatMessageWrapper(), _T("TortoiseGit"), MB_OK | MB_ICONERROR);
707 return;
710 else
712 if(g_Git.GetOneFile(m_rev1.m_CommitHash, *fd, filename))
714 CString out;
715 out.Format(IDS_STATUSLIST_CHECKOUTFILEFAILED, fd->GetGitPathString(), m_rev1.m_CommitHash.ToString(), filename);
716 if (CMessageBox::Show(NULL, out, _T("TortoiseGit"), 2, IDI_WARNING, CString(MAKEINTRESOURCE(IDS_IGNOREBUTTON)), CString(MAKEINTRESOURCE(IDS_ABORTBUTTON))) == 2)
717 return;
724 break;
730 BOOL CFileDiffDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
732 if (pWnd != &m_cFileList)
733 return CResizableStandAloneDialog::OnSetCursor(pWnd, nHitTest, message);
734 if (m_bThreadRunning == 0)
736 HCURSOR hCur = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
737 SetCursor(hCur);
738 return CResizableStandAloneDialog::OnSetCursor(pWnd, nHitTest, message);
740 HCURSOR hCur = LoadCursor(NULL, MAKEINTRESOURCE(IDC_WAIT));
741 SetCursor(hCur);
742 return TRUE;
745 void CFileDiffDlg::OnEnSetfocusFirsturl()
747 GetDlgItem(IDC_FIRSTURL)->HideCaret();
750 void CFileDiffDlg::OnEnSetfocusSecondurl()
752 GetDlgItem(IDC_SECONDURL)->HideCaret();
756 void CFileDiffDlg::OnBnClickedSwitchleftright()
759 if (m_bThreadRunning)
760 return;
762 #if 0
763 CString sFilterString;
764 m_cFilter.GetWindowText(sFilterString);
766 m_cFileList.SetRedraw(false);
767 m_cFileList.DeleteAllItems();
768 for (int i=0; i<(int)m_arFileList.GetCount(); ++i)
770 CTGitPath fd = m_arFileList[i];
771 if (fd.m_Action == CTGitPath::LOGACTIONS_ADDED)
772 fd.m_Action = CTGitPath::LOGACTIONS_DELETED;
773 else if (fd.m_Action == CTGitPath::LOGACTIONS_DELETED)
774 fd.m_Action = CTGitPath::LOGACTIONS_ADDED;
775 std::swap(fd.m_StatAdd, fd.m_StatDel);
776 (CTGitPath&)m_arFileList[i] = fd;
778 Filter(sFilterString);
779 #endif
781 m_cFileList.SetRedraw(true);
782 CTGitPath path = m_path1;
783 m_path1 = m_path2;
784 m_path2 = path;
785 GitRev rev = m_rev1;
786 m_rev1 = m_rev2;
787 m_rev2 = rev;
789 CString str1,str2;
790 this->m_ctrRev1Edit.GetWindowText(str1);
791 this->m_ctrRev2Edit.GetWindowText(str2);
793 this->m_ctrRev1Edit.SetWindowText(str2);
794 this->m_ctrRev2Edit.SetWindowText(str1);
796 SetURLLabels();
797 //KillTimer(IDT_INPUT);
800 void CFileDiffDlg::SetURLLabels(int mask)
803 // m_cRev1Btn.SetWindowText(m_rev1.m_CommitHash.ToString().Left(6));
804 // m_cRev2Btn.SetWindowText(m_rev2.m_CommitHash.ToString().Left(6));
806 if(mask &0x1)
808 SetDlgItemText(IDC_FIRSTURL, m_rev1.m_CommitHash.ToString().Left(8)+_T(": ")+m_rev1.GetSubject());
809 m_tooltips.AddTool(IDC_FIRSTURL,
810 CLoglistUtils::FormatDateAndTime(m_rev1.GetAuthorDate(), DATE_SHORTDATE, false) + _T(" ") + m_rev1.GetAuthorName());
814 if(mask &0x2)
816 SetDlgItemText(IDC_SECONDURL,m_rev2.m_CommitHash.ToString().Left(8)+_T(": ")+m_rev2.GetSubject());
818 m_tooltips.AddTool(IDC_SECONDURL,
819 CLoglistUtils::FormatDateAndTime(m_rev2.GetAuthorDate(), DATE_SHORTDATE, false) + _T(" ") + m_rev2.GetAuthorName());
822 this->GetDlgItem(IDC_REV2GROUP)->SetWindowText(CString(MAKEINTRESOURCE(IDS_PROC_FILEDIFF_VERSION2BASE)));
823 this->GetDlgItem(IDC_REV1GROUP)->SetWindowText(CString(MAKEINTRESOURCE(IDS_PROC_FILEDIFF_VERSION1)));
825 if( (mask&0x3) == 0x3)
826 if(m_rev2.GetCommitterDate() > m_rev1.GetCommitterDate())
828 this->GetDlgItem(IDC_REV2GROUP)->SetWindowText(CString(MAKEINTRESOURCE(IDS_PROC_FILEDIFF_VERSION2BASENEWER)));
830 else
832 this->GetDlgItem(IDC_REV1GROUP)->SetWindowText(CString(MAKEINTRESOURCE(IDS_PROC_FILEDIFF_VERSION1NEWER)));
836 void CFileDiffDlg::ClearURLabels(int mask)
838 if(mask&0x1)
840 SetDlgItemText(IDC_FIRSTURL, _T(""));
841 m_tooltips.AddTool(IDC_FIRSTURL, _T(""));
844 if(mask&0x2)
846 SetDlgItemText(IDC_SECONDURL, _T(""));
847 m_tooltips.AddTool(IDC_SECONDURL, _T(""));
850 BOOL CFileDiffDlg::PreTranslateMessage(MSG* pMsg)
852 m_tooltips.RelayEvent(pMsg);
853 if (pMsg->message == WM_KEYDOWN)
855 switch (pMsg->wParam)
857 case 'A':
859 if (GetAsyncKeyState(VK_CONTROL)&0x8000)
861 // select all entries
862 for (int i=0; i<m_cFileList.GetItemCount(); ++i)
864 m_cFileList.SetItemState(i, LVIS_SELECTED, LVIS_SELECTED);
866 return TRUE;
869 break;
870 case 'C':
871 case VK_INSERT:
873 if (GetAsyncKeyState(VK_CONTROL)&0x8000)
875 CopySelectionToClipboard();
876 return TRUE;
879 break;
880 case '\r':
882 if (GetFocus() == GetDlgItem(IDC_FILELIST))
884 // Return pressed in file list. Show diff, as for double click
885 int selIndex = m_cFileList.GetSelectionMark();
886 if ((selIndex >= 0) && (selIndex < (int)m_arFileList.GetCount()))
887 DoDiff(selIndex, m_bBlame);
888 return TRUE;
891 break;
892 case VK_F5:
894 OnTimer(IDT_INPUT);
896 break;
899 return __super::PreTranslateMessage(pMsg);
902 void CFileDiffDlg::OnCancel()
904 if (m_bThreadRunning)
906 m_bCancelled = true;
907 return;
909 __super::OnCancel();
912 void CFileDiffDlg::OnHdnItemclickFilelist(NMHDR *pNMHDR, LRESULT *pResult)
914 LPNMHEADER phdr = reinterpret_cast<LPNMHEADER>(pNMHDR);
915 if (m_bThreadRunning)
916 return;
918 if (m_nSortedColumn == phdr->iItem)
919 m_bAscending = !m_bAscending;
920 else
921 m_bAscending = TRUE;
922 m_nSortedColumn = phdr->iItem;
923 Sort();
925 CString temp;
926 m_cFileList.SetRedraw(FALSE);
927 m_cFileList.DeleteAllItems();
928 m_cFilter.GetWindowText(temp);
929 Filter(temp);
931 CHeaderCtrl * pHeader = m_cFileList.GetHeaderCtrl();
932 HDITEM HeaderItem = {0};
933 HeaderItem.mask = HDI_FORMAT;
934 for (int i=0; i<pHeader->GetItemCount(); ++i)
936 pHeader->GetItem(i, &HeaderItem);
937 HeaderItem.fmt &= ~(HDF_SORTDOWN | HDF_SORTUP);
938 pHeader->SetItem(i, &HeaderItem);
940 pHeader->GetItem(m_nSortedColumn, &HeaderItem);
941 HeaderItem.fmt |= (m_bAscending ? HDF_SORTUP : HDF_SORTDOWN);
942 pHeader->SetItem(m_nSortedColumn, &HeaderItem);
944 m_cFileList.SetRedraw(TRUE);
946 *pResult = 0;
949 void CFileDiffDlg::Sort()
951 if(m_arFileList.GetCount() < 2)
953 return;
956 std::sort(m_arFileList.m_paths.begin(), m_arFileList.m_paths.end(), &CFileDiffDlg::SortCompare);
959 bool CFileDiffDlg::SortCompare(const CTGitPath& Data1, const CTGitPath& Data2)
961 int result = 0;
962 int d1, d2;
963 switch (m_nSortedColumn)
965 case 0: //path column
966 result = Data1.GetWinPathString().Compare(Data2.GetWinPathString());
967 break;
968 case 1: //extension column
969 result = Data1.GetFileExtension().Compare(Data2.GetFileExtension());
970 break;
971 case 2: //action column
972 result = Data1.m_Action - Data2.m_Action;
973 break;
974 case 3:
975 d1 = CSorter::A2L(Data1.m_StatAdd);
976 d2 = CSorter::A2L(Data2.m_StatAdd);
977 result = d1 - d2;
978 break;
979 case 4:
980 d1 = CSorter::A2L(Data1.m_StatDel);;
981 d2 = CSorter::A2L(Data2.m_StatDel);
982 result = d1 - d2;
983 break;
984 default:
985 break;
987 // sort by path name as second priority
988 if (m_nSortedColumn != 0 && result == 0)
989 result = Data1.GetWinPathString().Compare(Data2.GetWinPathString());
991 if (!m_bAscending)
992 result = -result;
993 return result < 0;
997 void CFileDiffDlg::OnBnClickedRev1btn()
999 ClickRevButton(&this->m_cRev1Btn,&this->m_rev1, &this->m_ctrRev1Edit);
1002 void CFileDiffDlg::ClickRevButton(CMenuButton *button, GitRev *rev, CACEdit *edit)
1004 INT_PTR entry=button->GetCurrentEntry();
1005 if(entry == 0) /* Browse Refence*/
1008 CString str = CBrowseRefsDlg::PickRef();
1009 if(str.IsEmpty())
1010 return;
1012 if(FillRevFromString(rev,str))
1013 return;
1015 edit->SetWindowText(str);
1019 if(entry == 1) /*Log*/
1021 CLogDlg dlg;
1022 dlg.SetSelect(true);
1023 if(dlg.DoModal() == IDOK)
1025 if( dlg.GetSelectedHash().IsEmpty() )
1026 return;
1028 if(FillRevFromString(rev,dlg.GetSelectedHash()))
1029 return;
1031 edit->SetWindowText(dlg.GetSelectedHash());
1034 else
1035 return;
1038 if(entry == 2) /*RefLog*/
1040 CRefLogDlg dlg;
1041 if(dlg.DoModal() == IDOK)
1043 if(FillRevFromString(rev,dlg.m_SelectedHash))
1044 return;
1046 edit->SetWindowText(dlg.m_SelectedHash);
1049 else
1050 return;
1053 SetURLLabels();
1055 InterlockedExchange(&m_bThreadRunning, TRUE);
1056 if (AfxBeginThread(DiffThreadEntry, this)==NULL)
1058 InterlockedExchange(&m_bThreadRunning, FALSE);
1059 CMessageBox::Show(NULL, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
1061 KillTimer(IDT_INPUT);
1064 void CFileDiffDlg::OnBnClickedRev2btn()
1066 ClickRevButton(&this->m_cRev2Btn,&this->m_rev2, &this->m_ctrRev2Edit);
1069 LRESULT CFileDiffDlg::OnClickedCancelFilter(WPARAM /*wParam*/, LPARAM /*lParam*/)
1071 if (m_bThreadRunning)
1073 SetTimer(IDT_FILTER, 1000, NULL);
1074 return 0L;
1077 KillTimer(IDT_FILTER);
1079 m_cFileList.SetRedraw(FALSE);
1080 m_arFilteredList.clear();
1081 m_cFileList.DeleteAllItems();
1083 Filter(_T(""));
1085 m_cFileList.SetRedraw(TRUE);
1086 return 0L;
1089 void CFileDiffDlg::OnEnChangeFilter()
1091 SetTimer(IDT_FILTER, 1000, NULL);
1094 void CFileDiffDlg::OnTimer(UINT_PTR nIDEvent)
1096 if (m_bThreadRunning)
1097 return;
1099 if( nIDEvent == IDT_FILTER)
1101 CString sFilterText;
1102 KillTimer(IDT_FILTER);
1103 m_cFilter.GetWindowText(sFilterText);
1105 m_cFileList.SetRedraw(FALSE);
1106 m_cFileList.DeleteAllItems();
1108 Filter(sFilterText);
1110 m_cFileList.SetRedraw(TRUE);
1112 __super::OnTimer(nIDEvent);
1115 if( nIDEvent == IDT_INPUT)
1117 KillTimer(IDT_INPUT);
1118 TRACE(_T("Input Timer\r\n"));
1120 GitRev gitrev;
1121 CString str;
1122 int mask = 0;
1123 this->m_ctrRev1Edit.GetWindowText(str);
1126 if (!gitrev.GetCommit(str))
1128 m_rev1 = gitrev;
1129 mask |= 0x1;
1132 catch (const char *msg)
1134 CMessageBox::Show(m_hWnd, _T("Could not get commit ") + str + _T("\nlibgit reports:\n") + CString(msg), _T("TortoiseGit"), MB_ICONERROR);
1137 this->m_ctrRev2Edit.GetWindowText(str);
1141 if (!gitrev.GetCommit(str))
1143 m_rev2 = gitrev;
1144 mask |= 0x2;
1147 catch (const char *msg)
1149 CMessageBox::Show(m_hWnd, _T("Could not get commit ") + str + _T("\nlibgit reports:\n") + CString(msg), _T("TortoiseGit"), MB_ICONERROR);
1152 this->SetURLLabels(mask);
1154 if(mask == 0x3)
1157 InterlockedExchange(&m_bThreadRunning, TRUE);
1158 if (AfxBeginThread(DiffThreadEntry, this)==NULL)
1160 InterlockedExchange(&m_bThreadRunning, FALSE);
1161 CMessageBox::Show(NULL, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
1167 void CFileDiffDlg::Filter(CString sFilterText)
1169 sFilterText.MakeLower();
1171 m_arFilteredList.clear();
1173 for (int i=0;i<m_arFileList.GetCount();i++)
1175 CString sPath = m_arFileList[i].GetGitPathString();
1176 sPath.MakeLower();
1177 if (sPath.Find(sFilterText) >= 0)
1179 m_arFilteredList.push_back((CTGitPath*)&(m_arFileList[i]));
1182 for (std::vector<CTGitPath*>::const_iterator it = m_arFilteredList.begin(); it != m_arFilteredList.end(); ++it)
1184 AddEntry(*it);
1188 void CFileDiffDlg::CopySelectionToClipboard(BOOL isFull)
1190 // copy all selected paths to the clipboard
1191 POSITION pos = m_cFileList.GetFirstSelectedItemPosition();
1192 int index;
1193 CString sTextForClipboard;
1194 while ((index = m_cFileList.GetNextSelectedItem(pos)) >= 0)
1196 sTextForClipboard += m_cFileList.GetItemText(index, 0);
1197 sTextForClipboard += _T("\t");
1199 if(!isFull)
1201 sTextForClipboard += _T("\r\n");
1204 else
1206 sTextForClipboard += m_cFileList.GetItemText(index, 1);
1207 sTextForClipboard += _T("\t");
1208 sTextForClipboard += m_cFileList.GetItemText(index, 2);
1209 sTextForClipboard += _T("\t");
1210 sTextForClipboard += m_cFileList.GetItemText(index, 3);
1211 sTextForClipboard += _T("\t");
1212 sTextForClipboard += m_cFileList.GetItemText(index, 4);
1213 sTextForClipboard += _T("\r\n");
1216 CStringUtils::WriteAsciiStringToClipboard(sTextForClipboard);
1220 LRESULT CFileDiffDlg::OnRefLoad(WPARAM /*wParam*/, LPARAM /*lParam*/)
1222 for(int i=0;i<m_Reflist.size();i++)
1224 CString str=m_Reflist[i];
1226 if(str.Find(_T("remotes/")) == 0)
1227 str=str.Mid(8);
1229 m_ctrRev1Edit.AddSearchString(str);
1230 m_ctrRev2Edit.AddSearchString(str);
1232 return 0;
1235 BOOL CFileDiffDlg::DestroyWindow()
1237 return CResizableStandAloneDialog::DestroyWindow();
1240 LRESULT CFileDiffDlg::OnEnUpdate(WPARAM /*wParam*/, LPARAM lParam)
1242 if(lParam == IDC_REV1EDIT)
1244 OnTextUpdate(&this->m_ctrRev1Edit);
1245 ClearURLabels(1);
1247 if(lParam == IDC_REV2EDIT)
1249 OnTextUpdate(&this->m_ctrRev2Edit);
1250 ClearURLabels(1<<1);
1252 return 0;
1255 void CFileDiffDlg::OnTextUpdate(CACEdit * /*pEdit*/)
1257 SetTimer(IDT_INPUT, 1000, NULL);
1258 this->m_cFileList.ShowText(_T("Wait For input validate version"));
1261 int CFileDiffDlg::RevertSelectedItemToVersion(CString rev)
1263 if (rev.IsEmpty() || rev == GIT_REV_ZERO)
1264 return 0;
1266 POSITION pos = m_cFileList.GetFirstSelectedItemPosition();
1267 int index;
1268 int count = 0;
1269 while ((index = m_cFileList.GetNextSelectedItem(pos)) >= 0)
1271 CString cmd, out;
1272 CTGitPath *fentry = (CTGitPath *)m_arFilteredList[index];
1273 cmd.Format(_T("git.exe checkout %s -- \"%s\""), rev, fentry->GetGitPathString());
1274 if (g_Git.Run(cmd, &out, CP_UTF8))
1276 if (CMessageBox::Show(NULL, out, _T("TortoiseGit"), 2, IDI_WARNING, CString(MAKEINTRESOURCE(IDS_IGNOREBUTTON)), CString(MAKEINTRESOURCE(IDS_ABORTBUTTON))) == 2)
1277 break;
1279 else
1280 count++;
1283 CString out;
1284 out.Format(IDS_STATUSLIST_FILESREVERTED, count, rev);
1285 CMessageBox::Show(NULL, out, _T("TortoiseGit"), MB_OK);
1286 return 0;