1 // ProgressDlg.cpp : implementation file
5 #include "TortoiseProc.h"
6 #include "ProgressDlg.h"
9 #include "UnicodeUtils.h"
10 // CProgressDlg dialog
12 IMPLEMENT_DYNAMIC(CProgressDlg
, CResizableStandAloneDialog
)
14 CProgressDlg::CProgressDlg(CWnd
* pParent
/*=NULL*/)
15 : CResizableStandAloneDialog(CProgressDlg::IDD
, pParent
), m_bShowCommand(true), m_bAutoCloseOnSuccess(false), m_bAbort(false), m_bDone(false)
18 m_bAltAbortPress
=false;
22 CProgressDlg::~CProgressDlg()
30 void CProgressDlg::DoDataExchange(CDataExchange
* pDX
)
32 CDialog::DoDataExchange(pDX
);
33 DDX_Control(pDX
, IDC_CURRENT
, this->m_CurrentWork
);
34 DDX_Control(pDX
, IDC_TITLE_ANIMATE
, this->m_Animate
);
35 DDX_Control(pDX
, IDC_RUN_PROGRESS
, this->m_Progress
);
36 DDX_Control(pDX
, IDC_LOG
, this->m_Log
);
37 DDX_Control(pDX
, IDC_PROGRESS_BUTTON1
, this->m_ctrlPostCmd
);
41 BEGIN_MESSAGE_MAP(CProgressDlg
, CResizableStandAloneDialog
)
42 ON_MESSAGE(MSG_PROGRESSDLG_UPDATE_UI
, OnProgressUpdateUI
)
43 ON_BN_CLICKED(IDOK
, &CProgressDlg::OnBnClickedOk
)
44 ON_BN_CLICKED(IDC_PROGRESS_BUTTON1
,&CProgressDlg::OnBnClickedButton1
)
47 BOOL
CProgressDlg::OnInitDialog()
49 CResizableStandAloneDialog::OnInitDialog();
51 AddAnchor(IDC_TITLE_ANIMATE
, TOP_LEFT
, TOP_RIGHT
);
52 AddAnchor(IDC_RUN_PROGRESS
, TOP_LEFT
,TOP_RIGHT
);
53 AddAnchor(IDC_LOG
, TOP_LEFT
,BOTTOM_RIGHT
);
55 AddAnchor(IDOK
,BOTTOM_RIGHT
);
56 AddAnchor(IDCANCEL
,BOTTOM_RIGHT
);
57 AddAnchor(IDC_PROGRESS_BUTTON1
,BOTTOM_LEFT
);
58 AddAnchor(IDC_CURRENT
,TOP_LEFT
);
60 this->GetDlgItem(IDC_PROGRESS_BUTTON1
)->ShowWindow(SW_HIDE
);
61 m_Animate
.Open(IDR_DOWNLOAD
);
64 if ( !m_PreText
.IsEmpty() )
66 InitialText
= m_PreText
+ _T("\r\n");
69 if (m_bShowCommand
&& (!m_GitCmd
.IsEmpty() ))
71 InitialText
+= m_GitCmd
+_T("\r\n\r\n");
74 m_Log
.SetWindowTextW(InitialText
);
75 m_CurrentWork
.SetWindowTextW(_T(""));
77 EnableSaveRestore(_T("ProgressDlg"));
79 m_pThread
= AfxBeginThread(ProgressThreadEntry
, this, THREAD_PRIORITY_NORMAL
,0,CREATE_SUSPENDED
);
82 // ReportError(CString(MAKEINTRESOURCE(IDS_ERR_THREADSTARTFAILED)));
86 m_pThread
->m_bAutoDelete
= FALSE
;
87 m_pThread
->ResumeThread();
90 if(!m_Title
.IsEmpty())
91 this->SetWindowText(m_Title
);
93 if(m_PostCmdList
.GetCount()>0)
94 m_ctrlPostCmd
.AddEntries(m_PostCmdList
);
99 UINT
CProgressDlg::ProgressThreadEntry(LPVOID pVoid
)
101 return ((CProgressDlg
*)pVoid
)->ProgressThread();
104 //static function, Share with SyncDialog
105 UINT
CProgressDlg::RunCmdList(CWnd
*pWnd
,std::vector
<CString
> &cmdlist
,bool bShowCommand
,CString
*pfilename
,bool *bAbort
,CGitByteArray
*pdata
)
109 PROCESS_INFORMATION pi
;
112 pWnd
->PostMessage(MSG_PROGRESSDLG_UPDATE_UI
,MSG_PROGRESSDLG_START
,0);
117 for(int i
=0;i
<cmdlist
.size();i
++)
119 if(cmdlist
[i
].IsEmpty())
125 str
+= cmdlist
[i
]+_T("\n\n");
126 for(int j
=0;j
<str
.GetLength();j
++)
130 pdata
->m_critSec
.Lock();
131 pdata
->push_back(str
[j
]);
132 pdata
->m_critSec
.Unlock();
135 pWnd
->PostMessage(MSG_PROGRESSDLG_UPDATE_UI
,MSG_PROGRESSDLG_RUN
,str
[j
]);
138 pWnd
->PostMessage(MSG_PROGRESSDLG_UPDATE_UI
,MSG_PROGRESSDLG_RUN
,0);
141 g_Git
.RunAsync(cmdlist
[i
],&pi
, &hRead
,pfilename
);
146 while(ReadFile(hRead
,&byte
,1,&readnumber
,NULL
))
153 pdata
->m_critSec
.Lock();
154 pdata
->push_back( byte
);
155 pdata
->m_critSec
.Unlock();
157 if(byte
== '\r' || byte
== '\n')
158 pWnd
->PostMessage(MSG_PROGRESSDLG_UPDATE_UI
,MSG_PROGRESSDLG_RUN
,0);
160 pWnd
->PostMessage(MSG_PROGRESSDLG_UPDATE_UI
,MSG_PROGRESSDLG_RUN
,byte
);
163 CloseHandle(pi
.hThread
);
165 WaitForSingleObject(pi
.hProcess
, INFINITE
);
168 if(!GetExitCodeProcess(pi
.hProcess
,&status
) || *bAbort
)
170 CloseHandle(pi
.hProcess
);
174 pWnd
->PostMessage(MSG_PROGRESSDLG_UPDATE_UI
,MSG_PROGRESSDLG_FAILED
,0);
175 return GIT_ERROR_GET_EXIT_CODE
;
180 CloseHandle(pi
.hProcess
);
184 pWnd
->PostMessage(MSG_PROGRESSDLG_UPDATE_UI
,MSG_PROGRESSDLG_END
,0);
190 UINT
CProgressDlg::ProgressThread()
193 m_GitCmdList
.push_back(m_GitCmd
);
197 if(m_LogFile
.IsEmpty())
200 pfilename
=&m_LogFile
;
202 m_GitStatus
= RunCmdList(this,m_GitCmdList
,m_bShowCommand
,pfilename
,&m_bAbort
,&this->m_Databuf
);;
206 LRESULT
CProgressDlg::OnProgressUpdateUI(WPARAM wParam
,LPARAM lParam
)
208 if(wParam
== MSG_PROGRESSDLG_START
)
211 m_Animate
.Play(0,-1,-1);
212 this->DialogEnableWindow(IDOK
,FALSE
);
214 if(wParam
== MSG_PROGRESSDLG_END
|| wParam
== MSG_PROGRESSDLG_FAILED
)
218 m_Databuf
.m_critSec
.Lock();
219 m_Databuf
.push_back(0);
220 m_Databuf
.m_critSec
.Unlock();
222 m_Databuf
.m_critSec
.Lock();
223 m_Log
.SetWindowText(Convert2UnionCode((char*)&m_Databuf
[0]));
224 m_Databuf
.m_critSec
.Unlock();
225 m_Log
.LineScroll(m_Log
.GetLineCount() - m_Log
.GetFirstVisibleLine() - 4);
228 m_Databuf
.m_critSec
.Lock();
229 this->m_Databuf
.clear();
230 m_Databuf
.m_critSec
.Unlock();
234 m_Progress
.SetPos(100);
235 this->DialogEnableWindow(IDOK
,TRUE
);
238 err
.Format(_T("\r\nFailed 0x%x(git return wrong reture code at sometime )\r\n"),m_GitStatus
);
239 if(this->m_GitStatus
)
241 //InsertColorText(this->m_Log,err,RGB(255,0,0));
244 InsertColorText(this->m_Log
,_T("\r\nSuccess\r\n"),RGB(0,0,255));
246 if(wParam
== MSG_PROGRESSDLG_END
&& m_GitStatus
== 0)
248 if(m_bAutoCloseOnSuccess
)
251 if(m_PostCmdList
.GetCount() > 0)
253 //GetDlgItem(IDC_PROGRESS_BUTTON1)->SetWindowText(m_changeAbortButtonOnSuccessTo);
254 GetDlgItem(IDC_PROGRESS_BUTTON1
)->ShowWindow(SW_SHOW
);
255 //GetDlgItem(IDCANCEL)->ShowWindow(SW_HIDE);
256 //Set default button is "close" rather than "push"
257 this->SendMessage(WM_NEXTDLGCTL
, (WPARAM
)GetDlgItem(IDOK
)->m_hWnd
, TRUE
);
260 DialogEnableWindow(IDCANCEL
, FALSE
);
263 DialogEnableWindow(IDCANCEL
, FALSE
);
270 m_Databuf
.m_critSec
.Lock();
271 for(int i
=this->m_BufStart
;i
<this->m_Databuf
.size();i
++)
273 char c
= this->m_Databuf
[m_BufStart
];
275 m_Databuf
.m_critSec
.Unlock();
279 m_Databuf
.m_critSec
.Lock();
287 m_Databuf
.m_critSec
.Unlock();
290 ParserCmdOutput((char)lParam
);
295 //static function, Share with SyncDialog
296 int CProgressDlg::FindPercentage(CString
&log
)
298 int s1
=log
.Find(_T('%'));
303 for(int i
=s1
-1;i
>=0;i
--)
305 if(log
[i
]>=_T('0') && log
[i
]<=_T('9'))
310 return _ttol(log
.Mid(s2
,s1
-s2
));
314 void CProgressDlg::ParserCmdOutput(TCHAR ch
)
317 if( ch
== _T('\r') || ch
== _T('\n'))
319 TRACE(_T("End Char %s \r\n"),ch
==_T('\r')?_T("lf"):_T(""));
320 TRACE(_T("End Char %s \r\n"),ch
==_T('\n')?_T("cr"):_T(""));
322 int lines
=m_Log
.GetLineCount();
326 int start
=m_Log
.LineIndex(lines
-1);
327 int length
=m_Log
.LineLength(lines
-1);
328 m_Log
.SetSel( start
,start
+length
);
329 m_Log
.ReplaceSel(m_LogText
);
333 m_Log
.SetSel(m_Log
.GetWindowTextLength(),
334 m_Log
.GetWindowTextLength());
335 m_Log
.ReplaceSel(CString(_T("\r\n"))+m_LogText
);
338 if( lines
> 500 ) //limited log length
340 int end
=m_Log
.LineIndex(1);
342 m_Log
.ReplaceSel(_T(""));
344 m_Log
.LineScroll(m_Log
.GetLineCount());
346 int s1
=m_LogText
.Find(_T(':'));
347 int s2
=m_LogText
.Find(_T('%'));
350 this->m_CurrentWork
.SetWindowTextW(m_LogText
.Left(s1
));
351 int pos
=FindPercentage(m_LogText
);
352 TRACE(_T("Pos %d\r\n"),pos
);
354 this->m_Progress
.SetPos(pos
);
367 void CProgressDlg::ParserCmdOutput(char ch
)
369 ParserCmdOutput(this->m_Log
,this->m_Progress
,this->m_LogTextA
,ch
,&this->m_CurrentWork
);
371 void CProgressDlg::ClearESC(CStringA
&str
)
374 str
.Replace("\033[K","");
376 void CProgressDlg::ParserCmdOutput(CRichEditCtrl
&log
,CProgressCtrl
&progressctrl
,CStringA
&oneline
, char ch
, CWnd
*CurrentWork
)
378 //TRACE(_T("%c"),ch);
381 if( ch
== ('\r') || ch
== ('\n'))
383 TRACE(_T("End Char %s \r\n"),ch
==_T('\r')?_T("lf"):_T(""));
384 TRACE(_T("End Char %s \r\n"),ch
==_T('\n')?_T("cr"):_T(""));
388 int lines
=log
.GetLineCount();
389 g_Git
.StringAppend(&str
,(BYTE
*)oneline
.GetBuffer(),CP_ACP
);
393 int start
=log
.LineIndex(lines
-1);
394 int length
=log
.LineLength(lines
-1);
395 log
.SetSel( start
,start
+length
);
400 log
.SetSel(log
.GetWindowTextLength(),
401 log
.GetWindowTextLength());
402 log
.ReplaceSel(CString(_T("\r\n"))+str
);
405 if( lines
> 500 ) //limited log length
407 int end
=log
.LineIndex(1);
409 log
.ReplaceSel(_T(""));
411 log
.LineScroll(log
.GetLineCount() - log
.GetFirstVisibleLine() - 4);
413 int s1
=oneline
.Find(_T(':'));
414 int s2
=oneline
.Find(_T('%'));
418 CurrentWork
->SetWindowTextW(str
.Left(s1
));
420 int pos
=FindPercentage(str
);
421 TRACE(_T("Pos %d\r\n"),pos
);
423 progressctrl
.SetPos(pos
);
434 void CProgressDlg::RemoveLastLine(CString
&str
)
437 start
=str
.ReverseFind(_T('\n'));
442 // CProgressDlg message handlers
444 void CProgressDlg::OnBnClickedOk()
446 // TODO: Add your control notification handler code here
447 m_Log
.GetWindowText(this->m_LogText
);
451 void CProgressDlg::OnBnClickedButton1()
453 this->EndDialog(IDC_PROGRESS_BUTTON1
+ this->m_ctrlPostCmd
.GetCurrentEntry());
456 void CProgressDlg::OnCancel()
461 CResizableStandAloneDialog::OnCancel();
465 if( g_Git
.m_CurrentGitPi
.hProcess
)
467 if(::GenerateConsoleCtrlEvent(CTRL_C_EVENT
,0))
469 ::WaitForSingleObject(g_Git
.m_CurrentGitPi
.hProcess
,10000);
472 int error
=::GetLastError();
475 HANDLE hProcessHandle
= ::OpenProcess( PROCESS_TERMINATE
, FALSE
,g_Git
.m_CurrentGitPi
.dwProcessId
);
477 if(!::TerminateProcess(hProcessHandle
,-1) )
479 int error
=::GetLastError();
483 ::WaitForSingleObject(g_Git
.m_CurrentGitPi
.hProcess
,10000);
484 CResizableStandAloneDialog::OnCancel();
488 void CProgressDlg::InsertCRLF()
490 m_Databuf
.m_critSec
.Lock();
491 for(int i
=0;i
<m_Databuf
.size();i
++)
493 if(m_Databuf
[i
]==('\n'))
495 if(i
==0 || m_Databuf
[i
-1]!= ('\r'))
497 m_Databuf
.insert(m_Databuf
.begin()+i
,('\r'));
502 m_Databuf
.m_critSec
.Unlock();
505 void CProgressDlg::InsertColorText(CRichEditCtrl
&edit
,CString text
,COLORREF rgb
)
508 edit
.GetDefaultCharFormat(cf
);
510 cf
.dwMask
|=CFM_COLOR
;
512 cf
.dwEffects
|=CFE_BOLD
;
513 cf
.dwEffects
&= ~CFE_AUTOCOLOR
;
514 edit
.SetSel(edit
.GetTextLength()-1,edit
.GetTextLength());
515 edit
.ReplaceSel(text
);
516 edit
.SetSel(edit
.LineIndex(edit
.GetLineCount()-2),edit
.GetTextLength());
517 edit
.SetSelectionCharFormat(cf
);
518 edit
.SetSel(edit
.GetTextLength(),edit
.GetTextLength());
519 edit
.SetDefaultCharFormat(old
);
520 edit
.LineScroll(edit
.GetLineCount() - edit
.GetFirstVisibleLine() - 4);
523 CString
CCommitProgressDlg::Convert2UnionCode(char *buff
, int size
)
530 cmd
=_T("git.exe config i18n.logOutputEncoding");
531 if(g_Git
.Run(cmd
,&output
,CP_ACP
))
535 output
=output
.Tokenize(_T("\n"),start
);
536 cp
=CUnicodeUtils::GetCPCode(output
);
542 for(int i
=0;i
<size
;i
++)
546 if( start
>0 && buff
[i
] =='\n' )
554 g_Git
.StringAppend(&str
, (BYTE
*)buff
, cp
, start
);
555 g_Git
.StringAppend(&str
, (BYTE
*)buff
+start
, CP_ACP
,size
- start
);