OSDN Git Service

Fix ProgressDlg Sometime thread is dead blocked.
[tortoisegit/TortoiseGitJp.git] / src / TortoiseProc / ProgressDlg.cpp
1 // ProgressDlg.cpp : implementation file\r
2 //\r
3 \r
4 #include "stdafx.h"\r
5 #include "TortoiseProc.h"\r
6 #include "ProgressDlg.h"\r
7 #include "Git.h"\r
8 #include "atlconv.h"\r
9 // CProgressDlg dialog\r
10 \r
11 IMPLEMENT_DYNAMIC(CProgressDlg, CResizableStandAloneDialog)\r
12 \r
13 CProgressDlg::CProgressDlg(CWnd* pParent /*=NULL*/)\r
14         : CResizableStandAloneDialog(CProgressDlg::IDD, pParent), m_bShowCommand(true)\r
15 {\r
16 \r
17 }\r
18 \r
19 CProgressDlg::~CProgressDlg()\r
20 {\r
21         if(m_pThread != NULL)\r
22         {\r
23                 delete m_pThread;\r
24         }\r
25 }\r
26 \r
27 void CProgressDlg::DoDataExchange(CDataExchange* pDX)\r
28 {\r
29         CDialog::DoDataExchange(pDX);\r
30         DDX_Control(pDX, IDC_CURRENT, this->m_CurrentWork);\r
31         DDX_Control(pDX, IDC_TITLE_ANIMATE, this->m_Animate);\r
32         DDX_Control(pDX, IDC_RUN_PROGRESS, this->m_Progress);\r
33         DDX_Control(pDX, IDC_LOG, this->m_Log);\r
34 }\r
35 \r
36 \r
37 BEGIN_MESSAGE_MAP(CProgressDlg, CResizableStandAloneDialog)\r
38         ON_MESSAGE(MSG_PROGRESSDLG_UPDATE_UI, OnProgressUpdateUI)\r
39 END_MESSAGE_MAP()\r
40 \r
41 BOOL CProgressDlg::OnInitDialog()\r
42 {\r
43         CResizableStandAloneDialog::OnInitDialog();\r
44 \r
45         AddAnchor(IDC_TITLE_ANIMATE, TOP_LEFT, TOP_RIGHT);\r
46         AddAnchor(IDC_RUN_PROGRESS, TOP_LEFT,TOP_RIGHT);\r
47         AddAnchor(IDC_LOG, TOP_LEFT,BOTTOM_RIGHT);\r
48 \r
49         AddAnchor(IDOK,BOTTOM_RIGHT);\r
50         AddAnchor(IDCANCEL,BOTTOM_RIGHT);\r
51 \r
52         m_Animate.Open(IDR_DOWNLOAD);\r
53         \r
54         CString InitialText;\r
55         if ( !m_PreText.IsEmpty() )\r
56         {\r
57                 InitialText = m_PreText + _T("\r\n");\r
58         }\r
59         if (m_bShowCommand)\r
60         {\r
61                 InitialText += m_GitCmd+_T("\r\n\r\n");\r
62         }\r
63         m_Log.SetWindowTextW(InitialText);\r
64         m_CurrentWork.SetWindowTextW(_T(""));\r
65 \r
66         m_pThread = AfxBeginThread(ProgressThreadEntry, this, THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);\r
67         if (m_pThread==NULL)\r
68         {\r
69 //              ReportError(CString(MAKEINTRESOURCE(IDS_ERR_THREADSTARTFAILED)));\r
70         }\r
71         else\r
72         {\r
73                 m_pThread->m_bAutoDelete = FALSE;\r
74                 m_pThread->ResumeThread();\r
75         }\r
76         return TRUE;\r
77 }\r
78 \r
79 UINT CProgressDlg::ProgressThreadEntry(LPVOID pVoid)\r
80 {\r
81         return ((CProgressDlg*)pVoid)->ProgressThread();\r
82 }\r
83 \r
84 UINT CProgressDlg::ProgressThread()\r
85 {\r
86         PROCESS_INFORMATION pi;\r
87         HANDLE hRead;\r
88 \r
89         this->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_START,0);\r
90 \r
91         CString *pfilename;\r
92         if(m_LogFile.IsEmpty())\r
93                 pfilename=NULL;\r
94         else\r
95                 pfilename=&m_LogFile;\r
96 \r
97         g_Git.RunAsync(this->m_GitCmd,&pi, &hRead,pfilename);\r
98 \r
99         DWORD readnumber;\r
100         char buffer[2];\r
101         CString output;\r
102         while(ReadFile(hRead,buffer,1,&readnumber,NULL))\r
103         {\r
104                 buffer[readnumber]=0;\r
105                 this->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_END,(TCHAR)buffer[0]);\r
106         }\r
107 \r
108         CloseHandle(pi.hThread);\r
109 \r
110         WaitForSingleObject(pi.hProcess, INFINITE);\r
111         m_GitStatus =0;\r
112 \r
113         if(!GetExitCodeProcess(pi.hProcess,&m_GitStatus))\r
114         {\r
115                 return GIT_ERROR_GET_EXIT_CODE;\r
116         }\r
117 \r
118         CloseHandle(pi.hProcess);\r
119 \r
120         CloseHandle(hRead);\r
121 \r
122         this->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_END,0);\r
123 \r
124         return 0;\r
125 }\r
126 \r
127 LRESULT CProgressDlg::OnProgressUpdateUI(WPARAM wParam,LPARAM lParam)\r
128 {\r
129         if(wParam == MSG_PROGRESSDLG_START)\r
130         {\r
131                 m_Animate.Play(0,-1,-1);\r
132                 this->DialogEnableWindow(IDOK,FALSE);\r
133         }\r
134         if(wParam == MSG_PROGRESSDLG_END)\r
135         {\r
136                 m_Animate.Stop();\r
137                 m_Progress.SetPos(100);\r
138                 this->DialogEnableWindow(IDOK,TRUE);\r
139         }\r
140 \r
141         if(lParam != 0)\r
142                 ParserCmdOutput((TCHAR)lParam);\r
143 \r
144         return 0;\r
145 }\r
146 int CProgressDlg::FindPercentage(CString &log)\r
147 {\r
148         int s1=log.Find(_T('%'));\r
149         if(s1<0)\r
150                 return -1;\r
151 \r
152         int s2=s1-1;\r
153         for(int i=s1-1;i>=0;i--)\r
154         {\r
155                 if(log[i]>=_T('0') && log[i]<=_T('9'))\r
156                         s2=i;\r
157                 else\r
158                         break;\r
159         }\r
160         return _ttol(log.Mid(s2,s1-s2));\r
161 }\r
162 \r
163 void CProgressDlg::ParserCmdOutput(TCHAR ch)\r
164 {\r
165         TRACE(_T("%c"),ch);\r
166         if( ch == _T('\r') || ch == _T('\n'))\r
167         {\r
168                 TRACE(_T("End Char %s \r\n"),ch==_T('\r')?_T("lf"):_T(""));\r
169                 TRACE(_T("End Char %s \r\n"),ch==_T('\n')?_T("cr"):_T(""));\r
170 \r
171                 CString text;\r
172                 m_Log.GetWindowTextW(text);\r
173                 if(ch == _T('\r'))\r
174                 {\r
175                         RemoveLastLine(text);\r
176                 }\r
177                 text+=_T("\r\n")+m_LogText;\r
178                 m_Log.SetWindowTextW(text);\r
179                 \r
180                 m_Log.LineScroll(m_Log.GetLineCount());\r
181 \r
182                 int s1=m_LogText.Find(_T(':'));\r
183                 int s2=m_LogText.Find(_T('%'));\r
184                 if(s1>0 && s2>0)\r
185                 {\r
186                         this->m_CurrentWork.SetWindowTextW(m_LogText.Left(s1));\r
187                         int pos=FindPercentage(m_LogText);\r
188                         TRACE(_T("Pos %d\r\n"),pos);\r
189                         if(pos>0)\r
190                                 this->m_Progress.SetPos(pos);\r
191                 }\r
192 \r
193                 m_LogText=_T("");\r
194 \r
195         }else\r
196         {\r
197                 m_LogText+=ch;\r
198         }\r
199 \r
200 }\r
201 void CProgressDlg::RemoveLastLine(CString &str)\r
202 {\r
203         int start;\r
204         start=str.ReverseFind(_T('\n'));\r
205         if(start>0)\r
206                 str=str.Left(start);\r
207         return;\r
208 }\r
209 // CProgressDlg message handlers\r