OSDN Git Service

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