1 // TortoiseGit - a Windows shell extension for easy version control
\r
3 // Copyright (C) 2003-2008 - TortoiseGit
\r
5 // This program is free software; you can redistribute it and/or
\r
6 // modify it under the terms of the GNU General Public License
\r
7 // as published by the Free Software Foundation; either version 2
\r
8 // of the License, or (at your option) any later version.
\r
10 // This program is distributed in the hope that it will be useful,
\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
13 // GNU General Public License for more details.
\r
15 // You should have received a copy of the GNU General Public License
\r
16 // along with this program; if not, write to the Free Software Foundation,
\r
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
\r
20 #include "TortoiseProc.h"
\r
21 #include "UnicodeUtils.h"
\r
22 #include "MessageBox.h"
\r
23 #include "AppUtils.h"
\r
24 #include "TempFile.h"
\r
25 #include "ProgressDlg.h"
\r
26 #include "SysImageList.h"
\r
27 //#include "GitProperties.h"
\r
28 #include "StringUtils.h"
\r
29 #include "PathUtils.h"
\r
30 #include "BrowseFolder.h"
\r
31 #include "RevisionDlg.h"
\r
32 #include ".\filediffdlg.h"
\r
33 #include "gitdiff.h"
\r
34 #include "CommonResource.h"
\r
35 #include "BrowseRefsDlg.h"
\r
37 #include "RefLogDlg.h"
\r
39 #define ID_COMPARE 1
\r
43 #define ID_CLIPBOARD 5
\r
45 BOOL CFileDiffDlg::m_bAscending = FALSE;
\r
46 int CFileDiffDlg::m_nSortedColumn = -1;
\r
49 IMPLEMENT_DYNAMIC(CFileDiffDlg, CResizableStandAloneDialog)
\r
50 CFileDiffDlg::CFileDiffDlg(CWnd* pParent /*=NULL*/)
\r
51 : CResizableStandAloneDialog(CFileDiffDlg::IDD, pParent),
\r
56 m_bLoadingRef=FALSE;
\r
59 CFileDiffDlg::~CFileDiffDlg()
\r
61 DestroyIcon(m_hSwitchIcon);
\r
64 void CFileDiffDlg::DoDataExchange(CDataExchange* pDX)
\r
66 CResizableStandAloneDialog::DoDataExchange(pDX);
\r
67 DDX_Control(pDX, IDC_FILELIST, m_cFileList);
\r
68 DDX_Control(pDX, IDC_SWITCHLEFTRIGHT, m_SwitchButton);
\r
69 DDX_Control(pDX, IDC_REV1BTN, m_cRev1Btn);
\r
70 DDX_Control(pDX, IDC_REV2BTN, m_cRev2Btn);
\r
71 DDX_Control(pDX, IDC_FILTER, m_cFilter);
\r
72 DDX_Control(pDX, IDC_REV1EDIT, m_ctrRev1Edit);
\r
73 DDX_Control(pDX, IDC_REV2EDIT, m_ctrRev2Edit);
\r
77 BEGIN_MESSAGE_MAP(CFileDiffDlg, CResizableStandAloneDialog)
\r
78 ON_NOTIFY(NM_DBLCLK, IDC_FILELIST, OnNMDblclkFilelist)
\r
79 ON_NOTIFY(LVN_GETINFOTIP, IDC_FILELIST, OnLvnGetInfoTipFilelist)
\r
80 ON_NOTIFY(NM_CUSTOMDRAW, IDC_FILELIST, OnNMCustomdrawFilelist)
\r
83 ON_EN_SETFOCUS(IDC_SECONDURL, &CFileDiffDlg::OnEnSetfocusSecondurl)
\r
84 ON_EN_SETFOCUS(IDC_FIRSTURL, &CFileDiffDlg::OnEnSetfocusFirsturl)
\r
85 ON_BN_CLICKED(IDC_SWITCHLEFTRIGHT, &CFileDiffDlg::OnBnClickedSwitchleftright)
\r
86 ON_NOTIFY(HDN_ITEMCLICK, 0, &CFileDiffDlg::OnHdnItemclickFilelist)
\r
87 ON_BN_CLICKED(IDC_REV1BTN, &CFileDiffDlg::OnBnClickedRev1btn)
\r
88 ON_BN_CLICKED(IDC_REV2BTN, &CFileDiffDlg::OnBnClickedRev2btn)
\r
89 ON_MESSAGE(WM_FILTEREDIT_CANCELCLICKED, OnClickedCancelFilter)
\r
90 ON_EN_CHANGE(IDC_FILTER, &CFileDiffDlg::OnEnChangeFilter)
\r
92 ON_MESSAGE(ENAC_UPDATE, &CFileDiffDlg::OnEnUpdate)
\r
93 ON_MESSAGE(MSG_REF_LOADED, OnRefLoad)
\r
97 void CFileDiffDlg::SetDiff(CTGitPath * path, GitRev rev1, GitRev rev2)
\r
108 void CFileDiffDlg::SetDiff(CTGitPath * path, CString &hash1, CString &hash2)
\r
116 BYTE_VECTOR logout;
\r
118 if(hash1 == GIT_REV_ZERO)
\r
120 m_rev1.m_CommitHash.Empty();
\r
121 m_rev1.m_Subject=_T("Working Copy");
\r
124 g_Git.GetLog(logout,hash1,path,1,0);
\r
125 m_rev1.ParserFromLog(logout);
\r
130 if(hash2 == GIT_REV_ZERO)
\r
132 m_rev2.m_CommitHash.Empty();
\r
133 m_rev2.m_Subject=_T("Working Copy");
\r
136 g_Git.GetLog(logout,hash2,path,1,0);
\r
137 m_rev2.ParserFromLog(logout);
\r
140 void CFileDiffDlg::SetDiff(CTGitPath * path, GitRev rev1)
\r
148 m_rev2.m_CommitHash.Empty();
\r
149 m_rev2.m_Subject = _T("Previou Version");
\r
151 //this->GetDlgItem()->EnableWindow(FALSE);
\r
156 BOOL CFileDiffDlg::OnInitDialog()
\r
158 CResizableStandAloneDialog::OnInitDialog();
\r
161 this->m_ctrRev1Edit.Init();
\r
162 this->m_ctrRev2Edit.Init();
\r
164 m_tooltips.Create(this);
\r
165 m_tooltips.AddTool(IDC_SWITCHLEFTRIGHT, IDS_FILEDIFF_SWITCHLEFTRIGHT_TT);
\r
167 m_cFileList.SetRedraw(false);
\r
168 m_cFileList.DeleteAllItems();
\r
169 DWORD exStyle = LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER | LVS_EX_INFOTIP;
\r
170 m_cFileList.SetExtendedStyle(exStyle);
\r
172 m_nIconFolder = SYS_IMAGE_LIST().GetDirIconIndex();
\r
173 m_cFileList.SetImageList(&SYS_IMAGE_LIST(), LVSIL_SMALL);
\r
175 m_hSwitchIcon = (HICON)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_SWITCHLEFTRIGHT), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
\r
176 m_SwitchButton.SetIcon(m_hSwitchIcon);
\r
178 m_cFilter.SetCancelBitmaps(IDI_CANCELNORMAL, IDI_CANCELPRESSED);
\r
179 m_cFilter.SetInfoIcon(IDI_FILTEREDIT);
\r
180 temp.LoadString(IDS_FILEDIFF_FILTERCUE);
\r
181 temp = _T(" ")+temp;
\r
182 m_cFilter.SetCueBanner(temp);
\r
184 int c = ((CHeaderCtrl*)(m_cFileList.GetDlgItem(0)))->GetItemCount()-1;
\r
186 m_cFileList.DeleteColumn(c--);
\r
189 temp.LoadString(IDS_FILEDIFF_FILE);
\r
190 m_cFileList.InsertColumn(0, temp);
\r
191 temp.LoadString(IDS_FILEDIFF_ACTION);
\r
192 m_cFileList.InsertColumn(1, temp);
\r
194 temp.LoadString(IDS_FILEDIFF_STATADD);
\r
195 m_cFileList.InsertColumn(2, temp);
\r
196 temp.LoadString(IDS_FILEDIFF_STATDEL);
\r
197 m_cFileList.InsertColumn(3, temp);
\r
200 int maxcol = ((CHeaderCtrl*)(m_cFileList.GetDlgItem(0)))->GetItemCount()-1;
\r
202 for (col = mincol; col <= maxcol; col++)
\r
204 m_cFileList.SetColumnWidth(col,LVSCW_AUTOSIZE_USEHEADER);
\r
207 m_cFileList.SetRedraw(true);
\r
209 AddAnchor(IDC_DIFFSTATIC1, TOP_LEFT, TOP_RIGHT);
\r
210 AddAnchor(IDC_SWITCHLEFTRIGHT, TOP_RIGHT);
\r
211 AddAnchor(IDC_FIRSTURL, TOP_LEFT, TOP_RIGHT);
\r
212 AddAnchor(IDC_REV1BTN, TOP_RIGHT);
\r
213 //AddAnchor(IDC_DIFFSTATIC2, TOP_LEFT, TOP_RIGHT);
\r
214 AddAnchor(IDC_SECONDURL, TOP_LEFT, TOP_RIGHT);
\r
215 AddAnchor(IDC_REV2BTN, TOP_RIGHT);
\r
216 AddAnchor(IDC_FILTER, TOP_LEFT, TOP_RIGHT);
\r
217 AddAnchor(IDC_FILELIST, TOP_LEFT, BOTTOM_RIGHT);
\r
218 AddAnchor(IDC_REV1GROUP,TOP_LEFT,TOP_RIGHT);
\r
219 AddAnchor(IDC_REV2GROUP,TOP_LEFT,TOP_RIGHT);
\r
220 AddAnchor(IDC_REV1EDIT,TOP_LEFT);
\r
221 AddAnchor(IDC_REV2EDIT,TOP_LEFT);
\r
223 EnableSaveRestore(_T("FileDiffDlg"));
\r
225 if(this->m_strRev1.IsEmpty())
\r
226 this->m_ctrRev1Edit.SetWindowText(this->m_rev1.m_CommitHash.ToString());
\r
229 if(m_rev1.GetCommit(this->m_strRev1))
\r
230 this->m_FileListText+=this->m_strRev1 + _T(" is wrong");
\r
232 this->m_ctrRev1Edit.SetWindowText(m_strRev1);
\r
235 if(this->m_strRev2.IsEmpty())
\r
236 this->m_ctrRev2Edit.SetWindowText(this->m_rev2.m_CommitHash.ToString());
\r
239 if(m_rev2.GetCommit(this->m_strRev2))
\r
240 this->m_FileListText+=this->m_strRev2 + _T(" is wrong");
\r
242 this->m_ctrRev2Edit.SetWindowText(m_strRev2);
\r
247 InterlockedExchange(&m_bThreadRunning, TRUE);
\r
248 if (AfxBeginThread(DiffThreadEntry, this)==NULL)
\r
250 InterlockedExchange(&m_bThreadRunning, FALSE);
\r
251 CMessageBox::Show(NULL, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
\r
254 InterlockedExchange(&m_bLoadingRef, TRUE);
\r
255 if (AfxBeginThread(LoadRefThreadEntry, this)==NULL)
\r
257 InterlockedExchange(&m_bLoadingRef, FALSE);
\r
258 CMessageBox::Show(NULL, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
\r
262 this->m_cRev1Btn.AddEntry(_T("RefBrowse"));
\r
263 this->m_cRev1Btn.AddEntry(_T("Log"));
\r
264 this->m_cRev1Btn.AddEntry(_T("RefLog"));
\r
266 this->m_cRev2Btn.AddEntry(_T("RefBrowse"));
\r
267 this->m_cRev2Btn.AddEntry(_T("Log"));
\r
268 this->m_cRev2Btn.AddEntry(_T("RefLog"));
\r
270 // Start with focus on file list
\r
271 GetDlgItem(IDC_FILELIST)->SetFocus();
\r
273 if(m_rev2.m_CommitHash.IsEmpty())
\r
274 m_SwitchButton.EnableWindow(FALSE);
\r
276 KillTimer(IDT_INPUT);
\r
281 svn_error_t* CFileDiffDlg::DiffSummarizeCallback(const CTGitPath& path,
\r
282 svn_client_diff_summarize_kind_t kind,
\r
283 bool propchanged, svn_node_kind_t node)
\r
289 fd.propchanged = propchanged;
\r
290 m_arFileList.push_back(fd);
\r
291 return Git_NO_ERROR;
\r
295 UINT CFileDiffDlg::DiffThreadEntry(LPVOID pVoid)
\r
297 return ((CFileDiffDlg*)pVoid)->DiffThread();
\r
300 UINT CFileDiffDlg::DiffThread()
\r
302 bool bSuccess = true;
\r
304 m_cFileList.ShowText(CString(MAKEINTRESOURCE(IDS_FILEDIFF_WAIT)));
\r
305 m_cFileList.DeleteAllItems();
\r
306 m_arFileList.Clear();
\r
307 EnableInputControl(false);
\r
311 // bSuccess = DiffSummarizePeg(m_path1, m_peg, m_rev1, m_rev2, m_depth, m_bIgnoreancestry);
\r
315 // bSuccess = DiffSummarize(m_path1, m_rev1, m_path2, m_rev2, m_depth, m_bIgnoreancestry);
\r
319 // m_cFileList.ShowText(GetLastErrorMessage());
\r
320 // InterlockedExchange(&m_bThreadRunning, FALSE);
\r
325 g_Git.GetCommitDiffList(m_rev1.m_CommitHash.ToString(),m_rev2.m_CommitHash.ToString(),m_arFileList);
\r
327 CString sFilterText;
\r
328 m_cFilter.GetWindowText(sFilterText);
\r
329 m_cFileList.SetRedraw(false);
\r
330 Filter(sFilterText);
\r
331 if (m_arFileList.GetCount()>0)
\r
333 // Highlight first entry in file list
\r
334 m_cFileList.SetSelectionMark(0);
\r
335 m_cFileList.SetItemState(0, LVIS_SELECTED, LVIS_SELECTED);
\r
339 int maxcol = ((CHeaderCtrl*)(m_cFileList.GetDlgItem(0)))->GetItemCount()-1;
\r
341 for (col = mincol; col <= maxcol; col++)
\r
343 m_cFileList.SetColumnWidth(col,LVSCW_AUTOSIZE_USEHEADER);
\r
346 m_cFileList.ClearText();
\r
347 m_cFileList.SetRedraw(true);
\r
349 InterlockedExchange(&m_bThreadRunning, FALSE);
\r
350 InvalidateRect(NULL);
\r
352 EnableInputControl(true);
\r
356 int CFileDiffDlg::AddEntry(const CTGitPath * fd)
\r
361 int index = m_cFileList.GetItemCount();
\r
364 // if (fd->node == svn_node_dir)
\r
365 // icon_idx = m_nIconFolder;
\r
368 icon_idx = SYS_IMAGE_LIST().GetPathIconIndex(fd->GetGitPathString());
\r
371 ret = m_cFileList.InsertItem(index, fd->GetGitPathString(), icon_idx);
\r
372 m_cFileList.SetItemText(index, 1, ((CTGitPath*)fd)->GetActionName());
\r
373 m_cFileList.SetItemText(index, 2, ((CTGitPath*)fd)->m_StatAdd);
\r
374 m_cFileList.SetItemText(index, 3, ((CTGitPath*)fd)->m_StatDel);
\r
379 void CFileDiffDlg::EnableInputControl(bool b)
\r
381 this->m_ctrRev1Edit.EnableWindow(b);
\r
382 this->m_ctrRev2Edit.EnableWindow(b);
\r
383 this->m_cRev1Btn.EnableWindow(b);
\r
384 this->m_cRev2Btn.EnableWindow(b);
\r
385 m_cFilter.EnableWindow(b);
\r
386 m_SwitchButton.EnableWindow(b);
\r
389 void CFileDiffDlg::DoDiff(int selIndex, bool blame)
\r
393 CTGitPath* fd = m_arFilteredList[selIndex];
\r
394 diff.Diff(fd, fd,this->m_rev1.m_CommitHash.ToString(), this->m_rev2.m_CommitHash.ToString(), blame, FALSE);
\r
397 CFileDiffDlg::CTGitPath* fd = m_arFilteredList[selIndex];
\r
399 CTGitPath url1 = CTGitPath(m_path1.GetGitPathString() + _T("/") + fd.path.GetGitPathString());
\r
400 CTGitPath url2 = m_bDoPegDiff ? url1 : CTGitPath(m_path2.GetGitPathString() + _T("/") + fd.path.GetGitPathString());
\r
402 if (fd.kind == svn_client_diff_summarize_kind_deleted)
\r
404 if (!PathIsURL(url1))
\r
405 url1 = CTGitPath(GetURLFromPath(m_path1) + _T("/") + fd.path.GetGitPathString());
\r
406 if (!PathIsURL(url2))
\r
407 url2 = m_bDoPegDiff ? url1 : CTGitPath(GetURLFromPath(m_path2) + _T("/") + fd.path.GetGitPathString());
\r
410 if (fd.propchanged)
\r
412 DiffProps(selIndex);
\r
414 if (fd.node == svn_node_dir)
\r
417 CTGitPath tempfile = CTempFiles::Instance().GetTempFilePath(false, m_path1, m_rev1);
\r
419 CProgressDlg progDlg;
\r
420 progDlg.SetTitle(IDS_PROGRESSWAIT);
\r
421 progDlg.SetAnimation(IDR_DOWNLOAD);
\r
422 progDlg.ShowModeless(this);
\r
423 progDlg.FormatPathLine(1, IDS_PROGRESSGETFILE, (LPCTSTR)m_path1.GetUIPathString());
\r
424 progDlg.FormatNonPathLine(2, IDS_PROGRESSREVISIONTEXT, (LPCTSTR)m_rev1.ToString());
\r
426 if ((fd.kind != svn_client_diff_summarize_kind_added)&&(!blame)&&(!Cat(url1, m_bDoPegDiff ? m_peg : m_rev1, m_rev1, tempfile)))
\r
428 if ((!m_bDoPegDiff)||(!Cat(url1, m_rev1, m_rev1, tempfile)))
\r
430 CMessageBox::Show(NULL, GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR);
\r
434 else if ((fd.kind != svn_client_diff_summarize_kind_added)&&(blame)&&(!m_blamer.BlameToFile(url1, 1, m_rev1, m_bDoPegDiff ? m_peg : m_rev1, tempfile, _T(""), TRUE, TRUE)))
\r
436 if ((!m_bDoPegDiff)||(!m_blamer.BlameToFile(url1, 1, m_rev1, m_rev1, tempfile, _T(""), TRUE, TRUE)))
\r
438 CMessageBox::Show(NULL, m_blamer.GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR);
\r
442 SetFileAttributes(tempfile.GetWinPath(), FILE_ATTRIBUTE_READONLY);
\r
443 progDlg.SetProgress(1, 2);
\r
444 progDlg.FormatPathLine(1, IDS_PROGRESSGETFILE, (LPCTSTR)url2.GetUIPathString());
\r
445 progDlg.FormatNonPathLine(2, IDS_PROGRESSREVISIONTEXT, (LPCTSTR)m_rev2.ToString());
\r
446 CTGitPath tempfile2 = CTempFiles::Instance().GetTempFilePath(false, url2, m_rev2);
\r
447 if ((fd.kind != svn_client_diff_summarize_kind_deleted)&&(!blame)&&(!Cat(url2, m_bDoPegDiff ? m_peg : m_rev2, m_rev2, tempfile2)))
\r
449 if ((!m_bDoPegDiff)||(!Cat(url2, m_rev2, m_rev2, tempfile2)))
\r
451 CMessageBox::Show(NULL, GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR);
\r
455 else if ((fd.kind != svn_client_diff_summarize_kind_deleted)&&(blame)&&(!m_blamer.BlameToFile(url2, 1, m_bDoPegDiff ? m_peg : m_rev2, m_rev2, tempfile2, _T(""), TRUE, TRUE)))
\r
457 if ((!m_bDoPegDiff)||(!m_blamer.BlameToFile(url2, 1, m_rev2, m_rev2, tempfile2, _T(""), TRUE, TRUE)))
\r
459 CMessageBox::Show(NULL, m_blamer.GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR);
\r
463 SetFileAttributes(tempfile2.GetWinPath(), FILE_ATTRIBUTE_READONLY);
\r
464 progDlg.SetProgress(2,2);
\r
467 CString rev1name, rev2name;
\r
470 rev1name.Format(_T("%s Revision %ld"), (LPCTSTR)fd.path.GetGitPathString(), (LONG)m_rev1);
\r
471 rev2name.Format(_T("%s Revision %ld"), (LPCTSTR)fd.path.GetGitPathString(), (LONG)m_rev2);
\r
475 rev1name = m_path1.GetGitPathString() + _T("/") + fd.path.GetGitPathString();
\r
476 rev2name = m_path2.GetGitPathString() + _T("/") + fd.path.GetGitPathString();
\r
478 CAppUtils::DiffFlags flags;
\r
479 flags.AlternativeTool(!!(GetAsyncKeyState(VK_SHIFT) & 0x8000));
\r
480 flags.Blame(blame);
\r
481 CAppUtils::StartExtDiff(
\r
482 tempfile, tempfile2, rev1name, rev2name, flags);
\r
487 void CFileDiffDlg::DiffProps(int selIndex)
\r
489 CFileDiffDlg::CTGitPath* fd = m_arFilteredList[selIndex];
\r
491 CTGitPath url1 = CTGitPath(m_path1.GetGitPathString() + _T("/") + fd.path.GetGitPathString());
\r
492 CTGitPath url2 = m_bDoPegDiff ? url1 : CTGitPath(m_path2.GetGitPathString() + _T("/") + fd.path.GetGitPathString());
\r
494 GitProperties propsurl1(url1, m_rev1, false);
\r
495 GitProperties propsurl2(url2, m_rev2, false);
\r
497 // collect the properties of both revisions in a set
\r
498 std::set<stdstring> properties;
\r
499 for (int wcindex = 0; wcindex < propsurl1.GetCount(); ++wcindex)
\r
501 stdstring urlname = propsurl1.GetItemName(wcindex);
\r
502 if ( properties.find(urlname) == properties.end() )
\r
504 properties.insert(urlname);
\r
507 for (int wcindex = 0; wcindex < propsurl2.GetCount(); ++wcindex)
\r
509 stdstring urlname = propsurl2.GetItemName(wcindex);
\r
510 if ( properties.find(urlname) == properties.end() )
\r
512 properties.insert(urlname);
\r
516 // iterate over all properties and diff the properties
\r
517 for (std::set<stdstring>::iterator iter = properties.begin(), end = properties.end(); iter != end; ++iter)
\r
519 stdstring url1name = *iter;
\r
521 stdstring url1value = _T(""); // CUnicodeUtils::StdGetUnicode((char *)propsurl1.GetItemValue(wcindex).c_str());
\r
522 for (int url1index = 0; url1index < propsurl1.GetCount(); ++url1index)
\r
524 if (propsurl1.GetItemName(url1index).compare(url1name)==0)
\r
526 url1value = CString((char *)propsurl1.GetItemValue(url1index).c_str());
\r
530 stdstring url2value = _T("");
\r
531 for (int url2index = 0; url2index < propsurl2.GetCount(); ++url2index)
\r
533 if (propsurl2.GetItemName(url2index).compare(url1name)==0)
\r
535 url2value = CString((char *)propsurl2.GetItemValue(url2index).c_str());
\r
539 if (url2value.compare(url1value)!=0)
\r
541 // write both property values to temporary files
\r
542 CTGitPath url1propfile = CTempFiles::Instance().GetTempFilePath(false);
\r
543 CTGitPath url2propfile = CTempFiles::Instance().GetTempFilePath(false);
\r
545 _tfopen_s(&pFile, url1propfile.GetWinPath(), _T("wb"));
\r
548 fputs(CUnicodeUtils::StdGetUTF8(url1value).c_str(), pFile);
\r
551 _tfopen_s(&pFile, url2propfile.GetWinPath(), _T("wb"));
\r
554 fputs(CUnicodeUtils::StdGetUTF8(url2value).c_str(), pFile);
\r
562 SetFileAttributes(url1propfile.GetWinPath(), FILE_ATTRIBUTE_READONLY);
\r
563 SetFileAttributes(url2propfile.GetWinPath(), FILE_ATTRIBUTE_READONLY);
\r
565 if (m_rev1.IsWorking())
\r
566 n1.Format(IDS_DIFF_WCNAME, url1name.c_str());
\r
567 if (m_rev1.IsBase())
\r
568 n1.Format(IDS_DIFF_BASENAME, url1name.c_str());
\r
569 if (m_rev1.IsHead() || m_rev1.IsNumber())
\r
573 n1.Format(_T("%s : %s Revision %ld"), url1name.c_str(), (LPCTSTR)fd.path.GetGitPathString(), (LONG)m_rev1);
\r
577 CString sTemp = url1name.c_str();
\r
578 sTemp += _T(" : ");
\r
579 n1 = sTemp + m_path1.GetGitPathString() + _T("/") + fd.path.GetGitPathString();
\r
582 if (m_rev2.IsWorking())
\r
583 n2.Format(IDS_DIFF_WCNAME, url1name.c_str());
\r
584 if (m_rev2.IsBase())
\r
585 n2.Format(IDS_DIFF_BASENAME, url1name.c_str());
\r
586 if (m_rev2.IsHead() || m_rev2.IsNumber())
\r
590 n2.Format(_T("%s : %s Revision %ld"), url1name.c_str(), (LPCTSTR)fd.path.GetGitPathString(), (LONG)m_rev2);
\r
594 CString sTemp = url1name.c_str();
\r
595 sTemp += _T(" : ");
\r
596 n2 = sTemp + m_path2.GetGitPathString() + _T("/") + fd.path.GetGitPathString();
\r
599 CAppUtils::StartExtDiffProps(url1propfile, url2propfile, n1, n2, TRUE);
\r
604 void CFileDiffDlg::OnNMDblclkFilelist(NMHDR *pNMHDR, LRESULT *pResult)
\r
607 LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
\r
608 int selIndex = pNMLV->iItem;
\r
611 if (selIndex >= (int)m_arFilteredList.size())
\r
614 DoDiff(selIndex, m_bBlame);
\r
617 void CFileDiffDlg::OnLvnGetInfoTipFilelist(NMHDR *pNMHDR, LRESULT *pResult)
\r
620 LPNMLVGETINFOTIP pGetInfoTip = reinterpret_cast<LPNMLVGETINFOTIP>(pNMHDR);
\r
621 if (pGetInfoTip->iItem >= (int)m_arFilteredList.size())
\r
624 CString path = m_path1.GetGitPathString() + _T("/") + m_arFilteredList[pGetInfoTip->iItem]->GetGitPathString();
\r
625 if (pGetInfoTip->cchTextMax > path.GetLength())
\r
626 _tcsncpy_s(pGetInfoTip->pszText, pGetInfoTip->cchTextMax, path, pGetInfoTip->cchTextMax);
\r
631 void CFileDiffDlg::OnNMCustomdrawFilelist(NMHDR *pNMHDR, LRESULT *pResult)
\r
633 NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>( pNMHDR );
\r
634 // Take the default processing unless we set this to something else below.
\r
635 *pResult = CDRF_DODEFAULT;
\r
637 // First thing - check the draw stage. If it's the control's prepaint
\r
638 // stage, then tell Windows we want messages for every item.
\r
640 if ( CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage )
\r
642 *pResult = CDRF_NOTIFYITEMDRAW;
\r
644 else if ( CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage )
\r
646 // This is the prepaint stage for an item. Here's where we set the
\r
647 // item's text color. Our return value will tell Windows to draw the
\r
648 // item itself, but it will use the new color we set here.
\r
650 // Tell Windows to paint the control itself.
\r
651 *pResult = CDRF_DODEFAULT;
\r
653 COLORREF crText = GetSysColor(COLOR_WINDOWTEXT);
\r
655 if (m_arFilteredList.size() > pLVCD->nmcd.dwItemSpec)
\r
657 CTGitPath * fd = m_arFilteredList[pLVCD->nmcd.dwItemSpec];
\r
658 switch (fd->m_Action)
\r
660 case CTGitPath::LOGACTIONS_ADDED:
\r
661 crText = m_colors.GetColor(CColors::Added);
\r
663 case CTGitPath::LOGACTIONS_DELETED:
\r
664 crText = m_colors.GetColor(CColors::Deleted);
\r
666 case CTGitPath::LOGACTIONS_MODIFIED:
\r
667 crText = m_colors.GetColor(CColors::Modified);
\r
669 //case svn_client_diff_summarize_kind_normal:
\r
671 //if (fd.propchanged)
\r
672 crText = m_colors.GetColor(CColors::PropertyChanged);
\r
676 // Store the color back in the NMLVCUSTOMDRAW struct.
\r
677 pLVCD->clrText = crText;
\r
681 UINT CFileDiffDlg::LoadRefThread()
\r
683 g_Git.GetBranchList(m_Reflist,NULL,CGit::BRANCH_ALL);
\r
684 g_Git.GetTagList(m_Reflist);
\r
686 this->PostMessage(MSG_REF_LOADED);
\r
687 InterlockedExchange(&m_bLoadingRef, FALSE);
\r
691 void CFileDiffDlg::OnContextMenu(CWnd* pWnd, CPoint point)
\r
693 if ((pWnd==0)||(pWnd != &m_cFileList))
\r
695 if (m_cFileList.GetSelectedCount() == 0)
\r
697 // if the context menu is invoked through the keyboard, we have to use
\r
698 // a calculated position on where to anchor the menu on
\r
699 if ((point.x == -1) && (point.y == -1))
\r
702 m_cFileList.GetItemRect(m_cFileList.GetSelectionMark(), &rect, LVIR_LABEL);
\r
703 m_cFileList.ClientToScreen(&rect);
\r
704 point = rect.CenterPoint();
\r
707 if (popup.CreatePopupMenu())
\r
710 temp.LoadString(IDS_LOG_POPUP_COMPARETWO);
\r
711 popup.AppendMenu(MF_STRING | MF_ENABLED, ID_COMPARE, temp);
\r
712 temp.LoadString(IDS_FILEDIFF_POPBLAME);
\r
713 //popup.AppendMenu(MF_STRING | MF_ENABLED, ID_BLAME, temp);
\r
714 popup.AppendMenu(MF_SEPARATOR, NULL);
\r
715 temp.LoadString(IDS_FILEDIFF_POPSAVELIST);
\r
716 popup.AppendMenu(MF_STRING | MF_ENABLED, ID_SAVEAS, temp);
\r
717 temp.LoadString(IDS_FILEDIFF_POPCLIPBOARD);
\r
718 popup.AppendMenu(MF_STRING | MF_ENABLED, ID_CLIPBOARD, temp);
\r
719 temp.LoadString(IDS_FILEDIFF_POPEXPORT);
\r
720 //popup.AppendMenu(MF_STRING | MF_ENABLED, ID_EXPORT, temp);
\r
721 int cmd = popup.TrackPopupMenu(TPM_RETURNCMD | TPM_LEFTALIGN | TPM_NONOTIFY, point.x, point.y, this, 0);
\r
722 m_bCancelled = false;
\r
727 POSITION pos = m_cFileList.GetFirstSelectedItemPosition();
\r
730 int index = m_cFileList.GetNextSelectedItem(pos);
\r
731 DoDiff(index, false);
\r
737 POSITION pos = m_cFileList.GetFirstSelectedItemPosition();
\r
740 int index = m_cFileList.GetNextSelectedItem(pos);
\r
741 DoDiff(index, true);
\r
747 if (m_cFileList.GetSelectedCount() > 0)
\r
750 CTGitPath savePath;
\r
752 if (!CAppUtils::FileOpenSave(pathSave, NULL, IDS_REPOBROWSE_SAVEAS, IDS_COMMONFILEFILTER, false, m_hWnd))
\r
756 savePath = CTGitPath(pathSave);
\r
758 // now open the selected file for writing
\r
761 CStdioFile file(savePath.GetWinPathString(), CFile::typeBinary | CFile::modeReadWrite | CFile::modeCreate);
\r
762 // temp.Format(IDS_FILEDIFF_CHANGEDLISTINTRO, (LPCTSTR)m_path1.GetGitPathString(), (LPCTSTR)m_rev1.ToString(), (LPCTSTR)m_path2.GetGitPathString(), (LPCTSTR)m_rev2.ToString());
\r
763 file.WriteString(temp + _T("\n"));
\r
764 POSITION pos = m_cFileList.GetFirstSelectedItemPosition();
\r
767 int index = m_cFileList.GetNextSelectedItem(pos);
\r
768 CTGitPath* fd = m_arFilteredList[index];
\r
769 file.WriteString(fd->GetGitPathString());
\r
770 file.WriteString(_T("\n"));
\r
774 catch (CFileException* pE)
\r
783 CopySelectionToClipboard();
\r
788 #if 0 //this funcation seem no useful
\r
789 // export all changed files to a folder
\r
790 CBrowseFolder browseFolder;
\r
791 browseFolder.m_style = BIF_EDITBOX | BIF_NEWDIALOGSTYLE | BIF_RETURNFSANCESTORS | BIF_RETURNONLYFSDIRS;
\r
792 if (browseFolder.Show(GetSafeHwnd(), m_strExportDir) == CBrowseFolder::OK)
\r
794 m_arSelectedFileList.RemoveAll();
\r
795 POSITION pos = m_cFileList.GetFirstSelectedItemPosition();
\r
798 int index = m_cFileList.GetNextSelectedItem(pos);
\r
799 CTGitPath* fd = m_arFilteredList[index];
\r
800 m_arSelectedFileList.Add(fd);
\r
802 m_pProgDlg = new CProgressDlg();
\r
803 InterlockedExchange(&m_bThreadRunning, TRUE);
\r
804 if (AfxBeginThread(ExportThreadEntry, this)==NULL)
\r
806 InterlockedExchange(&m_bThreadRunning, FALSE);
\r
807 CMessageBox::Show(NULL, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
\r
819 UINT CFileDiffDlg::ExportThreadEntry(LPVOID pVoid)
\r
821 return ((CFileDiffDlg*)pVoid)->ExportThread();
\r
824 UINT CFileDiffDlg::ExportThread()
\r
828 // if (m_pProgDlg == NULL)
\r
831 // SetAndClearProgressInfo(m_pProgDlg, false);
\r
832 m_pProgDlg->SetTitle(IDS_PROGRESSWAIT);
\r
833 m_pProgDlg->SetAnimation(AfxGetResourceHandle(), IDR_DOWNLOAD);
\r
834 m_pProgDlg->ShowModeless(this);
\r
835 for (INT_PTR i=0; (i<m_arSelectedFileList.GetCount())&&(!m_pProgDlg->HasUserCancelled()); ++i)
\r
837 CTGitPath* fd = m_arSelectedFileList[i];
\r
838 // CTGitPath url1 = CTGitPath(m_path1.GetGitPathString() + _T("/") + fd.path.GetGitPathString());
\r
839 // CTGitPath url2 = m_bDoPegDiff ? url1 : CTGitPath(m_path2.GetGitPathString() + _T("/") + fd.path.GetGitPathString());
\r
840 // if ((fd.node == svn_node_dir)&&(fd.kind != svn_client_diff_summarize_kind_added))
\r
842 // just create the directory
\r
843 // CreateDirectoryEx(NULL, m_strExportDir+_T("\\")+CPathUtils::PathUnescape(fd.path.GetWinPathString()), NULL);
\r
848 m_pProgDlg->FormatPathLine(1, IDS_PROGRESSGETFILE, (LPCTSTR)url1.GetGitPathString());
\r
850 CTGitPath savepath = CTGitPath(m_strExportDir);
\r
851 savepath.AppendPathString(_T("\\") + CPathUtils::PathUnescape(fd.path.GetWinPathString()));
\r
852 CPathUtils::MakeSureDirectoryPathExists(fd.node == svn_node_file ? savepath.GetContainingDirectory().GetWinPath() : savepath.GetDirectory().GetWinPath());
\r
853 if (fd.node == svn_node_dir)
\r
855 // exporting a folder requires calling Git::Export() so we also export all
\r
856 // children of that added folder.
\r
857 if ((fd.kind == svn_client_diff_summarize_kind_added)&&(!Export(url2, savepath, m_bDoPegDiff ? m_peg : m_rev2, m_rev2, true, true)))
\r
859 if ((!m_bDoPegDiff)||(!Export(url2, savepath, m_rev2, m_rev2, true, true)))
\r
863 CMessageBox::Show(NULL, GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR);
\r
864 InterlockedExchange(&m_bThreadRunning, FALSE);
\r
872 // exporting a file requires calling Git::Cat(), since Git::Export() only works
\r
874 if ((fd.kind != svn_client_diff_summarize_kind_deleted)&&(!Cat(url2, m_bDoPegDiff ? m_peg : m_rev2, m_rev2, savepath)))
\r
876 if ((!m_bDoPegDiff)||(!Cat(url2, m_rev2, m_rev2, savepath)))
\r
880 CMessageBox::Show(NULL, GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR);
\r
881 InterlockedExchange(&m_bThreadRunning, FALSE);
\r
888 m_pProgDlg->SetProgress (count, static_cast<DWORD>(m_arSelectedFileList.GetCount()));
\r
890 m_pProgDlg->Stop();
\r
891 SetAndClearProgressInfo(NULL, false);
\r
894 InterlockedExchange(&m_bThreadRunning, FALSE);
\r
900 BOOL CFileDiffDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
\r
902 if (pWnd != &m_cFileList)
\r
903 return CResizableStandAloneDialog::OnSetCursor(pWnd, nHitTest, message);
\r
904 if (m_bThreadRunning == 0)
\r
906 HCURSOR hCur = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
\r
908 return CResizableStandAloneDialog::OnSetCursor(pWnd, nHitTest, message);
\r
910 HCURSOR hCur = LoadCursor(NULL, MAKEINTRESOURCE(IDC_WAIT));
\r
915 void CFileDiffDlg::OnEnSetfocusFirsturl()
\r
917 GetDlgItem(IDC_FIRSTURL)->HideCaret();
\r
920 void CFileDiffDlg::OnEnSetfocusSecondurl()
\r
922 GetDlgItem(IDC_SECONDURL)->HideCaret();
\r
926 void CFileDiffDlg::OnBnClickedSwitchleftright()
\r
929 if (m_bThreadRunning)
\r
931 CString sFilterString;
\r
932 m_cFilter.GetWindowText(sFilterString);
\r
934 m_cFileList.SetRedraw(false);
\r
935 m_cFileList.DeleteAllItems();
\r
936 for (int i=0; i<(int)m_arFileList.GetCount(); ++i)
\r
938 CTGitPath fd = m_arFileList[i];
\r
939 if (fd.m_Action == CTGitPath::LOGACTIONS_ADDED)
\r
940 fd.m_Action = CTGitPath::LOGACTIONS_DELETED;
\r
941 else if (fd.m_Action == CTGitPath::LOGACTIONS_DELETED)
\r
942 fd.m_Action = CTGitPath::LOGACTIONS_ADDED;
\r
943 std::swap(fd.m_StatAdd, fd.m_StatDel);
\r
944 (CTGitPath&)m_arFileList[i] = fd;
\r
946 Filter(sFilterString);
\r
948 m_cFileList.SetRedraw(true);
\r
949 CTGitPath path = m_path1;
\r
952 GitRev rev = m_rev1;
\r
957 this->m_ctrRev1Edit.GetWindowText(str1);
\r
958 this->m_ctrRev2Edit.GetWindowText(str2);
\r
960 this->m_ctrRev1Edit.SetWindowText(str2);
\r
961 this->m_ctrRev2Edit.SetWindowText(str1);
\r
967 void CFileDiffDlg::SetURLLabels(int mask)
\r
970 // m_cRev1Btn.SetWindowText(m_rev1.m_CommitHash.ToString().Left(6));
\r
971 // m_cRev2Btn.SetWindowText(m_rev2.m_CommitHash.ToString().Left(6));
\r
975 SetDlgItemText(IDC_FIRSTURL, m_rev1.m_CommitHash.ToString().Left(8)+_T(": ")+m_rev1.m_Subject);
\r
976 m_tooltips.AddTool(IDC_FIRSTURL,
\r
977 CAppUtils::FormatDateAndTime( m_rev1.m_AuthorDate, DATE_SHORTDATE, false )+_T(" ")+m_rev1.m_AuthorName);
\r
983 SetDlgItemText(IDC_SECONDURL,m_rev2.m_CommitHash.ToString().Left(8)+_T(": ")+m_rev2.m_Subject);
\r
985 m_tooltips.AddTool(IDC_SECONDURL,
\r
986 CAppUtils::FormatDateAndTime( m_rev2.m_AuthorDate, DATE_SHORTDATE, false )+_T(" ")+m_rev2.m_AuthorName);
\r
991 void CFileDiffDlg::ClearURLabels(int mask)
\r
995 SetDlgItemText(IDC_FIRSTURL, _T(""));
\r
996 m_tooltips.AddTool(IDC_FIRSTURL, _T(""));
\r
1001 SetDlgItemText(IDC_SECONDURL, _T(""));
\r
1002 m_tooltips.AddTool(IDC_SECONDURL, _T(""));
\r
1005 BOOL CFileDiffDlg::PreTranslateMessage(MSG* pMsg)
\r
1007 m_tooltips.RelayEvent(pMsg);
\r
1008 if (pMsg->message == WM_KEYDOWN)
\r
1010 switch (pMsg->wParam)
\r
1014 if (GetAsyncKeyState(VK_CONTROL)&0x8000)
\r
1016 // select all entries
\r
1017 for (int i=0; i<m_cFileList.GetItemCount(); ++i)
\r
1019 m_cFileList.SetItemState(i, LVIS_SELECTED, LVIS_SELECTED);
\r
1028 if (GetAsyncKeyState(VK_CONTROL)&0x8000)
\r
1030 CopySelectionToClipboard();
\r
1037 if (GetFocus() == GetDlgItem(IDC_FILELIST))
\r
1039 // Return pressed in file list. Show diff, as for double click
\r
1040 int selIndex = m_cFileList.GetSelectionMark();
\r
1041 if ((selIndex >= 0) && (selIndex < (int)m_arFileList.GetCount()))
\r
1042 DoDiff(selIndex, m_bBlame);
\r
1049 return __super::PreTranslateMessage(pMsg);
\r
1052 void CFileDiffDlg::OnCancel()
\r
1054 if (m_bThreadRunning)
\r
1056 m_bCancelled = true;
\r
1059 __super::OnCancel();
\r
1062 void CFileDiffDlg::OnHdnItemclickFilelist(NMHDR *pNMHDR, LRESULT *pResult)
\r
1064 LPNMHEADER phdr = reinterpret_cast<LPNMHEADER>(pNMHDR);
\r
1065 if (m_bThreadRunning)
\r
1068 if (m_nSortedColumn == phdr->iItem)
\r
1069 m_bAscending = !m_bAscending;
\r
1071 m_bAscending = TRUE;
\r
1072 m_nSortedColumn = phdr->iItem;
\r
1073 m_arSelectedFileList.RemoveAll();
\r
1077 m_cFileList.SetRedraw(FALSE);
\r
1078 m_cFileList.DeleteAllItems();
\r
1079 m_cFilter.GetWindowText(temp);
\r
1082 CHeaderCtrl * pHeader = m_cFileList.GetHeaderCtrl();
\r
1083 HDITEM HeaderItem = {0};
\r
1084 HeaderItem.mask = HDI_FORMAT;
\r
1085 for (int i=0; i<pHeader->GetItemCount(); ++i)
\r
1087 pHeader->GetItem(i, &HeaderItem);
\r
1088 HeaderItem.fmt &= ~(HDF_SORTDOWN | HDF_SORTUP);
\r
1089 pHeader->SetItem(i, &HeaderItem);
\r
1091 pHeader->GetItem(m_nSortedColumn, &HeaderItem);
\r
1092 HeaderItem.fmt |= (m_bAscending ? HDF_SORTUP : HDF_SORTDOWN);
\r
1093 pHeader->SetItem(m_nSortedColumn, &HeaderItem);
\r
1095 m_cFileList.SetRedraw(TRUE);
\r
1100 void CFileDiffDlg::Sort()
\r
1102 if(m_arFileList.GetCount() < 2)
\r
1107 // std::sort(m_arFileList.begin(), m_arFileList.end(), &CFileDiffDlg::SortCompare);
\r
1110 bool CFileDiffDlg::SortCompare(const CTGitPath*& Data1, const CTGitPath*& Data2)
\r
1113 switch (m_nSortedColumn)
\r
1115 case 0: //path column
\r
1116 result = Data1.path.GetWinPathString().Compare(Data2.path.GetWinPathString());
\r
1118 case 1: //action column
\r
1119 result = Data1.kind - Data2.kind;
\r
1125 if (!m_bAscending)
\r
1127 return result < 0;
\r
1131 void CFileDiffDlg::OnBnClickedRev1btn()
\r
1134 ClickRevButton(&this->m_cRev1Btn,&this->m_rev1, &this->m_ctrRev1Edit);
\r
1139 void CFileDiffDlg::ClickRevButton(CMenuButton *button, GitRev *rev, CACEdit *edit)
\r
1141 int entry=button->GetCurrentEntry();
\r
1142 if(entry == 0) /* Browse Refence*/
\r
1145 CString str = CBrowseRefsDlg::PickRef();
\r
1149 if(FillRevFromString(rev,str))
\r
1152 edit->SetWindowText(str);
\r
1156 if(entry == 1) /*Log*/
\r
1159 dlg.SetSelect(true);
\r
1160 if(dlg.DoModal() == IDOK)
\r
1162 if( dlg.GetSelectedHash().IsEmpty() )
\r
1165 if(FillRevFromString(rev,dlg.GetSelectedHash()))
\r
1168 edit->SetWindowText(dlg.GetSelectedHash());
\r
1174 if(entry == 2) /*RefLog*/
\r
1177 if(dlg.DoModal() == IDOK)
\r
1179 if(FillRevFromString(rev,dlg.m_SelectedHash))
\r
1182 edit->SetWindowText(dlg.m_SelectedHash);
\r
1191 InterlockedExchange(&m_bThreadRunning, TRUE);
\r
1192 if (AfxBeginThread(DiffThreadEntry, this)==NULL)
\r
1194 InterlockedExchange(&m_bThreadRunning, FALSE);
\r
1195 CMessageBox::Show(NULL, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
\r
1197 KillTimer(IDT_INPUT);
\r
1200 void CFileDiffDlg::OnBnClickedRev2btn()
\r
1202 ClickRevButton(&this->m_cRev2Btn,&this->m_rev2, &this->m_ctrRev2Edit);
\r
1204 if (m_bThreadRunning)
\r
1205 return; // do nothing as long as the thread is still running
\r
1207 // show a dialog where the user can enter a revision
\r
1208 CRevisionDlg dlg(this);
\r
1209 dlg.AllowWCRevs(false);
\r
1210 *((GitRev*)&dlg) = m_rev2;
\r
1212 if (dlg.DoModal() == IDOK)
\r
1215 m_cRev2Btn.SetWindowText(m_rev2.ToString());
\r
1216 m_cFileList.DeleteAllItems();
\r
1217 // start a new thread to re-fetch the diff
\r
1218 InterlockedExchange(&m_bThreadRunning, TRUE);
\r
1219 if (AfxBeginThread(DiffThreadEntry, this)==NULL)
\r
1221 InterlockedExchange(&m_bThreadRunning, FALSE);
\r
1222 CMessageBox::Show(NULL, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
\r
1228 LRESULT CFileDiffDlg::OnClickedCancelFilter(WPARAM /*wParam*/, LPARAM /*lParam*/)
\r
1230 if (m_bThreadRunning)
\r
1232 SetTimer(IDT_FILTER, 1000, NULL);
\r
1236 KillTimer(IDT_FILTER);
\r
1238 m_cFileList.SetRedraw(FALSE);
\r
1239 m_arFilteredList.clear();
\r
1240 m_cFileList.DeleteAllItems();
\r
1244 m_cFileList.SetRedraw(TRUE);
\r
1248 void CFileDiffDlg::OnEnChangeFilter()
\r
1250 SetTimer(IDT_FILTER, 1000, NULL);
\r
1253 void CFileDiffDlg::OnTimer(UINT_PTR nIDEvent)
\r
1255 if (m_bThreadRunning)
\r
1258 if( nIDEvent == IDT_FILTER)
\r
1261 CString sFilterText;
\r
1262 KillTimer(IDT_FILTER);
\r
1263 m_cFilter.GetWindowText(sFilterText);
\r
1265 m_cFileList.SetRedraw(FALSE);
\r
1266 m_cFileList.DeleteAllItems();
\r
1268 Filter(sFilterText);
\r
1270 m_cFileList.SetRedraw(TRUE);
\r
1272 __super::OnTimer(nIDEvent);
\r
1275 if( nIDEvent == IDT_INPUT)
\r
1277 KillTimer(IDT_INPUT);
\r
1278 TRACE(_T("Input Timer\r\n"));
\r
1283 this->m_ctrRev1Edit.GetWindowText(str);
\r
1284 if( !gitrev.GetCommit(str) )
\r
1286 this->m_rev1=gitrev;
\r
1288 this->SetURLLabels(0x1);
\r
1291 this->m_ctrRev2Edit.GetWindowText(str);
\r
1293 if( !gitrev.GetCommit(str) )
\r
1295 this->m_rev2=gitrev;
\r
1297 this->SetURLLabels(0x2);
\r
1302 InterlockedExchange(&m_bThreadRunning, TRUE);
\r
1303 if (AfxBeginThread(DiffThreadEntry, this)==NULL)
\r
1305 InterlockedExchange(&m_bThreadRunning, FALSE);
\r
1306 CMessageBox::Show(NULL, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
\r
1312 void CFileDiffDlg::Filter(CString sFilterText)
\r
1315 sFilterText.MakeLower();
\r
1317 m_arFilteredList.clear();
\r
1319 for (int i=0;i<m_arFileList.GetCount();i++)
\r
1321 CString sPath = m_arFileList[i].GetGitPathString();
\r
1322 sPath.MakeLower();
\r
1323 if (sPath.Find(sFilterText) >= 0)
\r
1325 m_arFilteredList.push_back((CTGitPath*)&(m_arFileList[i]));
\r
1328 for (std::vector<CTGitPath*>::const_iterator it = m_arFilteredList.begin(); it != m_arFilteredList.end(); ++it)
\r
1335 void CFileDiffDlg::CopySelectionToClipboard()
\r
1337 // copy all selected paths to the clipboard
\r
1338 POSITION pos = m_cFileList.GetFirstSelectedItemPosition();
\r
1340 CString sTextForClipboard;
\r
1341 while ((index = m_cFileList.GetNextSelectedItem(pos)) >= 0)
\r
1343 sTextForClipboard += m_cFileList.GetItemText(index, 0);
\r
1344 sTextForClipboard += _T("\t");
\r
1345 sTextForClipboard += m_cFileList.GetItemText(index, 1);
\r
1346 sTextForClipboard += _T("\r\n");
\r
1348 CStringUtils::WriteAsciiStringToClipboard(sTextForClipboard);
\r
1352 void CFileDiffDlg::OnEnChangeRev1edit()
\r
1354 // TODO: If this is a RICHEDIT control, the control will not
\r
1355 // send this notification unless you override the CResizableStandAloneDialog::OnInitDialog()
\r
1356 // function and call CRichEditCtrl().SetEventMask()
\r
1357 // with the ENM_CHANGE flag ORed into the mask.
\r
1359 // TODO: Add your control notification handler code here
\r
1362 void CFileDiffDlg::OnEnChangeRev2edit()
\r
1364 // TODO: If this is a RICHEDIT control, the control will not
\r
1365 // send this notification unless you override the CResizableStandAloneDialog::OnInitDialog()
\r
1366 // function and call CRichEditCtrl().SetEventMask()
\r
1367 // with the ENM_CHANGE flag ORed into the mask.
\r
1369 // TODO: Add your control notification handler code here
\r
1372 LRESULT CFileDiffDlg::OnRefLoad(WPARAM wParam, LPARAM lParam)
\r
1374 for(int i=0;i<m_Reflist.size();i++)
\r
1376 CString str=m_Reflist[i];
\r
1378 if(str.Find(_T("remotes/")) == 0)
\r
1381 m_ctrRev1Edit.AddSearchString(str);
\r
1382 m_ctrRev2Edit.AddSearchString(str);
\r
1387 BOOL CFileDiffDlg::DestroyWindow()
\r
1389 return CResizableStandAloneDialog::DestroyWindow();
\r
1392 LRESULT CFileDiffDlg::OnEnUpdate(WPARAM wParam, LPARAM lParam)
\r
1394 if(lParam == IDC_REV1EDIT)
\r
1396 OnTextUpdate(&this->m_ctrRev1Edit);
\r
1399 if(lParam == IDC_REV2EDIT)
\r
1401 OnTextUpdate(&this->m_ctrRev2Edit);
\r
1402 ClearURLabels(1<<1);
\r
1407 void CFileDiffDlg::OnTextUpdate(CACEdit *pEdit)
\r
1409 SetTimer(IDT_INPUT, 1000, NULL);
\r
1410 this->m_cFileList.ShowText(_T("Wait For input validate version"));
\r