Clean up warning
[TortoiseGit.git] / src / TortoiseProc / FileDiffDlg.cpp
blob4b41903cd38b54280cc9e234597c6e8828c4ce9a
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2003-2008 - TortoiseGit
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #include "stdafx.h"
20 #include "TortoiseProc.h"
21 #include "UnicodeUtils.h"
22 #include "MessageBox.h"
23 #include "AppUtils.h"
24 #include "TempFile.h"
25 #include "ProgressDlg.h"
26 #include "SysImageList.h"
27 //#include "GitProperties.h"
28 #include "StringUtils.h"
29 #include "PathUtils.h"
30 #include "BrowseFolder.h"
31 #include "RevisionDlg.h"
32 #include ".\filediffdlg.h"
33 #include "gitdiff.h"
34 #include "CommonResource.h"
35 #include "BrowseRefsDlg.h"
36 #include "LogDlg.h"
37 #include "RefLogDlg.h"
38 #include "GitStatusListCtrl.h"
40 #define ID_COMPARE 1
41 #define ID_BLAME 2
42 #define ID_SAVEAS 3
43 #define ID_EXPORT 4
44 #define ID_CLIPBOARD_PATH 5
45 #define ID_CLIPBOARD_ALL 6
47 BOOL CFileDiffDlg::m_bAscending = FALSE;
48 int CFileDiffDlg::m_nSortedColumn = -1;
51 IMPLEMENT_DYNAMIC(CFileDiffDlg, CResizableStandAloneDialog)
52 CFileDiffDlg::CFileDiffDlg(CWnd* pParent /*=NULL*/)
53 : CResizableStandAloneDialog(CFileDiffDlg::IDD, pParent),
54 m_bBlame(false),
55 m_pProgDlg(NULL),
56 m_bCancelled(false)
58 m_bLoadingRef=FALSE;
61 CFileDiffDlg::~CFileDiffDlg()
63 DestroyIcon(m_hSwitchIcon);
66 void CFileDiffDlg::DoDataExchange(CDataExchange* pDX)
68 CResizableStandAloneDialog::DoDataExchange(pDX);
69 DDX_Control(pDX, IDC_FILELIST, m_cFileList);
70 DDX_Control(pDX, IDC_SWITCHLEFTRIGHT, m_SwitchButton);
71 DDX_Control(pDX, IDC_REV1BTN, m_cRev1Btn);
72 DDX_Control(pDX, IDC_REV2BTN, m_cRev2Btn);
73 DDX_Control(pDX, IDC_FILTER, m_cFilter);
74 DDX_Control(pDX, IDC_REV1EDIT, m_ctrRev1Edit);
75 DDX_Control(pDX, IDC_REV2EDIT, m_ctrRev2Edit);
79 BEGIN_MESSAGE_MAP(CFileDiffDlg, CResizableStandAloneDialog)
80 ON_NOTIFY(NM_DBLCLK, IDC_FILELIST, OnNMDblclkFilelist)
81 ON_NOTIFY(LVN_GETINFOTIP, IDC_FILELIST, OnLvnGetInfoTipFilelist)
82 ON_NOTIFY(NM_CUSTOMDRAW, IDC_FILELIST, OnNMCustomdrawFilelist)
83 ON_WM_CONTEXTMENU()
84 ON_WM_SETCURSOR()
85 ON_EN_SETFOCUS(IDC_SECONDURL, &CFileDiffDlg::OnEnSetfocusSecondurl)
86 ON_EN_SETFOCUS(IDC_FIRSTURL, &CFileDiffDlg::OnEnSetfocusFirsturl)
87 ON_BN_CLICKED(IDC_SWITCHLEFTRIGHT, &CFileDiffDlg::OnBnClickedSwitchleftright)
88 ON_NOTIFY(HDN_ITEMCLICK, 0, &CFileDiffDlg::OnHdnItemclickFilelist)
89 ON_BN_CLICKED(IDC_REV1BTN, &CFileDiffDlg::OnBnClickedRev1btn)
90 ON_BN_CLICKED(IDC_REV2BTN, &CFileDiffDlg::OnBnClickedRev2btn)
91 ON_MESSAGE(WM_FILTEREDIT_CANCELCLICKED, OnClickedCancelFilter)
92 ON_EN_CHANGE(IDC_FILTER, &CFileDiffDlg::OnEnChangeFilter)
93 ON_WM_TIMER()
94 ON_MESSAGE(ENAC_UPDATE, &CFileDiffDlg::OnEnUpdate)
95 ON_MESSAGE(MSG_REF_LOADED, OnRefLoad)
96 END_MESSAGE_MAP()
99 void CFileDiffDlg::SetDiff(CTGitPath * path, GitRev rev1, GitRev rev2)
101 if(path!=NULL)
103 m_path1 = *path;
104 m_path2 = *path;
106 m_rev1 = rev1;
107 m_rev2 = rev2;
110 void CFileDiffDlg::SetDiff(CTGitPath * path, CString &hash1, CString &hash2)
112 if(path!=NULL)
114 m_path1 = *path;
115 m_path2 = *path;
118 BYTE_VECTOR logout;
120 if(hash1 == GIT_REV_ZERO)
122 m_rev1.m_CommitHash.Empty();
123 m_rev1.GetSubject()=_T("Working Copy");
124 }else
126 m_rev1.GetCommit(hash1);
129 logout.clear();
131 if(hash2 == GIT_REV_ZERO)
133 m_rev2.m_CommitHash.Empty();
134 m_rev2.GetSubject()=_T("Working Copy");
135 }else
137 m_rev2.GetCommit(hash2);
140 void CFileDiffDlg::SetDiff(CTGitPath * path, GitRev rev1)
142 if(path!=NULL)
144 m_path1 = *path;
145 m_path2 = *path;
147 m_rev1 = rev1;
148 m_rev2.m_CommitHash.Empty();
149 m_rev2.GetSubject() = _T("Previou Version");
151 //this->GetDlgItem()->EnableWindow(FALSE);
156 BOOL CFileDiffDlg::OnInitDialog()
158 CResizableStandAloneDialog::OnInitDialog();
159 CString temp;
161 this->m_ctrRev1Edit.Init();
162 this->m_ctrRev2Edit.Init();
164 m_tooltips.Create(this);
165 m_tooltips.AddTool(IDC_SWITCHLEFTRIGHT, IDS_FILEDIFF_SWITCHLEFTRIGHT_TT);
167 m_cFileList.SetRedraw(false);
168 m_cFileList.DeleteAllItems();
169 DWORD exStyle = LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER | LVS_EX_INFOTIP;
170 m_cFileList.SetExtendedStyle(exStyle);
172 m_nIconFolder = SYS_IMAGE_LIST().GetDirIconIndex();
173 m_cFileList.SetImageList(&SYS_IMAGE_LIST(), LVSIL_SMALL);
175 m_hSwitchIcon = (HICON)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_SWITCHLEFTRIGHT), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
176 m_SwitchButton.SetIcon(m_hSwitchIcon);
178 m_cFilter.SetCancelBitmaps(IDI_CANCELNORMAL, IDI_CANCELPRESSED);
179 m_cFilter.SetInfoIcon(IDI_FILTEREDIT);
180 temp.LoadString(IDS_FILEDIFF_FILTERCUE);
181 temp = _T(" ")+temp;
182 m_cFilter.SetCueBanner(temp);
184 int c = ((CHeaderCtrl*)(m_cFileList.GetDlgItem(0)))->GetItemCount()-1;
185 while (c>=0)
186 m_cFileList.DeleteColumn(c--);
189 temp.LoadString(IDS_FILEDIFF_FILE);
190 m_cFileList.InsertColumn(0, temp);
191 temp.LoadString(IDS_FILEDIFF_ACTION);
192 m_cFileList.InsertColumn(1, temp);
194 temp.LoadString(IDS_FILEDIFF_STATADD);
195 m_cFileList.InsertColumn(2, temp);
196 temp.LoadString(IDS_FILEDIFF_STATDEL);
197 m_cFileList.InsertColumn(3, temp);
199 int mincol = 0;
200 int maxcol = ((CHeaderCtrl*)(m_cFileList.GetDlgItem(0)))->GetItemCount()-1;
201 int col;
202 for (col = mincol; col <= maxcol; col++)
204 m_cFileList.SetColumnWidth(col,LVSCW_AUTOSIZE_USEHEADER);
207 m_cFileList.SetRedraw(true);
209 AddAnchor(IDC_DIFFSTATIC1, TOP_LEFT, TOP_RIGHT);
210 AddAnchor(IDC_SWITCHLEFTRIGHT, TOP_RIGHT);
211 AddAnchor(IDC_FIRSTURL, TOP_LEFT, TOP_RIGHT);
212 AddAnchor(IDC_REV1BTN, TOP_RIGHT);
213 //AddAnchor(IDC_DIFFSTATIC2, TOP_LEFT, TOP_RIGHT);
214 AddAnchor(IDC_SECONDURL, TOP_LEFT, TOP_RIGHT);
215 AddAnchor(IDC_REV2BTN, TOP_RIGHT);
216 AddAnchor(IDC_FILTER, TOP_LEFT, TOP_RIGHT);
217 AddAnchor(IDC_FILELIST, TOP_LEFT, BOTTOM_RIGHT);
218 AddAnchor(IDC_REV1GROUP,TOP_LEFT,TOP_RIGHT);
219 AddAnchor(IDC_REV2GROUP,TOP_LEFT,TOP_RIGHT);
220 AddAnchor(IDC_REV1EDIT,TOP_LEFT);
221 AddAnchor(IDC_REV2EDIT,TOP_LEFT);
223 EnableSaveRestore(_T("FileDiffDlg"));
225 if(this->m_strRev1.IsEmpty())
226 this->m_ctrRev1Edit.SetWindowText(this->m_rev1.m_CommitHash.ToString());
227 else
229 if(m_rev1.GetCommit(this->m_strRev1))
230 this->m_FileListText+=this->m_strRev1 + _T(" is wrong");
232 this->m_ctrRev1Edit.SetWindowText(m_strRev1);
235 if(this->m_strRev2.IsEmpty())
236 this->m_ctrRev2Edit.SetWindowText(this->m_rev2.m_CommitHash.ToString());
237 else
239 if(m_rev2.GetCommit(this->m_strRev2))
240 this->m_FileListText+=this->m_strRev2 + _T(" is wrong");
242 this->m_ctrRev2Edit.SetWindowText(m_strRev2);
245 SetURLLabels();
247 InterlockedExchange(&m_bThreadRunning, TRUE);
248 if (AfxBeginThread(DiffThreadEntry, this)==NULL)
250 InterlockedExchange(&m_bThreadRunning, FALSE);
251 CMessageBox::Show(NULL, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
254 InterlockedExchange(&m_bLoadingRef, TRUE);
255 if (AfxBeginThread(LoadRefThreadEntry, this)==NULL)
257 InterlockedExchange(&m_bLoadingRef, FALSE);
258 CMessageBox::Show(NULL, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
262 this->m_cRev1Btn.AddEntry(_T("RefBrowse"));
263 this->m_cRev1Btn.AddEntry(_T("Log"));
264 this->m_cRev1Btn.AddEntry(_T("RefLog"));
266 this->m_cRev2Btn.AddEntry(_T("RefBrowse"));
267 this->m_cRev2Btn.AddEntry(_T("Log"));
268 this->m_cRev2Btn.AddEntry(_T("RefLog"));
270 // Start with focus on file list
271 GetDlgItem(IDC_FILELIST)->SetFocus();
273 if(m_rev2.m_CommitHash.IsEmpty())
274 m_SwitchButton.EnableWindow(FALSE);
276 KillTimer(IDT_INPUT);
277 return FALSE;
280 #if 0
281 svn_error_t* CFileDiffDlg::DiffSummarizeCallback(const CTGitPath& path,
282 svn_client_diff_summarize_kind_t kind,
283 bool propchanged, svn_node_kind_t node)
285 CTGitPath* fd;
286 fd.path = path;
287 fd.kind = kind;
288 fd.node = node;
289 fd.propchanged = propchanged;
290 m_arFileList.push_back(fd);
291 return Git_NO_ERROR;
293 #endif
295 UINT CFileDiffDlg::DiffThreadEntry(LPVOID pVoid)
297 return ((CFileDiffDlg*)pVoid)->DiffThread();
300 UINT CFileDiffDlg::DiffThread()
302 RefreshCursor();
303 m_cFileList.ShowText(CString(MAKEINTRESOURCE(IDS_FILEDIFF_WAIT)));
304 m_cFileList.DeleteAllItems();
305 m_arFileList.Clear();
306 EnableInputControl(false);
307 #if 0
308 bool bSuccess = true;
309 if (m_bDoPegDiff)
311 // bSuccess = DiffSummarizePeg(m_path1, m_peg, m_rev1, m_rev2, m_depth, m_bIgnoreancestry);
313 else
315 // bSuccess = DiffSummarize(m_path1, m_rev1, m_path2, m_rev2, m_depth, m_bIgnoreancestry);
317 // if (!bSuccess)
318 // {
319 // m_cFileList.ShowText(GetLastErrorMessage());
320 // InterlockedExchange(&m_bThreadRunning, FALSE);
321 // return 0;
322 // }
323 #endif
325 if( m_rev1.m_CommitHash.IsEmpty() || m_rev2.m_CommitHash.IsEmpty())
326 g_Git.RefreshGitIndex();
328 g_Git.GetCommitDiffList(m_rev1.m_CommitHash.ToString(),m_rev2.m_CommitHash.ToString(),m_arFileList);
330 CString sFilterText;
331 m_cFilter.GetWindowText(sFilterText);
332 m_cFileList.SetRedraw(false);
333 Filter(sFilterText);
334 if (m_arFileList.GetCount()>0)
336 // Highlight first entry in file list
337 m_cFileList.SetSelectionMark(0);
338 m_cFileList.SetItemState(0, LVIS_SELECTED, LVIS_SELECTED);
341 int mincol = 0;
342 int maxcol = ((CHeaderCtrl*)(m_cFileList.GetDlgItem(0)))->GetItemCount()-1;
343 int col;
344 for (col = mincol; col <= maxcol; col++)
346 m_cFileList.SetColumnWidth(col,LVSCW_AUTOSIZE_USEHEADER);
349 m_cFileList.ClearText();
350 m_cFileList.SetRedraw(true);
352 InterlockedExchange(&m_bThreadRunning, FALSE);
353 InvalidateRect(NULL);
354 RefreshCursor();
355 EnableInputControl(true);
356 return 0;
359 int CFileDiffDlg::AddEntry(const CTGitPath * fd)
361 int ret = -1;
362 if (fd)
364 int index = m_cFileList.GetItemCount();
366 int icon_idx = 0;
367 // if (fd->node == svn_node_dir)
368 // icon_idx = m_nIconFolder;
369 // else
371 icon_idx = SYS_IMAGE_LIST().GetPathIconIndex(fd->GetGitPathString());
374 ret = m_cFileList.InsertItem(index, fd->GetGitPathString(), icon_idx);
375 m_cFileList.SetItemText(index, 1, ((CTGitPath*)fd)->GetActionName());
376 m_cFileList.SetItemText(index, 2, ((CTGitPath*)fd)->m_StatAdd);
377 m_cFileList.SetItemText(index, 3, ((CTGitPath*)fd)->m_StatDel);
379 return ret;
382 void CFileDiffDlg::EnableInputControl(bool b)
384 this->m_ctrRev1Edit.EnableWindow(b);
385 this->m_ctrRev2Edit.EnableWindow(b);
386 this->m_cRev1Btn.EnableWindow(b);
387 this->m_cRev2Btn.EnableWindow(b);
388 m_cFilter.EnableWindow(b);
389 m_SwitchButton.EnableWindow(b);
392 void CFileDiffDlg::DoDiff(int selIndex, bool blame)
395 CGitDiff diff;
396 CTGitPath* fd = m_arFilteredList[selIndex];
397 diff.Diff(fd, fd,this->m_rev1.m_CommitHash.ToString(), this->m_rev2.m_CommitHash.ToString(), blame, FALSE);
399 #if 0
400 CFileDiffDlg::CTGitPath* fd = m_arFilteredList[selIndex];
402 CTGitPath url1 = CTGitPath(m_path1.GetGitPathString() + _T("/") + fd.path.GetGitPathString());
403 CTGitPath url2 = m_bDoPegDiff ? url1 : CTGitPath(m_path2.GetGitPathString() + _T("/") + fd.path.GetGitPathString());
405 if (fd.kind == svn_client_diff_summarize_kind_deleted)
407 if (!PathIsURL(url1))
408 url1 = CTGitPath(GetURLFromPath(m_path1) + _T("/") + fd.path.GetGitPathString());
409 if (!PathIsURL(url2))
410 url2 = m_bDoPegDiff ? url1 : CTGitPath(GetURLFromPath(m_path2) + _T("/") + fd.path.GetGitPathString());
413 if (fd.propchanged)
415 DiffProps(selIndex);
417 if (fd.node == svn_node_dir)
418 return;
420 CTGitPath tempfile = CTempFiles::Instance().GetTempFilePath(false, m_path1, m_rev1);
421 CString sTemp;
422 CProgressDlg progDlg;
423 progDlg.SetTitle(IDS_PROGRESSWAIT);
424 progDlg.SetAnimation(IDR_DOWNLOAD);
425 progDlg.ShowModeless(this);
426 progDlg.FormatPathLine(1, IDS_PROGRESSGETFILE, (LPCTSTR)m_path1.GetUIPathString());
427 progDlg.FormatNonPathLine(2, IDS_PROGRESSREVISIONTEXT, (LPCTSTR)m_rev1.ToString());
429 if ((fd.kind != svn_client_diff_summarize_kind_added)&&(!blame)&&(!Cat(url1, m_bDoPegDiff ? m_peg : m_rev1, m_rev1, tempfile)))
431 if ((!m_bDoPegDiff)||(!Cat(url1, m_rev1, m_rev1, tempfile)))
433 CMessageBox::Show(NULL, GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR);
434 return;
437 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)))
439 if ((!m_bDoPegDiff)||(!m_blamer.BlameToFile(url1, 1, m_rev1, m_rev1, tempfile, _T(""), TRUE, TRUE)))
441 CMessageBox::Show(NULL, m_blamer.GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR);
442 return;
445 SetFileAttributes(tempfile.GetWinPath(), FILE_ATTRIBUTE_READONLY);
446 progDlg.SetProgress(1, 2);
447 progDlg.FormatPathLine(1, IDS_PROGRESSGETFILE, (LPCTSTR)url2.GetUIPathString());
448 progDlg.FormatNonPathLine(2, IDS_PROGRESSREVISIONTEXT, (LPCTSTR)m_rev2.ToString());
449 CTGitPath tempfile2 = CTempFiles::Instance().GetTempFilePath(false, url2, m_rev2);
450 if ((fd.kind != svn_client_diff_summarize_kind_deleted)&&(!blame)&&(!Cat(url2, m_bDoPegDiff ? m_peg : m_rev2, m_rev2, tempfile2)))
452 if ((!m_bDoPegDiff)||(!Cat(url2, m_rev2, m_rev2, tempfile2)))
454 CMessageBox::Show(NULL, GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR);
455 return;
458 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)))
460 if ((!m_bDoPegDiff)||(!m_blamer.BlameToFile(url2, 1, m_rev2, m_rev2, tempfile2, _T(""), TRUE, TRUE)))
462 CMessageBox::Show(NULL, m_blamer.GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR);
463 return;
466 SetFileAttributes(tempfile2.GetWinPath(), FILE_ATTRIBUTE_READONLY);
467 progDlg.SetProgress(2,2);
468 progDlg.Stop();
470 CString rev1name, rev2name;
471 if (m_bDoPegDiff)
473 rev1name.Format(_T("%s Revision %ld"), (LPCTSTR)fd.path.GetGitPathString(), (LONG)m_rev1);
474 rev2name.Format(_T("%s Revision %ld"), (LPCTSTR)fd.path.GetGitPathString(), (LONG)m_rev2);
476 else
478 rev1name = m_path1.GetGitPathString() + _T("/") + fd.path.GetGitPathString();
479 rev2name = m_path2.GetGitPathString() + _T("/") + fd.path.GetGitPathString();
481 CAppUtils::DiffFlags flags;
482 flags.AlternativeTool(!!(GetAsyncKeyState(VK_SHIFT) & 0x8000));
483 flags.Blame(blame);
484 CAppUtils::StartExtDiff(
485 tempfile, tempfile2, rev1name, rev2name, flags);
486 #endif
489 #if 0
490 void CFileDiffDlg::DiffProps(int selIndex)
492 CFileDiffDlg::CTGitPath* fd = m_arFilteredList[selIndex];
494 CTGitPath url1 = CTGitPath(m_path1.GetGitPathString() + _T("/") + fd.path.GetGitPathString());
495 CTGitPath url2 = m_bDoPegDiff ? url1 : CTGitPath(m_path2.GetGitPathString() + _T("/") + fd.path.GetGitPathString());
497 GitProperties propsurl1(url1, m_rev1, false);
498 GitProperties propsurl2(url2, m_rev2, false);
500 // collect the properties of both revisions in a set
501 std::set<stdstring> properties;
502 for (int wcindex = 0; wcindex < propsurl1.GetCount(); ++wcindex)
504 stdstring urlname = propsurl1.GetItemName(wcindex);
505 if ( properties.find(urlname) == properties.end() )
507 properties.insert(urlname);
510 for (int wcindex = 0; wcindex < propsurl2.GetCount(); ++wcindex)
512 stdstring urlname = propsurl2.GetItemName(wcindex);
513 if ( properties.find(urlname) == properties.end() )
515 properties.insert(urlname);
519 // iterate over all properties and diff the properties
520 for (std::set<stdstring>::iterator iter = properties.begin(), end = properties.end(); iter != end; ++iter)
522 stdstring url1name = *iter;
524 stdstring url1value = _T(""); // CUnicodeUtils::StdGetUnicode((char *)propsurl1.GetItemValue(wcindex).c_str());
525 for (int url1index = 0; url1index < propsurl1.GetCount(); ++url1index)
527 if (propsurl1.GetItemName(url1index).compare(url1name)==0)
529 url1value = CString((char *)propsurl1.GetItemValue(url1index).c_str());
533 stdstring url2value = _T("");
534 for (int url2index = 0; url2index < propsurl2.GetCount(); ++url2index)
536 if (propsurl2.GetItemName(url2index).compare(url1name)==0)
538 url2value = CString((char *)propsurl2.GetItemValue(url2index).c_str());
542 if (url2value.compare(url1value)!=0)
544 // write both property values to temporary files
545 CTGitPath url1propfile = CTempFiles::Instance().GetTempFilePath(false);
546 CTGitPath url2propfile = CTempFiles::Instance().GetTempFilePath(false);
547 FILE * pFile;
548 _tfopen_s(&pFile, url1propfile.GetWinPath(), _T("wb"));
549 if (pFile)
551 fputs(CUnicodeUtils::StdGetUTF8(url1value).c_str(), pFile);
552 fclose(pFile);
553 FILE * pFile;
554 _tfopen_s(&pFile, url2propfile.GetWinPath(), _T("wb"));
555 if (pFile)
557 fputs(CUnicodeUtils::StdGetUTF8(url2value).c_str(), pFile);
558 fclose(pFile);
560 else
561 return;
563 else
564 return;
565 SetFileAttributes(url1propfile.GetWinPath(), FILE_ATTRIBUTE_READONLY);
566 SetFileAttributes(url2propfile.GetWinPath(), FILE_ATTRIBUTE_READONLY);
567 CString n1, n2;
568 if (m_rev1.IsWorking())
569 n1.Format(IDS_DIFF_WCNAME, url1name.c_str());
570 if (m_rev1.IsBase())
571 n1.Format(IDS_DIFF_BASENAME, url1name.c_str());
572 if (m_rev1.IsHead() || m_rev1.IsNumber())
574 if (m_bDoPegDiff)
576 n1.Format(_T("%s : %s Revision %ld"), url1name.c_str(), (LPCTSTR)fd.path.GetGitPathString(), (LONG)m_rev1);
578 else
580 CString sTemp = url1name.c_str();
581 sTemp += _T(" : ");
582 n1 = sTemp + m_path1.GetGitPathString() + _T("/") + fd.path.GetGitPathString();
585 if (m_rev2.IsWorking())
586 n2.Format(IDS_DIFF_WCNAME, url1name.c_str());
587 if (m_rev2.IsBase())
588 n2.Format(IDS_DIFF_BASENAME, url1name.c_str());
589 if (m_rev2.IsHead() || m_rev2.IsNumber())
591 if (m_bDoPegDiff)
593 n2.Format(_T("%s : %s Revision %ld"), url1name.c_str(), (LPCTSTR)fd.path.GetGitPathString(), (LONG)m_rev2);
595 else
597 CString sTemp = url1name.c_str();
598 sTemp += _T(" : ");
599 n2 = sTemp + m_path2.GetGitPathString() + _T("/") + fd.path.GetGitPathString();
602 CAppUtils::StartExtDiffProps(url1propfile, url2propfile, n1, n2, TRUE);
606 #endif
607 void CFileDiffDlg::OnNMDblclkFilelist(NMHDR *pNMHDR, LRESULT *pResult)
609 *pResult = 0;
610 LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
611 int selIndex = pNMLV->iItem;
612 if (selIndex < 0)
613 return;
614 if (selIndex >= (int)m_arFilteredList.size())
615 return;
617 DoDiff(selIndex, m_bBlame);
620 void CFileDiffDlg::OnLvnGetInfoTipFilelist(NMHDR *pNMHDR, LRESULT *pResult)
623 LPNMLVGETINFOTIP pGetInfoTip = reinterpret_cast<LPNMLVGETINFOTIP>(pNMHDR);
624 if (pGetInfoTip->iItem >= (int)m_arFilteredList.size())
625 return;
627 CString path = m_path1.GetGitPathString() + _T("/") + m_arFilteredList[pGetInfoTip->iItem]->GetGitPathString();
628 if (pGetInfoTip->cchTextMax > path.GetLength())
629 _tcsncpy_s(pGetInfoTip->pszText, pGetInfoTip->cchTextMax, path, pGetInfoTip->cchTextMax);
631 *pResult = 0;
634 void CFileDiffDlg::OnNMCustomdrawFilelist(NMHDR *pNMHDR, LRESULT *pResult)
636 NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>( pNMHDR );
637 // Take the default processing unless we set this to something else below.
638 *pResult = CDRF_DODEFAULT;
640 // First thing - check the draw stage. If it's the control's prepaint
641 // stage, then tell Windows we want messages for every item.
643 if ( CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage )
645 *pResult = CDRF_NOTIFYITEMDRAW;
647 else if ( CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage )
649 // This is the prepaint stage for an item. Here's where we set the
650 // item's text color. Our return value will tell Windows to draw the
651 // item itself, but it will use the new color we set here.
653 // Tell Windows to paint the control itself.
654 *pResult = CDRF_DODEFAULT;
656 COLORREF crText = GetSysColor(COLOR_WINDOWTEXT);
658 if (m_arFilteredList.size() > pLVCD->nmcd.dwItemSpec)
660 CTGitPath * fd = m_arFilteredList[pLVCD->nmcd.dwItemSpec];
661 switch (fd->m_Action)
663 case CTGitPath::LOGACTIONS_ADDED:
664 crText = m_colors.GetColor(CColors::Added);
665 break;
666 case CTGitPath::LOGACTIONS_DELETED:
667 crText = m_colors.GetColor(CColors::Deleted);
668 break;
669 case CTGitPath::LOGACTIONS_MODIFIED:
670 crText = m_colors.GetColor(CColors::Modified);
671 break;
672 //case svn_client_diff_summarize_kind_normal:
673 default:
674 //if (fd.propchanged)
675 crText = m_colors.GetColor(CColors::PropertyChanged);
676 break;
679 // Store the color back in the NMLVCUSTOMDRAW struct.
680 pLVCD->clrText = crText;
684 UINT CFileDiffDlg::LoadRefThread()
686 g_Git.GetBranchList(m_Reflist,NULL,CGit::BRANCH_ALL);
687 g_Git.GetTagList(m_Reflist);
689 this->PostMessage(MSG_REF_LOADED);
690 InterlockedExchange(&m_bLoadingRef, FALSE);
691 return 0;
694 void CFileDiffDlg::OnContextMenu(CWnd* pWnd, CPoint point)
696 if ((pWnd==0)||(pWnd != &m_cFileList))
697 return;
698 if (m_cFileList.GetSelectedCount() == 0)
699 return;
700 // if the context menu is invoked through the keyboard, we have to use
701 // a calculated position on where to anchor the menu on
702 if ((point.x == -1) && (point.y == -1))
704 CRect rect;
705 m_cFileList.GetItemRect(m_cFileList.GetSelectionMark(), &rect, LVIR_LABEL);
706 m_cFileList.ClientToScreen(&rect);
707 point = rect.CenterPoint();
709 CMenu popup;
710 if (popup.CreatePopupMenu())
712 CString temp;
713 temp.LoadString(IDS_LOG_POPUP_COMPARETWO);
714 popup.AppendMenu(MF_STRING | MF_ENABLED, ID_COMPARE, temp);
715 temp.LoadString(IDS_FILEDIFF_POPBLAME);
716 //popup.AppendMenu(MF_STRING | MF_ENABLED, ID_BLAME, temp);
717 popup.AppendMenu(MF_SEPARATOR, NULL);
718 temp.LoadString(IDS_FILEDIFF_POPSAVELIST);
719 popup.AppendMenu(MF_STRING | MF_ENABLED, ID_SAVEAS, temp);
720 temp.LoadString(IDS_STATUSLIST_CONTEXT_COPY);
721 popup.AppendMenu(MF_STRING | MF_ENABLED, ID_CLIPBOARD_PATH, temp);
722 temp.LoadString(IDS_STATUSLIST_CONTEXT_COPYEXT);
723 popup.AppendMenu(MF_STRING | MF_ENABLED, ID_CLIPBOARD_ALL, temp);
725 //temp.LoadString(IDS_FILEDIFF_POPEXPORT);
726 //popup.AppendMenu(MF_STRING | MF_ENABLED, ID_EXPORT, temp);
727 int cmd = popup.TrackPopupMenu(TPM_RETURNCMD | TPM_LEFTALIGN | TPM_NONOTIFY, point.x, point.y, this, 0);
728 m_bCancelled = false;
729 switch (cmd)
731 case ID_COMPARE:
733 POSITION pos = m_cFileList.GetFirstSelectedItemPosition();
734 while (pos)
736 int index = m_cFileList.GetNextSelectedItem(pos);
737 DoDiff(index, false);
740 break;
741 case ID_BLAME:
743 POSITION pos = m_cFileList.GetFirstSelectedItemPosition();
744 while (pos)
746 int index = m_cFileList.GetNextSelectedItem(pos);
747 DoDiff(index, true);
750 break;
751 case ID_SAVEAS:
753 if (m_cFileList.GetSelectedCount() > 0)
755 CString temp;
756 CTGitPath savePath;
757 CString pathSave;
758 if (!CAppUtils::FileOpenSave(pathSave, NULL, IDS_REPOBROWSE_SAVEAS, IDS_COMMONFILEFILTER, false, m_hWnd))
760 break;
762 savePath = CTGitPath(pathSave);
764 // now open the selected file for writing
767 CStdioFile file(savePath.GetWinPathString(), CFile::typeBinary | CFile::modeReadWrite | CFile::modeCreate);
768 // temp.Format(IDS_FILEDIFF_CHANGEDLISTINTRO, (LPCTSTR)m_path1.GetGitPathString(), (LPCTSTR)m_rev1.ToString(), (LPCTSTR)m_path2.GetGitPathString(), (LPCTSTR)m_rev2.ToString());
769 file.WriteString(temp + _T("\n"));
770 POSITION pos = m_cFileList.GetFirstSelectedItemPosition();
771 while (pos)
773 int index = m_cFileList.GetNextSelectedItem(pos);
774 CTGitPath* fd = m_arFilteredList[index];
775 file.WriteString(fd->GetGitPathString());
776 file.WriteString(_T("\n"));
778 file.Close();
780 catch (CFileException* pE)
782 pE->ReportError();
786 break;
787 case ID_CLIPBOARD_PATH:
789 CopySelectionToClipboard();
791 break;
793 case ID_CLIPBOARD_ALL:
795 CopySelectionToClipboard(TRUE);
797 break;
798 case ID_EXPORT:
800 #if 0 //this funcation seem no useful
801 // export all changed files to a folder
802 CBrowseFolder browseFolder;
803 browseFolder.m_style = BIF_EDITBOX | BIF_NEWDIALOGSTYLE | BIF_RETURNFSANCESTORS | BIF_RETURNONLYFSDIRS;
804 if (browseFolder.Show(GetSafeHwnd(), m_strExportDir) == CBrowseFolder::OK)
806 m_arSelectedFileList.RemoveAll();
807 POSITION pos = m_cFileList.GetFirstSelectedItemPosition();
808 while (pos)
810 int index = m_cFileList.GetNextSelectedItem(pos);
811 CTGitPath* fd = m_arFilteredList[index];
812 m_arSelectedFileList.Add(fd);
814 m_pProgDlg = new CProgressDlg();
815 InterlockedExchange(&m_bThreadRunning, TRUE);
816 if (AfxBeginThread(ExportThreadEntry, this)==NULL)
818 InterlockedExchange(&m_bThreadRunning, FALSE);
819 CMessageBox::Show(NULL, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
822 #endif;
825 break;
831 UINT CFileDiffDlg::ExportThreadEntry(LPVOID pVoid)
833 return ((CFileDiffDlg*)pVoid)->ExportThread();
836 UINT CFileDiffDlg::ExportThread()
838 #if 0
839 RefreshCursor();
840 // if (m_pProgDlg == NULL)
841 // return 1;
842 long count = 0;
843 // SetAndClearProgressInfo(m_pProgDlg, false);
844 m_pProgDlg->SetTitle(IDS_PROGRESSWAIT);
845 m_pProgDlg->SetAnimation(AfxGetResourceHandle(), IDR_DOWNLOAD);
846 m_pProgDlg->ShowModeless(this);
847 for (INT_PTR i=0; (i<m_arSelectedFileList.GetCount())&&(!m_pProgDlg->HasUserCancelled()); ++i)
849 CTGitPath* fd = m_arSelectedFileList[i];
850 // CTGitPath url1 = CTGitPath(m_path1.GetGitPathString() + _T("/") + fd.path.GetGitPathString());
851 // CTGitPath url2 = m_bDoPegDiff ? url1 : CTGitPath(m_path2.GetGitPathString() + _T("/") + fd.path.GetGitPathString());
852 // if ((fd.node == svn_node_dir)&&(fd.kind != svn_client_diff_summarize_kind_added))
853 // {
854 // just create the directory
855 // CreateDirectoryEx(NULL, m_strExportDir+_T("\\")+CPathUtils::PathUnescape(fd.path.GetWinPathString()), NULL);
856 // continue;
857 // }
859 CString sTemp;
860 m_pProgDlg->FormatPathLine(1, IDS_PROGRESSGETFILE, (LPCTSTR)url1.GetGitPathString());
862 CTGitPath savepath = CTGitPath(m_strExportDir);
863 savepath.AppendPathString(_T("\\") + CPathUtils::PathUnescape(fd.path.GetWinPathString()));
864 CPathUtils::MakeSureDirectoryPathExists(fd.node == svn_node_file ? savepath.GetContainingDirectory().GetWinPath() : savepath.GetDirectory().GetWinPath());
865 if (fd.node == svn_node_dir)
867 // exporting a folder requires calling Git::Export() so we also export all
868 // children of that added folder.
869 if ((fd.kind == svn_client_diff_summarize_kind_added)&&(!Export(url2, savepath, m_bDoPegDiff ? m_peg : m_rev2, m_rev2, true, true)))
871 if ((!m_bDoPegDiff)||(!Export(url2, savepath, m_rev2, m_rev2, true, true)))
873 delete m_pProgDlg;
874 m_pProgDlg = NULL;
875 CMessageBox::Show(NULL, GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR);
876 InterlockedExchange(&m_bThreadRunning, FALSE);
877 RefreshCursor();
878 return 1;
882 else
884 // exporting a file requires calling Git::Cat(), since Git::Export() only works
885 // with folders.
886 if ((fd.kind != svn_client_diff_summarize_kind_deleted)&&(!Cat(url2, m_bDoPegDiff ? m_peg : m_rev2, m_rev2, savepath)))
888 if ((!m_bDoPegDiff)||(!Cat(url2, m_rev2, m_rev2, savepath)))
890 delete m_pProgDlg;
891 m_pProgDlg = NULL;
892 CMessageBox::Show(NULL, GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR);
893 InterlockedExchange(&m_bThreadRunning, FALSE);
894 RefreshCursor();
895 return 1;
899 count++;
900 m_pProgDlg->SetProgress (count, static_cast<DWORD>(m_arSelectedFileList.GetCount()));
902 m_pProgDlg->Stop();
903 SetAndClearProgressInfo(NULL, false);
904 delete m_pProgDlg;
905 m_pProgDlg = NULL;
906 InterlockedExchange(&m_bThreadRunning, FALSE);
907 RefreshCursor();
908 #endif
909 return 0;
912 BOOL CFileDiffDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
914 if (pWnd != &m_cFileList)
915 return CResizableStandAloneDialog::OnSetCursor(pWnd, nHitTest, message);
916 if (m_bThreadRunning == 0)
918 HCURSOR hCur = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
919 SetCursor(hCur);
920 return CResizableStandAloneDialog::OnSetCursor(pWnd, nHitTest, message);
922 HCURSOR hCur = LoadCursor(NULL, MAKEINTRESOURCE(IDC_WAIT));
923 SetCursor(hCur);
924 return TRUE;
927 void CFileDiffDlg::OnEnSetfocusFirsturl()
929 GetDlgItem(IDC_FIRSTURL)->HideCaret();
932 void CFileDiffDlg::OnEnSetfocusSecondurl()
934 GetDlgItem(IDC_SECONDURL)->HideCaret();
938 void CFileDiffDlg::OnBnClickedSwitchleftright()
941 if (m_bThreadRunning)
942 return;
944 #if 0
945 CString sFilterString;
946 m_cFilter.GetWindowText(sFilterString);
948 m_cFileList.SetRedraw(false);
949 m_cFileList.DeleteAllItems();
950 for (int i=0; i<(int)m_arFileList.GetCount(); ++i)
952 CTGitPath fd = m_arFileList[i];
953 if (fd.m_Action == CTGitPath::LOGACTIONS_ADDED)
954 fd.m_Action = CTGitPath::LOGACTIONS_DELETED;
955 else if (fd.m_Action == CTGitPath::LOGACTIONS_DELETED)
956 fd.m_Action = CTGitPath::LOGACTIONS_ADDED;
957 std::swap(fd.m_StatAdd, fd.m_StatDel);
958 (CTGitPath&)m_arFileList[i] = fd;
960 Filter(sFilterString);
961 #endif
963 m_cFileList.SetRedraw(true);
964 CTGitPath path = m_path1;
965 m_path1 = m_path2;
966 m_path2 = path;
967 GitRev rev = m_rev1;
968 m_rev1 = m_rev2;
969 m_rev2 = rev;
971 CString str1,str2;
972 this->m_ctrRev1Edit.GetWindowText(str1);
973 this->m_ctrRev2Edit.GetWindowText(str2);
975 this->m_ctrRev1Edit.SetWindowText(str2);
976 this->m_ctrRev2Edit.SetWindowText(str1);
978 SetURLLabels();
979 //KillTimer(IDT_INPUT);
982 void CFileDiffDlg::SetURLLabels(int mask)
985 // m_cRev1Btn.SetWindowText(m_rev1.m_CommitHash.ToString().Left(6));
986 // m_cRev2Btn.SetWindowText(m_rev2.m_CommitHash.ToString().Left(6));
988 if(mask &0x1)
990 SetDlgItemText(IDC_FIRSTURL, m_rev1.m_CommitHash.ToString().Left(8)+_T(": ")+m_rev1.GetSubject());
991 m_tooltips.AddTool(IDC_FIRSTURL,
992 CAppUtils::FormatDateAndTime( m_rev1.GetAuthorDate(), DATE_SHORTDATE, false )+_T(" ")+m_rev1.GetAuthorName());
996 if(mask &0x2)
998 SetDlgItemText(IDC_SECONDURL,m_rev2.m_CommitHash.ToString().Left(8)+_T(": ")+m_rev2.GetSubject());
1000 m_tooltips.AddTool(IDC_SECONDURL,
1001 CAppUtils::FormatDateAndTime( m_rev2.GetAuthorDate(), DATE_SHORTDATE, false )+_T(" ")+m_rev2.GetAuthorName());
1004 this->GetDlgItem(IDC_REV2GROUP)->SetWindowText(_T("Version 2 (Base)"));
1005 this->GetDlgItem(IDC_REV1GROUP)->SetWindowText(_T("Version 1"));
1007 if( (mask&0x3) == 0x3)
1008 if(m_rev2.GetCommitterDate() > m_rev1.GetCommitterDate())
1010 this->GetDlgItem(IDC_REV2GROUP)->SetWindowText(_T("Version 2 (Base) (Commit Date New)"));
1011 }else
1013 this->GetDlgItem(IDC_REV1GROUP)->SetWindowText(_T("Version 1(Commit Data New)"));
1017 void CFileDiffDlg::ClearURLabels(int mask)
1019 if(mask&0x1)
1021 SetDlgItemText(IDC_FIRSTURL, _T(""));
1022 m_tooltips.AddTool(IDC_FIRSTURL, _T(""));
1025 if(mask&0x2)
1027 SetDlgItemText(IDC_SECONDURL, _T(""));
1028 m_tooltips.AddTool(IDC_SECONDURL, _T(""));
1031 BOOL CFileDiffDlg::PreTranslateMessage(MSG* pMsg)
1033 m_tooltips.RelayEvent(pMsg);
1034 if (pMsg->message == WM_KEYDOWN)
1036 switch (pMsg->wParam)
1038 case 'A':
1040 if (GetAsyncKeyState(VK_CONTROL)&0x8000)
1042 // select all entries
1043 for (int i=0; i<m_cFileList.GetItemCount(); ++i)
1045 m_cFileList.SetItemState(i, LVIS_SELECTED, LVIS_SELECTED);
1047 return TRUE;
1050 break;
1051 case 'C':
1052 case VK_INSERT:
1054 if (GetAsyncKeyState(VK_CONTROL)&0x8000)
1056 CopySelectionToClipboard();
1057 return TRUE;
1060 break;
1061 case '\r':
1063 if (GetFocus() == GetDlgItem(IDC_FILELIST))
1065 // Return pressed in file list. Show diff, as for double click
1066 int selIndex = m_cFileList.GetSelectionMark();
1067 if ((selIndex >= 0) && (selIndex < (int)m_arFileList.GetCount()))
1068 DoDiff(selIndex, m_bBlame);
1069 return TRUE;
1072 break;
1075 return __super::PreTranslateMessage(pMsg);
1078 void CFileDiffDlg::OnCancel()
1080 if (m_bThreadRunning)
1082 m_bCancelled = true;
1083 return;
1085 __super::OnCancel();
1088 void CFileDiffDlg::OnHdnItemclickFilelist(NMHDR *pNMHDR, LRESULT *pResult)
1090 LPNMHEADER phdr = reinterpret_cast<LPNMHEADER>(pNMHDR);
1091 if (m_bThreadRunning)
1092 return;
1094 if (m_nSortedColumn == phdr->iItem)
1095 m_bAscending = !m_bAscending;
1096 else
1097 m_bAscending = TRUE;
1098 m_nSortedColumn = phdr->iItem;
1099 m_arSelectedFileList.RemoveAll();
1100 Sort();
1102 CString temp;
1103 m_cFileList.SetRedraw(FALSE);
1104 m_cFileList.DeleteAllItems();
1105 m_cFilter.GetWindowText(temp);
1106 Filter(temp);
1108 CHeaderCtrl * pHeader = m_cFileList.GetHeaderCtrl();
1109 HDITEM HeaderItem = {0};
1110 HeaderItem.mask = HDI_FORMAT;
1111 for (int i=0; i<pHeader->GetItemCount(); ++i)
1113 pHeader->GetItem(i, &HeaderItem);
1114 HeaderItem.fmt &= ~(HDF_SORTDOWN | HDF_SORTUP);
1115 pHeader->SetItem(i, &HeaderItem);
1117 pHeader->GetItem(m_nSortedColumn, &HeaderItem);
1118 HeaderItem.fmt |= (m_bAscending ? HDF_SORTUP : HDF_SORTDOWN);
1119 pHeader->SetItem(m_nSortedColumn, &HeaderItem);
1121 m_cFileList.SetRedraw(TRUE);
1123 *pResult = 0;
1126 void CFileDiffDlg::Sort()
1128 if(m_arFileList.GetCount() < 2)
1130 return;
1133 std::sort(m_arFileList.m_paths.begin(), m_arFileList.m_paths.end(), &CFileDiffDlg::SortCompare);
1136 bool CFileDiffDlg::SortCompare(const CTGitPath& Data1, const CTGitPath& Data2)
1138 int result = 0;
1139 int d1, d2;
1140 switch (m_nSortedColumn)
1142 case 0: //path column
1143 result = Data1.GetWinPathString().Compare(Data2.GetWinPathString());
1144 break;
1145 case 1: //action column
1146 result = Data1.m_Action - Data2.m_Action;
1147 break;
1148 case 2:
1149 d1 = CSorter::A2L(Data1.m_StatAdd);
1150 d2 = CSorter::A2L(Data2.m_StatAdd);
1151 result = d1 - d2;
1152 break;
1153 case 3:
1154 d1 = CSorter::A2L(Data1.m_StatDel);;
1155 d2 = CSorter::A2L(Data2.m_StatDel);
1156 result = d1 - d2;
1157 break;
1158 default:
1159 break;
1162 if (!m_bAscending)
1163 result = -result;
1164 return result < 0;
1168 void CFileDiffDlg::OnBnClickedRev1btn()
1171 ClickRevButton(&this->m_cRev1Btn,&this->m_rev1, &this->m_ctrRev1Edit);
1176 void CFileDiffDlg::ClickRevButton(CMenuButton *button, GitRev *rev, CACEdit *edit)
1178 int entry=button->GetCurrentEntry();
1179 if(entry == 0) /* Browse Refence*/
1182 CString str = CBrowseRefsDlg::PickRef();
1183 if(str.IsEmpty())
1184 return;
1186 if(FillRevFromString(rev,str))
1187 return;
1189 edit->SetWindowText(str);
1193 if(entry == 1) /*Log*/
1195 CLogDlg dlg;
1196 dlg.SetSelect(true);
1197 if(dlg.DoModal() == IDOK)
1199 if( dlg.GetSelectedHash().IsEmpty() )
1200 return;
1202 if(FillRevFromString(rev,dlg.GetSelectedHash()))
1203 return;
1205 edit->SetWindowText(dlg.GetSelectedHash());
1207 }else
1208 return;
1211 if(entry == 2) /*RefLog*/
1213 CRefLogDlg dlg;
1214 if(dlg.DoModal() == IDOK)
1216 if(FillRevFromString(rev,dlg.m_SelectedHash))
1217 return;
1219 edit->SetWindowText(dlg.m_SelectedHash);
1221 }else
1222 return;
1226 SetURLLabels();
1228 InterlockedExchange(&m_bThreadRunning, TRUE);
1229 if (AfxBeginThread(DiffThreadEntry, this)==NULL)
1231 InterlockedExchange(&m_bThreadRunning, FALSE);
1232 CMessageBox::Show(NULL, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
1234 KillTimer(IDT_INPUT);
1237 void CFileDiffDlg::OnBnClickedRev2btn()
1239 ClickRevButton(&this->m_cRev2Btn,&this->m_rev2, &this->m_ctrRev2Edit);
1240 #if 0
1241 if (m_bThreadRunning)
1242 return; // do nothing as long as the thread is still running
1244 // show a dialog where the user can enter a revision
1245 CRevisionDlg dlg(this);
1246 dlg.AllowWCRevs(false);
1247 *((GitRev*)&dlg) = m_rev2;
1249 if (dlg.DoModal() == IDOK)
1251 m_rev2 = dlg;
1252 m_cRev2Btn.SetWindowText(m_rev2.ToString());
1253 m_cFileList.DeleteAllItems();
1254 // start a new thread to re-fetch the diff
1255 InterlockedExchange(&m_bThreadRunning, TRUE);
1256 if (AfxBeginThread(DiffThreadEntry, this)==NULL)
1258 InterlockedExchange(&m_bThreadRunning, FALSE);
1259 CMessageBox::Show(NULL, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
1262 #endif
1265 LRESULT CFileDiffDlg::OnClickedCancelFilter(WPARAM /*wParam*/, LPARAM /*lParam*/)
1267 if (m_bThreadRunning)
1269 SetTimer(IDT_FILTER, 1000, NULL);
1270 return 0L;
1273 KillTimer(IDT_FILTER);
1275 m_cFileList.SetRedraw(FALSE);
1276 m_arFilteredList.clear();
1277 m_cFileList.DeleteAllItems();
1279 Filter(_T(""));
1281 m_cFileList.SetRedraw(TRUE);
1282 return 0L;
1285 void CFileDiffDlg::OnEnChangeFilter()
1287 SetTimer(IDT_FILTER, 1000, NULL);
1290 void CFileDiffDlg::OnTimer(UINT_PTR nIDEvent)
1292 if (m_bThreadRunning)
1293 return;
1295 if( nIDEvent == IDT_FILTER)
1298 CString sFilterText;
1299 KillTimer(IDT_FILTER);
1300 m_cFilter.GetWindowText(sFilterText);
1302 m_cFileList.SetRedraw(FALSE);
1303 m_cFileList.DeleteAllItems();
1305 Filter(sFilterText);
1307 m_cFileList.SetRedraw(TRUE);
1309 __super::OnTimer(nIDEvent);
1312 if( nIDEvent == IDT_INPUT)
1314 KillTimer(IDT_INPUT);
1315 TRACE(_T("Input Timer\r\n"));
1317 GitRev gitrev;
1318 CString str;
1319 int mask = 0;
1320 this->m_ctrRev1Edit.GetWindowText(str);
1321 if( !gitrev.GetCommit(str) )
1323 this->m_rev1=gitrev;
1324 mask |= 0x1;
1328 this->m_ctrRev2Edit.GetWindowText(str);
1330 if( !gitrev.GetCommit(str) )
1332 this->m_rev2=gitrev;
1333 mask |= 0x2;
1336 this->SetURLLabels(mask);
1338 if(mask == 0x3)
1341 InterlockedExchange(&m_bThreadRunning, TRUE);
1342 if (AfxBeginThread(DiffThreadEntry, this)==NULL)
1344 InterlockedExchange(&m_bThreadRunning, FALSE);
1345 CMessageBox::Show(NULL, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
1351 void CFileDiffDlg::Filter(CString sFilterText)
1354 sFilterText.MakeLower();
1356 m_arFilteredList.clear();
1358 for (int i=0;i<m_arFileList.GetCount();i++)
1360 CString sPath = m_arFileList[i].GetGitPathString();
1361 sPath.MakeLower();
1362 if (sPath.Find(sFilterText) >= 0)
1364 m_arFilteredList.push_back((CTGitPath*)&(m_arFileList[i]));
1367 for (std::vector<CTGitPath*>::const_iterator it = m_arFilteredList.begin(); it != m_arFilteredList.end(); ++it)
1369 AddEntry(*it);
1374 void CFileDiffDlg::CopySelectionToClipboard(BOOL isFull)
1376 // copy all selected paths to the clipboard
1377 POSITION pos = m_cFileList.GetFirstSelectedItemPosition();
1378 int index;
1379 CString sTextForClipboard;
1380 while ((index = m_cFileList.GetNextSelectedItem(pos)) >= 0)
1382 sTextForClipboard += m_cFileList.GetItemText(index, 0);
1383 sTextForClipboard += _T("\t");
1385 if(!isFull)
1387 sTextForClipboard += _T("\r\n");
1389 }else
1391 sTextForClipboard += m_cFileList.GetItemText(index, 1);
1392 sTextForClipboard += _T("\t");
1393 sTextForClipboard += m_cFileList.GetItemText(index, 2);
1394 sTextForClipboard += _T("\t");
1395 sTextForClipboard += m_cFileList.GetItemText(index, 3);
1396 sTextForClipboard += _T("\r\n");
1399 CStringUtils::WriteAsciiStringToClipboard(sTextForClipboard);
1403 LRESULT CFileDiffDlg::OnRefLoad(WPARAM wParam, LPARAM lParam)
1405 UNREFERENCED_PARAMETER(wParam);
1406 UNREFERENCED_PARAMETER(lParam);
1407 for(int i=0;i<m_Reflist.size();i++)
1409 CString str=m_Reflist[i];
1411 if(str.Find(_T("remotes/")) == 0)
1412 str=str.Mid(8);
1414 m_ctrRev1Edit.AddSearchString(str);
1415 m_ctrRev2Edit.AddSearchString(str);
1417 return 0;
1420 BOOL CFileDiffDlg::DestroyWindow()
1422 return CResizableStandAloneDialog::DestroyWindow();
1425 LRESULT CFileDiffDlg::OnEnUpdate(WPARAM /*wParam*/, LPARAM lParam)
1427 if(lParam == IDC_REV1EDIT)
1429 OnTextUpdate(&this->m_ctrRev1Edit);
1430 ClearURLabels(1);
1432 if(lParam == IDC_REV2EDIT)
1434 OnTextUpdate(&this->m_ctrRev2Edit);
1435 ClearURLabels(1<<1);
1437 return 0;
1440 void CFileDiffDlg::OnTextUpdate(CACEdit * /*pEdit*/)
1442 SetTimer(IDT_INPUT, 1000, NULL);
1443 this->m_cFileList.ShowText(_T("Wait For input validate version"));