OSDN Git Service

Fix Amend Last Commit CheckBox wrong Position
[tortoisegit/TortoiseGitJp.git] / src / TortoiseProc / CommitDlg.cpp
1 // TortoiseGit - a Windows shell extension for easy version control\r
2 \r
3 // Copyright (C) 2003-2008 - TortoiseGit\r
4 \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
9 \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
14 \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
18 //\r
19 #include "stdafx.h"\r
20 #include "TortoiseProc.h"\r
21 #include "CommitDlg.h"\r
22 #include "DirFileEnum.h"\r
23 //#include "GitConfig.h"\r
24 //#include "GitProperties.h"\r
25 #include "MessageBox.h"\r
26 #include "AppUtils.h"\r
27 #include "PathUtils.h"\r
28 #include "Git.h"\r
29 #include "Registry.h"\r
30 #include "GitStatus.h"\r
31 #include "HistoryDlg.h"\r
32 #include "Hooks.h"\r
33 #include "CommonResource.h"\r
34 #include "UnicodeUtils.h"\r
35 \r
36 #ifdef _DEBUG\r
37 #define new DEBUG_NEW\r
38 #undef THIS_FILE\r
39 static char THIS_FILE[] = __FILE__;\r
40 #endif\r
41 \r
42 UINT CCommitDlg::WM_AUTOLISTREADY = RegisterWindowMessage(_T("TORTOISEGIT_AUTOLISTREADY_MSG"));\r
43 \r
44 IMPLEMENT_DYNAMIC(CCommitDlg, CResizableStandAloneDialog)\r
45 CCommitDlg::CCommitDlg(CWnd* pParent /*=NULL*/)\r
46         : CResizableStandAloneDialog(CCommitDlg::IDD, pParent)\r
47         , m_bRecursive(FALSE)\r
48         , m_bShowUnversioned(FALSE)\r
49         , m_bBlock(FALSE)\r
50         , m_bThreadRunning(FALSE)\r
51         , m_bRunThread(FALSE)\r
52         , m_pThread(NULL)\r
53         , m_bKeepLocks(FALSE)\r
54         , m_bKeepChangeList(TRUE)\r
55         , m_itemsCount(0)\r
56         , m_bSelectFilesForCommit(TRUE)\r
57 {\r
58 }\r
59 \r
60 CCommitDlg::~CCommitDlg()\r
61 {\r
62         if(m_pThread != NULL)\r
63         {\r
64                 delete m_pThread;\r
65         }\r
66 }\r
67 \r
68 void CCommitDlg::DoDataExchange(CDataExchange* pDX)\r
69 {\r
70         CResizableStandAloneDialog::DoDataExchange(pDX);\r
71         DDX_Control(pDX, IDC_FILELIST, m_ListCtrl);\r
72         DDX_Control(pDX, IDC_LOGMESSAGE, m_cLogMessage);\r
73         DDX_Check(pDX, IDC_SHOWUNVERSIONED, m_bShowUnversioned);\r
74         DDX_Control(pDX, IDC_SELECTALL, m_SelectAll);\r
75         DDX_Text(pDX, IDC_BUGID, m_sBugID);\r
76         DDX_Check(pDX, IDC_KEEPLOCK, m_bKeepLocks);\r
77         DDX_Control(pDX, IDC_SPLITTER, m_wndSplitter);\r
78         DDX_Check(pDX, IDC_KEEPLISTS, m_bKeepChangeList);\r
79 }\r
80 \r
81 BEGIN_MESSAGE_MAP(CCommitDlg, CResizableStandAloneDialog)\r
82         ON_BN_CLICKED(IDC_SELECTALL, OnBnClickedSelectall)\r
83         ON_BN_CLICKED(IDHELP, OnBnClickedHelp)\r
84         ON_BN_CLICKED(IDC_SHOWUNVERSIONED, OnBnClickedShowunversioned)\r
85 //      ON_BN_CLICKED(IDC_HISTORY, OnBnClickedHistory)\r
86         ON_BN_CLICKED(IDC_BUGTRAQBUTTON, OnBnClickedBugtraqbutton)\r
87         ON_EN_CHANGE(IDC_LOGMESSAGE, OnEnChangeLogmessage)\r
88         ON_REGISTERED_MESSAGE(CGitStatusListCtrl::SVNSLNM_ITEMCOUNTCHANGED, OnGitStatusListCtrlItemCountChanged)\r
89         ON_REGISTERED_MESSAGE(CGitStatusListCtrl::SVNSLNM_NEEDSREFRESH, OnGitStatusListCtrlNeedsRefresh)\r
90         ON_REGISTERED_MESSAGE(CGitStatusListCtrl::SVNSLNM_ADDFILE, OnFileDropped)\r
91         ON_REGISTERED_MESSAGE(CGitStatusListCtrl::SVNSLNM_CHECKCHANGED, &CCommitDlg::OnGitStatusListCtrlCheckChanged)\r
92         ON_REGISTERED_MESSAGE(WM_AUTOLISTREADY, OnAutoListReady) \r
93         ON_WM_TIMER()\r
94     ON_WM_SIZE()\r
95         ON_STN_CLICKED(IDC_EXTERNALWARNING, &CCommitDlg::OnStnClickedExternalwarning)\r
96         ON_BN_CLICKED(IDC_SIGNOFF, &CCommitDlg::OnBnClickedSignOff)\r
97         ON_STN_CLICKED(IDC_COMMITLABEL, &CCommitDlg::OnStnClickedCommitlabel)\r
98     ON_BN_CLICKED(IDC_COMMIT_AMEND, &CCommitDlg::OnBnClickedCommitAmend)\r
99 END_MESSAGE_MAP()\r
100 \r
101 BOOL CCommitDlg::OnInitDialog()\r
102 {\r
103         CResizableStandAloneDialog::OnInitDialog();\r
104         \r
105         m_regAddBeforeCommit = CRegDWORD(_T("Software\\TortoiseGit\\AddBeforeCommit"), TRUE);\r
106         m_bShowUnversioned = m_regAddBeforeCommit;\r
107 \r
108         m_History.SetMaxHistoryItems((LONG)CRegDWORD(_T("Software\\TortoiseGit\\MaxHistoryItems"), 25));\r
109 \r
110         m_regKeepChangelists = CRegDWORD(_T("Software\\TortoiseGit\\KeepChangeLists"), FALSE);\r
111         m_bKeepChangeList = m_regKeepChangelists;\r
112 \r
113 //      GitConfig config;\r
114 //      m_bKeepLocks = config.KeepLocks();\r
115 \r
116         UpdateData(FALSE);\r
117         \r
118         m_ListCtrl.Init(SVNSLC_COLEXT | SVNSLC_COLSTATUS , _T("CommitDlg"));\r
119         m_ListCtrl.SetSelectButton(&m_SelectAll);\r
120         m_ListCtrl.SetStatLabel(GetDlgItem(IDC_STATISTICS));\r
121         m_ListCtrl.SetCancelBool(&m_bCancelled);\r
122         m_ListCtrl.SetEmptyString(IDS_COMMITDLG_NOTHINGTOCOMMIT);\r
123         m_ListCtrl.EnableFileDrop();\r
124         m_ListCtrl.SetBackgroundImage(IDI_COMMIT_BKG);\r
125         \r
126         this->DialogEnableWindow(IDC_COMMIT_AMEND,FALSE);\r
127 //      m_ProjectProperties.ReadPropsPathList(m_pathList);\r
128         m_cLogMessage.Init(m_ProjectProperties);\r
129         m_cLogMessage.SetFont((CString)CRegString(_T("Software\\TortoiseGit\\LogFontName"), _T("Courier New")), (DWORD)CRegDWORD(_T("Software\\TortoiseGit\\LogFontSize"), 8));\r
130         m_cLogMessage.RegisterContextMenuHandler(this);\r
131 \r
132         OnEnChangeLogmessage();\r
133 \r
134         m_tooltips.Create(this);\r
135         m_tooltips.AddTool(IDC_EXTERNALWARNING, IDS_COMMITDLG_EXTERNALS);\r
136 //      m_tooltips.AddTool(IDC_HISTORY, IDS_COMMITDLG_HISTORY_TT);\r
137         \r
138         m_SelectAll.SetCheck(BST_INDETERMINATE);\r
139 \r
140 #if 0\r
141         CBugTraqAssociations bugtraq_associations;\r
142         bugtraq_associations.Load();\r
143 \r
144         if (bugtraq_associations.FindProvider(m_pathList, &m_bugtraq_association))\r
145         {\r
146                 GetDlgItem(IDC_BUGID)->ShowWindow(SW_HIDE);\r
147                 GetDlgItem(IDC_BUGIDLABEL)->ShowWindow(SW_HIDE);\r
148 \r
149                 CComPtr<IBugTraqProvider> pProvider;\r
150                 HRESULT hr = pProvider.CoCreateInstance(m_bugtraq_association.GetProviderClass());\r
151                 if (SUCCEEDED(hr))\r
152                 {\r
153                         m_BugTraqProvider = pProvider;\r
154                         BSTR temp = NULL;\r
155                         if (SUCCEEDED(hr = pProvider->GetLinkText(GetSafeHwnd(), m_bugtraq_association.GetParameters().AllocSysString(), &temp)))\r
156                         {\r
157                                 SetDlgItemText(IDC_BUGTRAQBUTTON, temp);\r
158                                 GetDlgItem(IDC_BUGTRAQBUTTON)->EnableWindow(TRUE);\r
159                                 GetDlgItem(IDC_BUGTRAQBUTTON)->ShowWindow(SW_SHOW);\r
160                         }\r
161 \r
162                         SysFreeString(temp);\r
163                 }\r
164 \r
165                 GetDlgItem(IDC_LOGMESSAGE)->SetFocus();\r
166         }\r
167         else if (!m_ProjectProperties.sMessage.IsEmpty())\r
168         {\r
169                 GetDlgItem(IDC_BUGID)->ShowWindow(SW_SHOW);\r
170                 GetDlgItem(IDC_BUGIDLABEL)->ShowWindow(SW_SHOW);\r
171                 if (!m_ProjectProperties.sLabel.IsEmpty())\r
172                         SetDlgItemText(IDC_BUGIDLABEL, m_ProjectProperties.sLabel);\r
173                 GetDlgItem(IDC_BUGTRAQBUTTON)->ShowWindow(SW_HIDE);\r
174                 GetDlgItem(IDC_BUGTRAQBUTTON)->EnableWindow(FALSE);\r
175                 GetDlgItem(IDC_BUGID)->SetFocus();\r
176                 CString sBugID = m_ProjectProperties.GetBugIDFromLog(m_sLogMessage);\r
177                 if (!sBugID.IsEmpty())\r
178                 {\r
179                         SetDlgItemText(IDC_BUGID, sBugID);\r
180                 }\r
181         }\r
182         else\r
183 #endif\r
184         {\r
185                 GetDlgItem(IDC_BUGID)->ShowWindow(SW_HIDE);\r
186                 GetDlgItem(IDC_BUGIDLABEL)->ShowWindow(SW_HIDE);\r
187                 GetDlgItem(IDC_BUGTRAQBUTTON)->ShowWindow(SW_HIDE);\r
188                 GetDlgItem(IDC_BUGTRAQBUTTON)->EnableWindow(FALSE);\r
189                 GetDlgItem(IDC_LOGMESSAGE)->SetFocus();\r
190         }\r
191 \r
192         if (!m_sLogMessage.IsEmpty())\r
193                 m_cLogMessage.SetText(m_sLogMessage);\r
194                 \r
195         GetWindowText(m_sWindowTitle);\r
196         \r
197         AdjustControlSize(IDC_SHOWUNVERSIONED);\r
198         AdjustControlSize(IDC_SELECTALL);\r
199         AdjustControlSize(IDC_KEEPLOCK);\r
200 \r
201         GetClientRect(m_DlgOrigRect);\r
202         m_cLogMessage.GetClientRect(m_LogMsgOrigRect);\r
203 \r
204         AddAnchor(IDC_COMMITLABEL, TOP_LEFT, TOP_RIGHT);\r
205         AddAnchor(IDC_BUGIDLABEL, TOP_RIGHT);\r
206         AddAnchor(IDC_BUGID, TOP_RIGHT);\r
207         AddAnchor(IDC_BUGTRAQBUTTON, TOP_RIGHT);\r
208         AddAnchor(IDC_COMMIT_TO, TOP_LEFT, TOP_RIGHT);\r
209         AddAnchor(IDC_MESSAGEGROUP, TOP_LEFT, TOP_RIGHT);\r
210 //      AddAnchor(IDC_HISTORY, TOP_LEFT);\r
211         AddAnchor(IDC_LOGMESSAGE, TOP_LEFT, TOP_RIGHT);\r
212         AddAnchor(IDC_SIGNOFF,   TOP_RIGHT);\r
213         AddAnchor(IDC_LISTGROUP, TOP_LEFT, BOTTOM_RIGHT);\r
214         AddAnchor(IDC_SPLITTER, TOP_LEFT, TOP_RIGHT);\r
215         AddAnchor(IDC_FILELIST, TOP_LEFT, BOTTOM_RIGHT);\r
216         AddAnchor(IDC_SHOWUNVERSIONED, BOTTOM_LEFT);\r
217         AddAnchor(IDC_SELECTALL, BOTTOM_LEFT);\r
218         AddAnchor(IDC_EXTERNALWARNING, BOTTOM_RIGHT);\r
219         AddAnchor(IDC_STATISTICS, BOTTOM_LEFT, BOTTOM_RIGHT);\r
220         AddAnchor(IDC_KEEPLOCK, BOTTOM_LEFT);\r
221         AddAnchor(IDC_KEEPLISTS, BOTTOM_LEFT);\r
222         AddAnchor(IDOK, BOTTOM_RIGHT);\r
223         AddAnchor(IDCANCEL, BOTTOM_RIGHT);\r
224         AddAnchor(IDHELP, BOTTOM_RIGHT);\r
225         AddAnchor(IDC_COMMIT_AMEND,TOP_LEFT);\r
226         \r
227         if (hWndExplorer)\r
228                 CenterWindow(CWnd::FromHandle(hWndExplorer));\r
229         EnableSaveRestore(_T("CommitDlg"));\r
230         DWORD yPos = CRegDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\ResizableState\\CommitDlgSizer"));\r
231         RECT rcDlg, rcLogMsg, rcFileList;\r
232         GetClientRect(&rcDlg);\r
233         m_cLogMessage.GetWindowRect(&rcLogMsg);\r
234         ScreenToClient(&rcLogMsg);\r
235         m_ListCtrl.GetWindowRect(&rcFileList);\r
236         ScreenToClient(&rcFileList);\r
237         if (yPos)\r
238         {\r
239                 RECT rectSplitter;\r
240                 m_wndSplitter.GetWindowRect(&rectSplitter);\r
241                 ScreenToClient(&rectSplitter);\r
242                 int delta = yPos - rectSplitter.top;\r
243                 if ((rcLogMsg.bottom + delta > rcLogMsg.top)&&(rcLogMsg.bottom + delta < rcFileList.bottom - 30))\r
244                 {\r
245                         m_wndSplitter.SetWindowPos(NULL, 0, yPos, 0, 0, SWP_NOSIZE);\r
246                         DoSize(delta);\r
247                 }\r
248         }\r
249 \r
250         // add all directories to the watcher\r
251         for (int i=0; i<m_pathList.GetCount(); ++i)\r
252         {\r
253                 if (m_pathList[i].IsDirectory())\r
254                         m_pathwatcher.AddPath(m_pathList[i]);\r
255         }\r
256 \r
257         m_updatedPathList = m_pathList;\r
258 \r
259         //first start a thread to obtain the file list with the status without\r
260         //blocking the dialog\r
261         InterlockedExchange(&m_bBlock, TRUE);\r
262         m_pThread = AfxBeginThread(StatusThreadEntry, this, THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);\r
263         if (m_pThread==NULL)\r
264         {\r
265                 CMessageBox::Show(this->m_hWnd, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);\r
266                 InterlockedExchange(&m_bBlock, FALSE);\r
267         }\r
268         else\r
269         {\r
270                 m_pThread->m_bAutoDelete = FALSE;\r
271                 m_pThread->ResumeThread();\r
272         }\r
273         CRegDWORD err = CRegDWORD(_T("Software\\TortoiseGit\\ErrorOccurred"), FALSE);\r
274         CRegDWORD historyhint = CRegDWORD(_T("Software\\TortoiseGit\\HistoryHintShown"), FALSE);\r
275         if ((((DWORD)err)!=FALSE)&&((((DWORD)historyhint)==FALSE)))\r
276         {\r
277                 historyhint = TRUE;\r
278 //              ShowBalloon(IDC_HISTORY, IDS_COMMITDLG_HISTORYHINT_TT, IDI_INFORMATION);\r
279         }\r
280         err = FALSE;\r
281 \r
282 \r
283         return FALSE;  // return TRUE unless you set the focus to a control\r
284         // EXCEPTION: OCX Property Pages should return FALSE\r
285 }\r
286 \r
287 void CCommitDlg::OnOK()\r
288 {\r
289         if (m_bBlock)\r
290                 return;\r
291         if (m_bThreadRunning)\r
292         {\r
293                 m_bCancelled = true;\r
294                 InterlockedExchange(&m_bRunThread, FALSE);\r
295                 WaitForSingleObject(m_pThread->m_hThread, 1000);\r
296                 if (m_bThreadRunning)\r
297                 {\r
298                         // we gave the thread a chance to quit. Since the thread didn't\r
299                         // listen to us we have to kill it.\r
300                         TerminateThread(m_pThread->m_hThread, (DWORD)-1);\r
301                         InterlockedExchange(&m_bThreadRunning, FALSE);\r
302                 }\r
303         }\r
304         CString id;\r
305         GetDlgItemText(IDC_BUGID, id);\r
306         if (!m_ProjectProperties.CheckBugID(id))\r
307         {\r
308                 ShowBalloon(IDC_BUGID, IDS_COMMITDLG_ONLYNUMBERS, IDI_EXCLAMATION);\r
309                 return;\r
310         }\r
311         m_sLogMessage = m_cLogMessage.GetText();\r
312         if ((m_ProjectProperties.bWarnIfNoIssue) && (id.IsEmpty() && !m_ProjectProperties.HasBugID(m_sLogMessage)))\r
313         {\r
314                 if (CMessageBox::Show(this->m_hWnd, IDS_COMMITDLG_NOISSUEWARNING, IDS_APPNAME, MB_YESNO | MB_ICONWARNING)!=IDYES)\r
315                         return;\r
316         }\r
317 \r
318 #if 0\r
319         CRegDWORD regUnversionedRecurse (_T("Software\\TortoiseGit\\UnversionedRecurse"), TRUE);\r
320         if (!(DWORD)regUnversionedRecurse)\r
321         {\r
322                 // Find unversioned directories which are marked for commit. The user might expect them\r
323                 // to be added recursively since he cannot the the files. Let's ask the user if he knows\r
324                 // what he is doing.\r
325                 int nListItems = m_ListCtrl.GetItemCount();\r
326                 for (int j=0; j<nListItems; j++)\r
327                 {\r
328                         const CGitStatusListCtrl::FileEntry * entry = m_ListCtrl.GetListEntry(j);\r
329                         if (entry->IsChecked() && (entry->status == Git_wc_status_unversioned) && entry->IsFolder() )\r
330                         {\r
331                                 if (CMessageBox::Show(this->m_hWnd, IDS_COMMITDLG_UNVERSIONEDFOLDERWARNING, IDS_APPNAME, MB_YESNO | MB_ICONWARNING)!=IDYES)\r
332                                         return;\r
333                         }\r
334                 }\r
335         }\r
336 #endif\r
337         m_pathwatcher.Stop();\r
338         InterlockedExchange(&m_bBlock, TRUE);\r
339         CDWordArray arDeleted;\r
340         //first add all the unversioned files the user selected\r
341         //and check if all versioned files are selected\r
342         int nUnchecked = 0;\r
343         int nchecked = 0;\r
344         m_bRecursive = true;\r
345         int nListItems = m_ListCtrl.GetItemCount();\r
346 \r
347         CTGitPathList itemsToAdd;\r
348         CTGitPathList itemsToRemove;\r
349         bool bCheckedInExternal = false;\r
350         bool bHasConflicted = false;\r
351         //std::set<CString> checkedLists;\r
352         //std::set<CString> uncheckedLists;\r
353 \r
354         //CString checkedfiles;\r
355         //CString uncheckedfiles;\r
356 \r
357         CString cmd;\r
358         CString out;\r
359 \r
360         for (int j=0; j<nListItems; j++)\r
361         {\r
362                 //const CGitStatusListCtrl::FileEntry * entry = m_ListCtrl.GetListEntry(j);\r
363                 CTGitPath *entry = (CTGitPath*)m_ListCtrl.GetItemData(j);\r
364                 if (entry->m_Checked)\r
365                 {\r
366 #if 0\r
367                         if (entry->status == Git_wc_status_unversioned)\r
368                         {\r
369                                 itemsToAdd.AddPath(entry->GetPath());\r
370                         }\r
371                         if (entry->status == Git_wc_status_conflicted)\r
372                         {\r
373                                 bHasConflicted = true;\r
374                         }\r
375                         if (entry->status == Git_wc_status_missing)\r
376                         {\r
377                                 itemsToRemove.AddPath(entry->GetPath());\r
378                         }\r
379                         if (entry->status == Git_wc_status_deleted)\r
380                         {\r
381                                 arDeleted.Add(j);\r
382                         }\r
383                         if (entry->IsInExternal())\r
384                         {\r
385                                 bCheckedInExternal = true;\r
386                         }\r
387 #endif\r
388                         cmd.Format(_T("git.exe update-index -- \"%s\""),entry->GetGitPathString());\r
389                         g_Git.Run(cmd,&out,CP_OEMCP);\r
390                         nchecked++;\r
391                         //checkedLists.insert(entry->GetGitPathString());\r
392 //                      checkedfiles += _T("\"")+entry->GetGitPathString()+_T("\" ");\r
393                 }\r
394                 else\r
395                 {\r
396                         //uncheckedLists.insert(entry->GetGitPathString());\r
397                         if(entry->m_Action & CTGitPath::LOGACTIONS_ADDED)\r
398                         {       //To init git repository, there are not HEAD, so we can use git reset command\r
399                                 cmd.Format(_T("git.exe rm --cache -- \"%s\""),entry->GetGitPathString());\r
400                                 g_Git.Run(cmd,&out,CP_OEMCP);   \r
401                         }\r
402                         else\r
403                         {\r
404                                 cmd.Format(_T("git.exe reset -- %s"),entry->GetGitPathString());\r
405                                 g_Git.Run(cmd,&out,CP_OEMCP);\r
406                         }\r
407 \r
408                 //      uncheckedfiles += _T("\"")+entry->GetGitPathString()+_T("\" ");\r
409 #if 0\r
410                         if ((entry->status != Git_wc_status_unversioned)        &&\r
411                                 (entry->status != Git_wc_status_ignored))\r
412                         {\r
413                                 nUnchecked++;\r
414                                 uncheckedLists.insert(entry->GetChangeList());\r
415                                 if (m_bRecursive)\r
416                                 {\r
417                                         // This algorithm is for the sake of simplicity of the complexity O(N?\r
418                                         for (int k=0; k<nListItems; k++)\r
419                                         {\r
420                                                 const CGitStatusListCtrl::FileEntry * entryK = m_ListCtrl.GetListEntry(k);\r
421                                                 if (entryK->IsChecked() && entryK->GetPath().IsAncestorOf(entry->GetPath())  )\r
422                                                 {\r
423                                                         // Fall back to a non-recursive commit to prevent items being\r
424                                                         // committed which aren't checked although its parent is checked\r
425                                                         // (property change, directory deletion, ... )\r
426                                                         m_bRecursive = false;\r
427                                                         break;\r
428                                                 }\r
429                                         }\r
430                                 }\r
431                         }\r
432 #endif\r
433                 }\r
434         }\r
435 \r
436         //if(uncheckedfiles.GetLength()>0)\r
437         //{\r
438         //      cmd.Format(_T("git.exe reset -- %s"),uncheckedfiles);\r
439         //      g_Git.Run(cmd,&out);\r
440         //}\r
441 \r
442         //if(checkedfiles.GetLength()>0)\r
443         if(nchecked)\r
444         {\r
445         //      cmd.Format(_T("git.exe update-index -- %s"),checkedfiles);\r
446         //      g_Git.Run(cmd,&out);\r
447 \r
448                 CString tempfile=::GetTempFile();\r
449                 CFile file(tempfile,CFile::modeReadWrite|CFile::modeCreate );\r
450                 CStringA log=CUnicodeUtils::GetUTF8( m_sLogMessage);\r
451                 file.Write(log,log.GetLength());\r
452                 //file.WriteString(m_sLogMessage);\r
453                 file.Close();\r
454         \r
455                 out =_T("");\r
456                 cmd.Format(_T("git.exe commit -F \"%s\""), tempfile);\r
457                 g_Git.Run(cmd,&out,CP_OEMCP);\r
458         \r
459                 CFile::Remove(tempfile);\r
460 \r
461                 CMessageBox::Show(this->m_hWnd, out, _T("Commit Finish"), MB_OK | MB_ICONINFORMATION);\r
462         }else\r
463                 CMessageBox::Show(this->m_hWnd, _T("Nothing Commit"), _T("Commit Finish"), MB_OK | MB_ICONINFORMATION);\r
464 #if 0\r
465         if (m_pathwatcher.GetNumberOfChangedPaths() && m_bRecursive)\r
466         {\r
467                 // There are paths which got changed (touched at least).\r
468                 // We have to find out if this affects the selection in the commit dialog\r
469                 // If it could affect the selection, revert back to a non-recursive commit\r
470                 CTGitPathList changedList = m_pathwatcher.GetChangedPaths();\r
471                 changedList.RemoveDuplicates();\r
472                 for (int i=0; i<changedList.GetCount(); ++i)\r
473                 {\r
474                         if (changedList[i].IsAdminDir())\r
475                         {\r
476                                 // something inside an admin dir was changed.\r
477                                 // if it's the entries file, then we have to fully refresh because\r
478                                 // files may have been added/removed from version control\r
479                                 if ((changedList[i].GetWinPathString().Right(7).CompareNoCase(_T("entries")) == 0) &&\r
480                                         (changedList[i].GetWinPathString().Find(_T("\\tmp\\"))<0))\r
481                                 {\r
482                                         m_bRecursive = false;\r
483                                         break;\r
484                                 }\r
485                         }\r
486                         else if (!m_ListCtrl.IsPathShown(changedList[i]))\r
487                         {\r
488                                 // a path which is not shown in the list has changed\r
489                                 CGitStatusListCtrl::FileEntry * entry = m_ListCtrl.GetListEntry(changedList[i]);\r
490                                 if (entry)\r
491                                 {\r
492                                         // check if the changed path would get committed by a recursive commit\r
493                                         if ((!entry->IsFromDifferentRepository()) &&\r
494                                                 (!entry->IsInExternal()) &&\r
495                                                 (!entry->IsNested()) && \r
496                                                 (!entry->IsChecked()))\r
497                                         {\r
498                                                 m_bRecursive = false;\r
499                                                 break;\r
500                                         }\r
501                                 }\r
502                         }\r
503                 }\r
504         }\r
505 \r
506 \r
507         // Now, do all the adds - make sure that the list is sorted so that parents \r
508         // are added before their children\r
509         itemsToAdd.SortByPathname();\r
510         Git Git;\r
511         if (!Git.Add(itemsToAdd, &m_ProjectProperties, Git_depth_empty, FALSE, FALSE, TRUE))\r
512         {\r
513                 CMessageBox::Show(m_hWnd, Git.GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR);\r
514                 InterlockedExchange(&m_bBlock, FALSE);\r
515                 Refresh();\r
516                 return;\r
517         }\r
518 \r
519         // Remove any missing items\r
520         // Not sure that this sort is really necessary - indeed, it might be better to do a reverse sort at this point\r
521         itemsToRemove.SortByPathname();\r
522         Git.Remove(itemsToRemove, TRUE);\r
523 \r
524         //the next step: find all deleted files and check if they're \r
525         //inside a deleted folder. If that's the case, then remove those\r
526         //files from the list since they'll get deleted by the parent\r
527         //folder automatically.\r
528         m_ListCtrl.Block(TRUE, FALSE);\r
529         INT_PTR nDeleted = arDeleted.GetCount();\r
530         for (INT_PTR i=0; i<arDeleted.GetCount(); i++)\r
531         {\r
532                 if (m_ListCtrl.GetCheck(arDeleted.GetAt(i)))\r
533                 {\r
534                         const CTGitPath& path = m_ListCtrl.GetListEntry(arDeleted.GetAt(i))->GetPath();\r
535                         if (path.IsDirectory())\r
536                         {\r
537                                 //now find all children of this directory\r
538                                 for (int j=0; j<arDeleted.GetCount(); j++)\r
539                                 {\r
540                                         if (i!=j)\r
541                                         {\r
542                                                 CGitStatusListCtrl::FileEntry* childEntry = m_ListCtrl.GetListEntry(arDeleted.GetAt(j));\r
543                                                 if (childEntry->IsChecked())\r
544                                                 {\r
545                                                         if (path.IsAncestorOf(childEntry->GetPath()))\r
546                                                         {\r
547                                                                 m_ListCtrl.SetEntryCheck(childEntry, arDeleted.GetAt(j), false);\r
548                                                                 nDeleted--;\r
549                                                         }\r
550                                                 }\r
551                                         }\r
552                                 }\r
553                         }\r
554                 }\r
555         } \r
556         m_ListCtrl.Block(FALSE, FALSE);\r
557 \r
558         if ((nUnchecked != 0)||(bCheckedInExternal)||(bHasConflicted)||(!m_bRecursive))\r
559         {\r
560                 //save only the files the user has checked into the temporary file\r
561                 m_ListCtrl.WriteCheckedNamesToPathList(m_pathList);\r
562         }\r
563         m_ListCtrl.WriteCheckedNamesToPathList(m_selectedPathList);\r
564         // the item count is used in the progress dialog to show the overall commit\r
565         // progress.\r
566         // deleted items only send one notification event, all others send two\r
567         m_itemsCount = ((m_selectedPathList.GetCount() - nDeleted - itemsToRemove.GetCount()) * 2) + nDeleted + itemsToRemove.GetCount();\r
568 \r
569         if ((m_bRecursive)&&(checkedLists.size() == 1))\r
570         {\r
571                 // all checked items belong to the same changelist\r
572                 // find out if there are any unchecked items which belong to that changelist\r
573                 if (uncheckedLists.find(*checkedLists.begin()) == uncheckedLists.end())\r
574                         m_sChangeList = *checkedLists.begin();\r
575         }\r
576 #endif\r
577         UpdateData();\r
578         m_regAddBeforeCommit = m_bShowUnversioned;\r
579         if (!GetDlgItem(IDC_KEEPLOCK)->IsWindowEnabled())\r
580                 m_bKeepLocks = FALSE;\r
581         m_regKeepChangelists = m_bKeepChangeList;\r
582         if (!GetDlgItem(IDC_KEEPLISTS)->IsWindowEnabled())\r
583                 m_bKeepChangeList = FALSE;\r
584         InterlockedExchange(&m_bBlock, FALSE);\r
585         m_sBugID.Trim();\r
586         if (!m_sBugID.IsEmpty())\r
587         {\r
588                 m_sBugID.Replace(_T(", "), _T(","));\r
589                 m_sBugID.Replace(_T(" ,"), _T(","));\r
590                 CString sBugID = m_ProjectProperties.sMessage;\r
591                 sBugID.Replace(_T("%BUGID%"), m_sBugID);\r
592                 if (m_ProjectProperties.bAppend)\r
593                         m_sLogMessage += _T("\n") + sBugID + _T("\n");\r
594                 else\r
595                         m_sLogMessage = sBugID + _T("\n") + m_sLogMessage;\r
596         }\r
597         m_History.AddEntry(m_sLogMessage);\r
598         m_History.Save();\r
599 \r
600         SaveSplitterPos();\r
601 \r
602         CResizableStandAloneDialog::OnOK();\r
603 }\r
604 \r
605 void CCommitDlg::SaveSplitterPos()\r
606 {\r
607         if (!IsIconic())\r
608         {\r
609                 CRegDWORD regPos = CRegDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\ResizableState\\CommitDlgSizer"));\r
610                 RECT rectSplitter;\r
611                 m_wndSplitter.GetWindowRect(&rectSplitter);\r
612                 ScreenToClient(&rectSplitter);\r
613                 regPos = rectSplitter.top;\r
614         }\r
615 }\r
616 \r
617 UINT CCommitDlg::StatusThreadEntry(LPVOID pVoid)\r
618 {\r
619         return ((CCommitDlg*)pVoid)->StatusThread();\r
620 }\r
621 \r
622 UINT CCommitDlg::StatusThread()\r
623 {\r
624         //get the status of all selected file/folders recursively\r
625         //and show the ones which have to be committed to the user\r
626         //in a list control. \r
627         InterlockedExchange(&m_bBlock, TRUE);\r
628         InterlockedExchange(&m_bThreadRunning, TRUE);// so the main thread knows that this thread is still running\r
629         InterlockedExchange(&m_bRunThread, TRUE);       // if this is set to FALSE, the thread should stop\r
630         m_bCancelled = false;\r
631 \r
632         DialogEnableWindow(IDOK, false);\r
633         DialogEnableWindow(IDC_SHOWUNVERSIONED, false);\r
634         DialogEnableWindow(IDC_SELECTALL, false);\r
635         GetDlgItem(IDC_EXTERNALWARNING)->ShowWindow(SW_HIDE);\r
636         DialogEnableWindow(IDC_EXTERNALWARNING, false);\r
637     // read the list of recent log entries before querying the WC for status\r
638     // -> the user may select one and modify / update it while we are crawling the WC\r
639 #if 0\r
640         if (m_History.GetCount()==0)\r
641         {\r
642                 CString reg;\r
643                 if (m_ListCtrl.m_sUUID.IsEmpty() && m_pathList.GetCount()>0)\r
644                 {\r
645                         Git Git;\r
646                         reg.Format(_T("Software\\TortoiseGit\\History\\commit%s"), (LPCTSTR)Git.GetUUIDFromPath(m_pathList[0]));\r
647                 }\r
648                 else\r
649                         reg.Format(_T("Software\\TortoiseGit\\History\\commit%s"), (LPCTSTR)m_ListCtrl.m_sUUID);\r
650                 m_History.Load(reg, _T("logmsgs"));\r
651         }\r
652 #endif\r
653     // Initialise the list control with the status of the files/folders below us\r
654         BOOL success = m_ListCtrl.GetStatus(m_pathList);\r
655 \r
656         //m_ListCtrl.UpdateFileList(git_revnum_t(GIT_REV_ZERO));\r
657         if(this->m_bShowUnversioned)\r
658                 m_ListCtrl.UpdateFileList(CGitStatusListCtrl::FILELIST_UNVER);\r
659         \r
660         m_ListCtrl.CheckIfChangelistsArePresent(false);\r
661 \r
662         DWORD dwShow = SVNSLC_SHOWVERSIONEDBUTNORMALANDEXTERNALSFROMDIFFERENTREPOS | SVNSLC_SHOWLOCKS | SVNSLC_SHOWINCHANGELIST;\r
663         dwShow |= DWORD(m_regAddBeforeCommit) ? SVNSLC_SHOWUNVERSIONED : 0;\r
664         if (success)\r
665         {\r
666                 if (m_checkedPathList.GetCount())\r
667                         m_ListCtrl.Show(dwShow, m_checkedPathList);\r
668                 else\r
669                 {\r
670                         DWORD dwCheck = m_bSelectFilesForCommit ? dwShow : 0;\r
671                         m_ListCtrl.Show(dwShow, dwCheck);\r
672                         m_bSelectFilesForCommit = true;\r
673                 }\r
674 \r
675                 if (m_ListCtrl.HasExternalsFromDifferentRepos())\r
676                 {\r
677                         GetDlgItem(IDC_EXTERNALWARNING)->ShowWindow(SW_SHOW);\r
678                         DialogEnableWindow(IDC_EXTERNALWARNING, TRUE);\r
679                 }\r
680                 \r
681                 SetDlgItemText(IDC_COMMIT_TO, g_Git.GetCurrentBranch());\r
682                 m_tooltips.AddTool(GetDlgItem(IDC_STATISTICS), m_ListCtrl.GetStatisticsString());\r
683         }\r
684         CString logmsg;\r
685         GetDlgItemText(IDC_LOGMESSAGE, logmsg);\r
686         DialogEnableWindow(IDOK, logmsg.GetLength() >= m_ProjectProperties.nMinLogSize);\r
687         if (!success)\r
688         {\r
689                 if (!m_ListCtrl.GetLastErrorMessage().IsEmpty())\r
690                         m_ListCtrl.SetEmptyString(m_ListCtrl.GetLastErrorMessage());\r
691                 m_ListCtrl.Show(dwShow);\r
692         }\r
693         if ((m_ListCtrl.GetItemCount()==0)&&(m_ListCtrl.HasUnversionedItems()))\r
694         {\r
695                 if (CMessageBox::Show(m_hWnd, IDS_COMMITDLG_NOTHINGTOCOMMITUNVERSIONED, IDS_APPNAME, MB_ICONINFORMATION | MB_YESNO)==IDYES)\r
696                 {\r
697                         m_bShowUnversioned = TRUE;\r
698                         GetDlgItem(IDC_SHOWUNVERSIONED)->SendMessage(BM_SETCHECK, BST_CHECKED);\r
699                         DWORD dwShow = SVNSLC_SHOWVERSIONEDBUTNORMALANDEXTERNALSFROMDIFFERENTREPOS | SVNSLC_SHOWUNVERSIONED | SVNSLC_SHOWLOCKS;\r
700                         m_ListCtrl.Show(dwShow);\r
701                 }\r
702         }\r
703 \r
704         CTGitPath commonDir = m_ListCtrl.GetCommonDirectory(false);\r
705         SetWindowText(m_sWindowTitle + _T(" - ") + commonDir.GetWinPathString());\r
706 \r
707         m_autolist.clear();\r
708         // we don't have to block the commit dialog while we fetch the\r
709         // auto completion list.\r
710         m_pathwatcher.ClearChangedPaths();\r
711         InterlockedExchange(&m_bBlock, FALSE);\r
712         if ((DWORD)CRegDWORD(_T("Software\\TortoiseGit\\Autocompletion"), TRUE)==TRUE)\r
713         {\r
714                 m_ListCtrl.Block(TRUE, TRUE);\r
715                 GetAutocompletionList();\r
716                 m_ListCtrl.Block(FALSE, FALSE);\r
717         }\r
718         if (m_bRunThread)\r
719         {\r
720                 DialogEnableWindow(IDC_SHOWUNVERSIONED, true);\r
721                 DialogEnableWindow(IDC_SELECTALL, true);\r
722                 if (m_ListCtrl.HasChangeLists())\r
723                         DialogEnableWindow(IDC_KEEPLISTS, true);\r
724                 if (m_ListCtrl.HasLocks())\r
725                         DialogEnableWindow(IDC_KEEPLOCK, true);\r
726                 // we have the list, now signal the main thread about it\r
727                 SendMessage(WM_AUTOLISTREADY);  // only send the message if the thread wasn't told to quit!\r
728         }\r
729 \r
730         InterlockedExchange(&m_bRunThread, FALSE);\r
731         InterlockedExchange(&m_bThreadRunning, FALSE);\r
732         // force the cursor to normal\r
733         RefreshCursor();\r
734 \r
735         return 0;\r
736 }\r
737 \r
738 void CCommitDlg::OnCancel()\r
739 {\r
740         m_bCancelled = true;\r
741         if (m_bBlock)\r
742                 return;\r
743         m_pathwatcher.Stop();\r
744         if (m_bThreadRunning)\r
745         {\r
746                 InterlockedExchange(&m_bRunThread, FALSE);\r
747                 WaitForSingleObject(m_pThread->m_hThread, 1000);\r
748                 if (m_bThreadRunning)\r
749                 {\r
750                         // we gave the thread a chance to quit. Since the thread didn't\r
751                         // listen to us we have to kill it.\r
752                         TerminateThread(m_pThread->m_hThread, (DWORD)-1);\r
753                         InterlockedExchange(&m_bThreadRunning, FALSE);\r
754                 }\r
755         }\r
756         UpdateData();\r
757         m_sBugID.Trim();\r
758         m_sLogMessage = m_cLogMessage.GetText();\r
759         if (!m_sBugID.IsEmpty())\r
760         {\r
761                 m_sBugID.Replace(_T(", "), _T(","));\r
762                 m_sBugID.Replace(_T(" ,"), _T(","));\r
763                 CString sBugID = m_ProjectProperties.sMessage;\r
764                 sBugID.Replace(_T("%BUGID%"), m_sBugID);\r
765                 if (m_ProjectProperties.bAppend)\r
766                         m_sLogMessage += _T("\n") + sBugID + _T("\n");\r
767                 else\r
768                         m_sLogMessage = sBugID + _T("\n") + m_sLogMessage;\r
769         }\r
770         if (m_ProjectProperties.sLogTemplate.Compare(m_sLogMessage) != 0)\r
771                 m_History.AddEntry(m_sLogMessage);\r
772         m_History.Save();\r
773         SaveSplitterPos();\r
774         CResizableStandAloneDialog::OnCancel();\r
775 }\r
776 \r
777 void CCommitDlg::OnBnClickedSelectall()\r
778 {\r
779         m_tooltips.Pop();       // hide the tooltips\r
780         UINT state = (m_SelectAll.GetState() & 0x0003);\r
781         if (state == BST_INDETERMINATE)\r
782         {\r
783                 // It is not at all useful to manually place the checkbox into the indeterminate state...\r
784                 // We will force this on to the unchecked state\r
785                 state = BST_UNCHECKED;\r
786                 m_SelectAll.SetCheck(state);\r
787         }\r
788         m_ListCtrl.SelectAll(state == BST_CHECKED);\r
789 }\r
790 \r
791 BOOL CCommitDlg::PreTranslateMessage(MSG* pMsg)\r
792 {\r
793         if (!m_bBlock)\r
794                 m_tooltips.RelayEvent(pMsg);\r
795         if (pMsg->message == WM_KEYDOWN)\r
796         {\r
797                 switch (pMsg->wParam)\r
798                 {\r
799                 case VK_F5:\r
800                         {\r
801                                 if (m_bBlock)\r
802                                         return CResizableStandAloneDialog::PreTranslateMessage(pMsg);\r
803                                 Refresh();\r
804                         }\r
805                         break;\r
806                 case VK_RETURN:\r
807                         {\r
808                                 if (GetAsyncKeyState(VK_CONTROL)&0x8000)\r
809                                 {\r
810                                         if ( GetDlgItem(IDOK)->IsWindowEnabled() )\r
811                                         {\r
812                                                 PostMessage(WM_COMMAND, IDOK);\r
813                                         }\r
814                                         return TRUE;\r
815                                 }\r
816                                 if ( GetFocus()==GetDlgItem(IDC_BUGID) )\r
817                                 {\r
818                                         // Pressing RETURN in the bug id control\r
819                                         // moves the focus to the message\r
820                                         GetDlgItem(IDC_LOGMESSAGE)->SetFocus();\r
821                                         return TRUE;\r
822                                 }\r
823                         }\r
824                         break;\r
825                 }\r
826         }\r
827 \r
828         return CResizableStandAloneDialog::PreTranslateMessage(pMsg);\r
829 }\r
830 \r
831 void CCommitDlg::Refresh()\r
832 {\r
833         if (m_bThreadRunning)\r
834                 return;\r
835 \r
836         InterlockedExchange(&m_bBlock, TRUE);\r
837         m_pThread = AfxBeginThread(StatusThreadEntry, this, THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);\r
838         if (m_pThread==NULL)\r
839         {\r
840                 CMessageBox::Show(this->m_hWnd, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);\r
841                 InterlockedExchange(&m_bBlock, FALSE);\r
842         }\r
843         else\r
844         {\r
845                 m_pThread->m_bAutoDelete = FALSE;\r
846                 m_pThread->ResumeThread();\r
847         }\r
848 }\r
849 \r
850 void CCommitDlg::OnBnClickedHelp()\r
851 {\r
852         OnHelp();\r
853 }\r
854 \r
855 void CCommitDlg::OnBnClickedShowunversioned()\r
856 {\r
857         m_tooltips.Pop();       // hide the tooltips\r
858         UpdateData();\r
859         m_regAddBeforeCommit = m_bShowUnversioned;\r
860         if (!m_bBlock)\r
861         {\r
862                 DWORD dwShow = m_ListCtrl.GetShowFlags();\r
863                 if (DWORD(m_regAddBeforeCommit))\r
864                         dwShow |= SVNSLC_SHOWUNVERSIONED;\r
865                 else\r
866                         dwShow &= ~SVNSLC_SHOWUNVERSIONED;\r
867                 if(dwShow & SVNSLC_SHOWUNVERSIONED)\r
868                 {\r
869                         m_ListCtrl.GetStatus(this->m_pathList,false,false,true);\r
870                 }\r
871                 m_ListCtrl.Show(dwShow);\r
872         }\r
873 }\r
874 \r
875 void CCommitDlg::OnStnClickedExternalwarning()\r
876 {\r
877         m_tooltips.Popup();\r
878 }\r
879 \r
880 void CCommitDlg::OnEnChangeLogmessage()\r
881 {\r
882         UpdateOKButton();\r
883 }\r
884 \r
885 LRESULT CCommitDlg::OnGitStatusListCtrlItemCountChanged(WPARAM, LPARAM)\r
886 {\r
887 #if 0\r
888         if ((m_ListCtrl.GetItemCount() == 0)&&(m_ListCtrl.HasUnversionedItems())&&(!m_bShowUnversioned))\r
889         {\r
890                 if (CMessageBox::Show(*this, IDS_COMMITDLG_NOTHINGTOCOMMITUNVERSIONED, IDS_APPNAME, MB_ICONINFORMATION | MB_YESNO)==IDYES)\r
891                 {\r
892                         m_bShowUnversioned = TRUE;\r
893                         DWORD dwShow = GitSLC_SHOWVERSIONEDBUTNORMALANDEXTERNALSFROMDIFFERENTREPOS | GitSLC_SHOWUNVERSIONED | GitSLC_SHOWLOCKS;\r
894                         m_ListCtrl.Show(dwShow);\r
895                         UpdateData(FALSE);\r
896                 }\r
897         }\r
898 #endif\r
899         return 0;\r
900 }\r
901 \r
902 LRESULT CCommitDlg::OnGitStatusListCtrlNeedsRefresh(WPARAM, LPARAM)\r
903 {\r
904         Refresh();\r
905         return 0;\r
906 }\r
907 \r
908 LRESULT CCommitDlg::OnFileDropped(WPARAM, LPARAM lParam)\r
909 {\r
910 #if 0\r
911         BringWindowToTop();\r
912         SetForegroundWindow();\r
913         SetActiveWindow();\r
914         // if multiple files/folders are dropped\r
915         // this handler is called for every single item\r
916         // separately.\r
917         // To avoid creating multiple refresh threads and\r
918         // causing crashes, we only add the items to the\r
919         // list control and start a timer.\r
920         // When the timer expires, we start the refresh thread,\r
921         // but only if it isn't already running - otherwise we\r
922         // restart the timer.\r
923         CTGitPath path;\r
924         path.SetFromWin((LPCTSTR)lParam);\r
925 \r
926         // just add all the items we get here.\r
927         // if the item is versioned, the add will fail but nothing\r
928         // more will happen.\r
929         Git Git;\r
930         Git.Add(CTGitPathList(path), &m_ProjectProperties, Git_depth_empty, false, true, true);\r
931 \r
932         if (!m_ListCtrl.HasPath(path))\r
933         {\r
934                 if (m_pathList.AreAllPathsFiles())\r
935                 {\r
936                         m_pathList.AddPath(path);\r
937                         m_pathList.RemoveDuplicates();\r
938                         m_updatedPathList.AddPath(path);\r
939                         m_updatedPathList.RemoveDuplicates();\r
940                 }\r
941                 else\r
942                 {\r
943                         // if the path list contains folders, we have to check whether\r
944                         // our just (maybe) added path is a child of one of those. If it is\r
945                         // a child of a folder already in the list, we must not add it. Otherwise\r
946                         // that path could show up twice in the list.\r
947                         bool bHasParentInList = false;\r
948                         for (int i=0; i<m_pathList.GetCount(); ++i)\r
949                         {\r
950                                 if (m_pathList[i].IsAncestorOf(path))\r
951                                 {\r
952                                         bHasParentInList = true;\r
953                                         break;\r
954                                 }\r
955                         }\r
956                         if (!bHasParentInList)\r
957                         {\r
958                                 m_pathList.AddPath(path);\r
959                                 m_pathList.RemoveDuplicates();\r
960                                 m_updatedPathList.AddPath(path);\r
961                                 m_updatedPathList.RemoveDuplicates();\r
962                         }\r
963                 }\r
964         }\r
965         \r
966         // Always start the timer, since the status of an existing item might have changed\r
967         SetTimer(REFRESHTIMER, 200, NULL);\r
968         ATLTRACE(_T("Item %s dropped, timer started\n"), path.GetWinPath());\r
969 #endif\r
970         return 0;\r
971 }\r
972 \r
973 LRESULT CCommitDlg::OnAutoListReady(WPARAM, LPARAM)\r
974 {\r
975         m_cLogMessage.SetAutoCompletionList(m_autolist, '*');\r
976         return 0;\r
977 }\r
978 \r
979 //////////////////////////////////////////////////////////////////////////\r
980 // functions which run in the status thread\r
981 //////////////////////////////////////////////////////////////////////////\r
982 \r
983 void CCommitDlg::ParseRegexFile(const CString& sFile, std::map<CString, CString>& mapRegex)\r
984 {\r
985         CString strLine;\r
986         try\r
987         {\r
988                 CStdioFile file(sFile, CFile::typeText | CFile::modeRead | CFile::shareDenyWrite);\r
989                 while (m_bRunThread && file.ReadString(strLine))\r
990                 {\r
991                         int eqpos = strLine.Find('=');\r
992                         CString rgx;\r
993                         rgx = strLine.Mid(eqpos+1).Trim();\r
994 \r
995                         int pos = -1;\r
996                         while (((pos = strLine.Find(','))>=0)&&(pos < eqpos))\r
997                         {\r
998                                 mapRegex[strLine.Left(pos)] = rgx;\r
999                                 strLine = strLine.Mid(pos+1).Trim();\r
1000                         }\r
1001                         mapRegex[strLine.Left(strLine.Find('=')).Trim()] = rgx;\r
1002                 }\r
1003                 file.Close();\r
1004         }\r
1005         catch (CFileException* pE)\r
1006         {\r
1007                 TRACE("CFileException loading auto list regex file\n");\r
1008                 pE->Delete();\r
1009                 return;\r
1010         }\r
1011 }\r
1012 void CCommitDlg::GetAutocompletionList()\r
1013 {\r
1014         // the auto completion list is made of strings from each selected files.\r
1015         // the strings used are extracted from the files with regexes found\r
1016         // in the file "autolist.txt".\r
1017         // the format of that file is:\r
1018         // file extensions separated with commas '=' regular expression to use\r
1019         // example:\r
1020         // .h, .hpp = (?<=class[\s])\b\w+\b|(\b\w+(?=[\s ]?\(\);))\r
1021         // .cpp = (?<=[^\s]::)\b\w+\b\r
1022         \r
1023         std::map<CString, CString> mapRegex;\r
1024         CString sRegexFile = CPathUtils::GetAppDirectory();\r
1025         CRegDWORD regtimeout = CRegDWORD(_T("Software\\TortoiseGit\\AutocompleteParseTimeout"), 5);\r
1026         DWORD timeoutvalue = regtimeout*1000;\r
1027         sRegexFile += _T("autolist.txt");\r
1028         if (!m_bRunThread)\r
1029                 return;\r
1030         ParseRegexFile(sRegexFile, mapRegex);\r
1031         SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, sRegexFile.GetBuffer(MAX_PATH+1));\r
1032         sRegexFile.ReleaseBuffer();\r
1033         sRegexFile += _T("\\TortoiseGit\\autolist.txt");\r
1034         if (PathFileExists(sRegexFile))\r
1035         {\r
1036                 ParseRegexFile(sRegexFile, mapRegex);\r
1037         }\r
1038         DWORD starttime = GetTickCount();\r
1039 \r
1040         // now we have two arrays of strings, where the first array contains all\r
1041         // file extensions we can use and the second the corresponding regex strings\r
1042         // to apply to those files.\r
1043 \r
1044         // the next step is to go over all files shown in the commit dialog\r
1045         // and scan them for strings we can use\r
1046         int nListItems = m_ListCtrl.GetItemCount();\r
1047 \r
1048         for (int i=0; i<nListItems && m_bRunThread; ++i)\r
1049         {\r
1050                 // stop parsing after timeout\r
1051                 if ((!m_bRunThread) || (GetTickCount() - starttime > timeoutvalue))\r
1052                         return;\r
1053 \r
1054                 CTGitPath *path = (CTGitPath*)m_ListCtrl.GetItemData(i);\r
1055 \r
1056                 if(path == NULL)\r
1057                         continue;\r
1058 \r
1059                 CString sPartPath =path->GetGitPathString();\r
1060                 m_autolist.insert(sPartPath);\r
1061 \r
1062 //              const CGitStatusListCtrl::FileEntry * entry = m_ListCtrl.GetListEntry(i);\r
1063 //              if (!entry)\r
1064 //                      continue;\r
1065                 \r
1066                 // add the path parts to the auto completion list too\r
1067 //              CString sPartPath = entry->GetRelativeGitPath();\r
1068 //              m_autolist.insert(sPartPath);\r
1069 \r
1070 \r
1071                 int pos = 0;\r
1072                 int lastPos = 0;\r
1073                 while ((pos = sPartPath.Find('/', pos)) >= 0)\r
1074                 {\r
1075                         pos++;\r
1076                         lastPos = pos;\r
1077                         m_autolist.insert(sPartPath.Mid(pos));\r
1078                 }\r
1079 \r
1080                 // Last inserted entry is a file name.\r
1081                 // Some users prefer to also list file name without extension.\r
1082                 if (CRegDWORD(_T("Software\\TortoiseGit\\AutocompleteRemovesExtensions"), FALSE))\r
1083                 {\r
1084                         int dotPos = sPartPath.ReverseFind('.');\r
1085                         if ((dotPos >= 0) && (dotPos > lastPos))\r
1086                                 m_autolist.insert(sPartPath.Mid(lastPos, dotPos - lastPos));\r
1087                 }\r
1088 #if 0\r
1089                 if ((entry->status <= Git_wc_status_normal)||(entry->status == Git_wc_status_ignored))\r
1090                         continue;\r
1091 \r
1092                 CString sExt = entry->GetPath().GetFileExtension();\r
1093                 sExt.MakeLower();\r
1094                 // find the regex string which corresponds to the file extension\r
1095                 CString rdata = mapRegex[sExt];\r
1096                 if (rdata.IsEmpty())\r
1097                         continue;\r
1098 \r
1099                 ScanFile(entry->GetPath().GetWinPathString(), rdata);\r
1100                 if ((entry->textstatus != Git_wc_status_unversioned) &&\r
1101                         (entry->textstatus != Git_wc_status_none) &&\r
1102                         (entry->textstatus != Git_wc_status_ignored) &&\r
1103                         (entry->textstatus != Git_wc_status_added) &&\r
1104                         (entry->textstatus != Git_wc_status_normal))\r
1105                 {\r
1106                         CTGitPath basePath = Git::GetPristinePath(entry->GetPath());\r
1107                         if (!basePath.IsEmpty())\r
1108                                 ScanFile(basePath.GetWinPathString(), rdata);\r
1109                 }\r
1110 #endif\r
1111         }\r
1112         ATLTRACE(_T("Auto completion list loaded in %d msec\n"), GetTickCount() - starttime);\r
1113 }\r
1114 \r
1115 void CCommitDlg::ScanFile(const CString& sFilePath, const CString& sRegex)\r
1116 {\r
1117         wstring sFileContent;\r
1118         HANDLE hFile = CreateFile(sFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);\r
1119         if (hFile != INVALID_HANDLE_VALUE)\r
1120         {\r
1121                 DWORD size = GetFileSize(hFile, NULL);\r
1122                 if (size > 1000000L)\r
1123                 {\r
1124                         // no files bigger than 1 Meg\r
1125                         CloseHandle(hFile);\r
1126                         return;\r
1127                 }\r
1128                 // allocate memory to hold file contents\r
1129                 char * buffer = new char[size];\r
1130                 DWORD readbytes;\r
1131                 ReadFile(hFile, buffer, size, &readbytes, NULL);\r
1132                 CloseHandle(hFile);\r
1133                 int opts = 0;\r
1134                 IsTextUnicode(buffer, readbytes, &opts);\r
1135                 if (opts & IS_TEXT_UNICODE_NULL_BYTES)\r
1136                 {\r
1137                         delete [] buffer;\r
1138                         return;\r
1139                 }\r
1140                 if (opts & IS_TEXT_UNICODE_UNICODE_MASK)\r
1141                 {\r
1142                         sFileContent = wstring((wchar_t*)buffer, readbytes/sizeof(WCHAR));\r
1143                 }\r
1144                 if ((opts & IS_TEXT_UNICODE_NOT_UNICODE_MASK)||(opts == 0))\r
1145                 {\r
1146                         int ret = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (LPCSTR)buffer, readbytes, NULL, 0);\r
1147                         wchar_t * pWideBuf = new wchar_t[ret];\r
1148                         int ret2 = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (LPCSTR)buffer, readbytes, pWideBuf, ret);\r
1149                         if (ret2 == ret)\r
1150                                 sFileContent = wstring(pWideBuf, ret);\r
1151                         delete [] pWideBuf;\r
1152                 }\r
1153                 delete [] buffer;\r
1154         }\r
1155         if (sFileContent.empty()|| !m_bRunThread)\r
1156         {\r
1157                 return;\r
1158         }\r
1159 \r
1160         try\r
1161         {\r
1162                 const tr1::wregex regCheck(sRegex, tr1::regex_constants::icase | tr1::regex_constants::ECMAScript);\r
1163                 const tr1::wsregex_iterator end;\r
1164                 wstring s = sFileContent;\r
1165                 for (tr1::wsregex_iterator it(s.begin(), s.end(), regCheck); it != end; ++it)\r
1166                 {\r
1167                         const tr1::wsmatch match = *it;\r
1168                         for (size_t i=1; i<match.size(); ++i)\r
1169                         {\r
1170                                 if (match[i].second-match[i].first)\r
1171                                 {\r
1172                                         ATLTRACE(_T("matched keyword : %s\n"), wstring(match[i]).c_str());\r
1173                                         m_autolist.insert(wstring(match[i]).c_str());\r
1174                                 }\r
1175                         }\r
1176                 }\r
1177         }\r
1178         catch (exception) {}\r
1179 }\r
1180 \r
1181 // CSciEditContextMenuInterface\r
1182 void CCommitDlg::InsertMenuItems(CMenu& mPopup, int& nCmd)\r
1183 {\r
1184         CString sMenuItemText(MAKEINTRESOURCE(IDS_COMMITDLG_POPUP_PASTEFILELIST));\r
1185         m_nPopupPasteListCmd = nCmd++;\r
1186         mPopup.AppendMenu(MF_STRING | MF_ENABLED, m_nPopupPasteListCmd, sMenuItemText);\r
1187 }\r
1188 \r
1189 bool CCommitDlg::HandleMenuItemClick(int cmd, CSciEdit * pSciEdit)\r
1190 {\r
1191 #if 0\r
1192         if (m_bBlock)\r
1193                 return false;\r
1194         if (cmd == m_nPopupPasteListCmd)\r
1195         {\r
1196                 CString logmsg;\r
1197                 TCHAR buf[MAX_STATUS_STRING_LENGTH];\r
1198                 int nListItems = m_ListCtrl.GetItemCount();\r
1199                 for (int i=0; i<nListItems; ++i)\r
1200                 {\r
1201                         CGitStatusListCtrl::FileEntry * entry = m_ListCtrl.GetListEntry(i);\r
1202                         if (entry->IsChecked())\r
1203                         {\r
1204                                 CString line;\r
1205                                 Git_wc_status_kind status = entry->status;\r
1206                                 if (status == Git_wc_status_unversioned)\r
1207                                         status = Git_wc_status_added;\r
1208                                 if (status == Git_wc_status_missing)\r
1209                                         status = Git_wc_status_deleted;\r
1210                                 WORD langID = (WORD)CRegStdWORD(_T("Software\\TortoiseGit\\LanguageID"), GetUserDefaultLangID());\r
1211                                 if (m_ProjectProperties.bFileListInEnglish)\r
1212                                         langID = 1033;\r
1213                                 GitStatus::GetStatusString(AfxGetResourceHandle(), status, buf, sizeof(buf)/sizeof(TCHAR), langID);\r
1214                                 line.Format(_T("%-10s %s\r\n"), buf, (LPCTSTR)m_ListCtrl.GetItemText(i,0));\r
1215                                 logmsg += line;\r
1216                         }\r
1217                 }\r
1218                 pSciEdit->InsertText(logmsg);\r
1219                 return true;\r
1220         }\r
1221 #endif\r
1222         return false;\r
1223 }\r
1224 \r
1225 void CCommitDlg::OnTimer(UINT_PTR nIDEvent)\r
1226 {\r
1227         switch (nIDEvent)\r
1228         {\r
1229         case ENDDIALOGTIMER:\r
1230                 KillTimer(ENDDIALOGTIMER);\r
1231                 EndDialog(0);\r
1232                 break;\r
1233         case REFRESHTIMER:\r
1234                 if (m_bThreadRunning)\r
1235                 {\r
1236                         SetTimer(REFRESHTIMER, 200, NULL);\r
1237                         ATLTRACE("Wait some more before refreshing\n");\r
1238                 }\r
1239                 else\r
1240                 {\r
1241                         KillTimer(REFRESHTIMER);\r
1242                         ATLTRACE("Refreshing after items dropped\n");\r
1243                         Refresh();\r
1244                 }\r
1245                 break;\r
1246         }\r
1247         __super::OnTimer(nIDEvent);\r
1248 }\r
1249 \r
1250 void CCommitDlg::OnBnClickedHistory()\r
1251 {\r
1252         m_tooltips.Pop();       // hide the tooltips\r
1253         if (m_pathList.GetCount() == 0)\r
1254                 return;\r
1255 #if 0\r
1256         CHistoryDlg historyDlg;\r
1257         historyDlg.SetHistory(m_History);\r
1258         if (historyDlg.DoModal() != IDOK)\r
1259                 return;\r
1260 \r
1261         CString sMsg = historyDlg.GetSelectedText();\r
1262         if (sMsg != m_cLogMessage.GetText().Left(sMsg.GetLength()))\r
1263         {\r
1264                 CString sBugID = m_ProjectProperties.GetBugIDFromLog(sMsg);\r
1265                 if (!sBugID.IsEmpty())\r
1266                 {\r
1267                         SetDlgItemText(IDC_BUGID, sBugID);\r
1268                 }\r
1269                 if (m_ProjectProperties.sLogTemplate.Compare(m_cLogMessage.GetText())!=0)\r
1270                         m_cLogMessage.InsertText(sMsg, !m_cLogMessage.GetText().IsEmpty());\r
1271                 else\r
1272                         m_cLogMessage.SetText(sMsg);\r
1273         }\r
1274 \r
1275         UpdateOKButton();\r
1276         GetDlgItem(IDC_LOGMESSAGE)->SetFocus();\r
1277 #endif\r
1278 }\r
1279 \r
1280 void CCommitDlg::OnBnClickedBugtraqbutton()\r
1281 {\r
1282 #if 0\r
1283         m_tooltips.Pop();       // hide the tooltips\r
1284         CString sMsg = m_cLogMessage.GetText();\r
1285 \r
1286         if (m_BugTraqProvider == NULL)\r
1287                 return;\r
1288 \r
1289         BSTR parameters = m_bugtraq_association.GetParameters().AllocSysString();\r
1290         BSTR commonRoot = SysAllocString(m_pathList.GetCommonRoot().GetDirectory().GetWinPath());\r
1291         SAFEARRAY *pathList = SafeArrayCreateVector(VT_BSTR, 0, m_pathList.GetCount());\r
1292 \r
1293         for (LONG index = 0; index < m_pathList.GetCount(); ++index)\r
1294                 SafeArrayPutElement(pathList, &index, m_pathList[index].GetGitPathString().AllocSysString());\r
1295 \r
1296         BSTR originalMessage = sMsg.AllocSysString();\r
1297         BSTR temp = NULL;\r
1298 \r
1299         // first try the IBugTraqProvider2 interface\r
1300         CComPtr<IBugTraqProvider2> pProvider2 = NULL;\r
1301         HRESULT hr = m_BugTraqProvider.QueryInterface(&pProvider2);\r
1302         if (SUCCEEDED(hr))\r
1303         {\r
1304                 CString common = m_ListCtrl.GetCommonURL(false).GetGitPathString();\r
1305                 BSTR repositoryRoot = common.AllocSysString();\r
1306                 if (FAILED(hr = pProvider2->GetCommitMessage2(GetSafeHwnd(), parameters, repositoryRoot, commonRoot, pathList, originalMessage, &temp)))\r
1307                 {\r
1308                         CString sErr;\r
1309                         sErr.Format(IDS_ERR_FAILEDISSUETRACKERCOM, m_bugtraq_association.GetProviderName(), _com_error(hr).ErrorMessage());\r
1310                         CMessageBox::Show(m_hWnd, sErr, _T("TortoiseGit"), MB_ICONERROR);\r
1311                 }\r
1312                 else\r
1313                         m_cLogMessage.SetText(temp);\r
1314         }\r
1315         else\r
1316         {\r
1317                 // if IBugTraqProvider2 failed, try IBugTraqProvider\r
1318                 CComPtr<IBugTraqProvider> pProvider = NULL;\r
1319                 HRESULT hr = m_BugTraqProvider.QueryInterface(&pProvider);\r
1320                 if (FAILED(hr))\r
1321                 {\r
1322                         CString sErr;\r
1323                         sErr.Format(IDS_ERR_FAILEDISSUETRACKERCOM, (LPCTSTR)m_bugtraq_association.GetProviderName(), _com_error(hr).ErrorMessage());\r
1324                         CMessageBox::Show(m_hWnd, sErr, _T("TortoiseGit"), MB_ICONERROR);\r
1325                         return;\r
1326                 }\r
1327 \r
1328                 if (FAILED(hr = pProvider->GetCommitMessage(GetSafeHwnd(), parameters, commonRoot, pathList, originalMessage, &temp)))\r
1329                 {\r
1330                         CString sErr;\r
1331                         sErr.Format(IDS_ERR_FAILEDISSUETRACKERCOM, m_bugtraq_association.GetProviderName(), _com_error(hr).ErrorMessage());\r
1332                         CMessageBox::Show(m_hWnd, sErr, _T("TortoiseGit"), MB_ICONERROR);\r
1333                 }\r
1334                 else\r
1335                         m_cLogMessage.SetText(temp);\r
1336         }\r
1337 \r
1338         m_cLogMessage.SetFocus();\r
1339 \r
1340         SysFreeString(temp);\r
1341 #endif\r
1342 }\r
1343 \r
1344 LRESULT CCommitDlg::OnGitStatusListCtrlCheckChanged(WPARAM, LPARAM)\r
1345 {\r
1346         UpdateOKButton();\r
1347         return 0;\r
1348 }\r
1349 \r
1350 void CCommitDlg::UpdateOKButton()\r
1351 {\r
1352 #if 0\r
1353         BOOL bValidLogSize = FALSE;\r
1354 \r
1355     if (m_cLogMessage.GetText().GetLength() >= m_ProjectProperties.nMinLogSize)\r
1356                 bValidLogSize = !m_bBlock;\r
1357 \r
1358         LONG nSelectedItems = m_ListCtrl.GetSelected();\r
1359         DialogEnableWindow(IDOK, bValidLogSize && nSelectedItems>0);\r
1360 #endif\r
1361 }\r
1362 \r
1363 \r
1364 LRESULT CCommitDlg::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)\r
1365 {\r
1366         switch (message) {\r
1367         case WM_NOTIFY:\r
1368                 if (wParam == IDC_SPLITTER)\r
1369                 { \r
1370                         SPC_NMHDR* pHdr = (SPC_NMHDR*) lParam;\r
1371                         DoSize(pHdr->delta);\r
1372                 }\r
1373                 break;\r
1374         }\r
1375 \r
1376         return __super::DefWindowProc(message, wParam, lParam);\r
1377 }\r
1378 \r
1379 void CCommitDlg::SetSplitterRange()\r
1380 {\r
1381         if ((m_ListCtrl)&&(m_cLogMessage))\r
1382         {\r
1383                 CRect rcTop;\r
1384                 m_cLogMessage.GetWindowRect(rcTop);\r
1385                 ScreenToClient(rcTop);\r
1386                 CRect rcMiddle;\r
1387                 m_ListCtrl.GetWindowRect(rcMiddle);\r
1388                 ScreenToClient(rcMiddle);\r
1389                 if (rcMiddle.Height() && rcMiddle.Width())\r
1390                         m_wndSplitter.SetRange(rcTop.top+60, rcMiddle.bottom-80);\r
1391         }\r
1392 }\r
1393 \r
1394 void CCommitDlg::DoSize(int delta)\r
1395 {\r
1396         RemoveAnchor(IDC_MESSAGEGROUP);\r
1397         RemoveAnchor(IDC_LOGMESSAGE);\r
1398         RemoveAnchor(IDC_SPLITTER);\r
1399         RemoveAnchor(IDC_SIGNOFF);\r
1400         RemoveAnchor(IDC_COMMIT_AMEND);\r
1401         RemoveAnchor(IDC_LISTGROUP);\r
1402         RemoveAnchor(IDC_FILELIST);\r
1403         CSplitterControl::ChangeHeight(&m_cLogMessage, delta, CW_TOPALIGN);\r
1404         CSplitterControl::ChangeHeight(GetDlgItem(IDC_MESSAGEGROUP), delta, CW_TOPALIGN);\r
1405         CSplitterControl::ChangeHeight(&m_ListCtrl, -delta, CW_BOTTOMALIGN);\r
1406         CSplitterControl::ChangeHeight(GetDlgItem(IDC_LISTGROUP), -delta, CW_BOTTOMALIGN);\r
1407         CSplitterControl::ChangePos(GetDlgItem(IDC_SIGNOFF),0,delta);\r
1408         CSplitterControl::ChangePos(GetDlgItem(IDC_COMMIT_AMEND),0,delta);\r
1409         AddAnchor(IDC_MESSAGEGROUP, TOP_LEFT, TOP_RIGHT);\r
1410         AddAnchor(IDC_LOGMESSAGE, TOP_LEFT, TOP_RIGHT);\r
1411         AddAnchor(IDC_SPLITTER, TOP_LEFT, TOP_RIGHT);\r
1412         AddAnchor(IDC_LISTGROUP, TOP_LEFT, BOTTOM_RIGHT);\r
1413         AddAnchor(IDC_FILELIST, TOP_LEFT, BOTTOM_RIGHT);\r
1414         AddAnchor(IDC_SIGNOFF,TOP_RIGHT);\r
1415         AddAnchor(IDC_COMMIT_AMEND,TOP_LEFT);\r
1416         ArrangeLayout();\r
1417         // adjust the minimum size of the dialog to prevent the resizing from\r
1418         // moving the list control too far down.\r
1419         CRect rcLogMsg;\r
1420         m_cLogMessage.GetClientRect(rcLogMsg);\r
1421         SetMinTrackSize(CSize(m_DlgOrigRect.Width(), m_DlgOrigRect.Height()-m_LogMsgOrigRect.Height()+rcLogMsg.Height()));\r
1422 \r
1423         SetSplitterRange();\r
1424         m_cLogMessage.Invalidate();\r
1425         GetDlgItem(IDC_LOGMESSAGE)->Invalidate();\r
1426 }\r
1427 \r
1428 void CCommitDlg::OnSize(UINT nType, int cx, int cy)\r
1429 {\r
1430     // first, let the resizing take place\r
1431     __super::OnSize(nType, cx, cy);\r
1432 \r
1433     //set range\r
1434     SetSplitterRange();\r
1435 }\r
1436 \r
1437 \r
1438 void CCommitDlg::OnBnClickedSignOff()\r
1439 {\r
1440         // TODO: Add your control notification handler code here\r
1441         CString str;\r
1442         CString username;\r
1443         CString email;\r
1444         username=g_Git.GetUserName();\r
1445         email=g_Git.GetUserEmail();\r
1446         username.Remove(_T('\n'));\r
1447         email.Remove(_T('\n'));\r
1448         str.Format(_T("Signed-off-by: %s <%s>\n"),username,email);\r
1449 \r
1450         m_cLogMessage.SetText(m_cLogMessage.GetText()+_T("\r\n\r\n")+str);\r
1451 }\r
1452 \r
1453 void CCommitDlg::OnStnClickedCommitlabel()\r
1454 {\r
1455         // TODO: Add your control notification handler code here\r
1456 }\r
1457 \r
1458 void CCommitDlg::OnBnClickedCommitAmend()\r
1459 {\r
1460     // TODO: Add your control notification handler code here\r
1461 }\r