// PercentPrinter.cpp #include "StdAfx.h" #include "../../../Common/IntToString.h" #include "PercentPrinter.h" static const unsigned kPercentsSize = 4; CPercentPrinter::~CPercentPrinter() { ClosePrint(false); } void CPercentPrinterState::ClearCurState() { Completed = 0; Total = ((UInt64)(Int64)-1); Files = 0; Command.Empty(); FileName.Empty(); } void CPercentPrinter::ClosePrint(bool needFlush) { unsigned num = _printedString.Len(); if (num != 0) { unsigned i; /* '\r' in old MAC OS means "new line". So we can't use '\r' in some systems */ #ifdef _WIN32 char *start = _temp.GetBuf(num + 2); char *p = start; *p++ = '\r'; for (i = 0; i < num; i++) *p++ = ' '; *p++ = '\r'; #else char *start = _temp.GetBuf(num * 3); char *p = start; for (i = 0; i < num; i++) *p++ = '\b'; for (i = 0; i < num; i++) *p++ = ' '; for (i = 0; i < num; i++) *p++ = '\b'; #endif *p = 0; _temp.ReleaseBuf_SetLen((unsigned)(p - start)); *_so << _temp; } if (needFlush) _so->Flush(); _printedString.Empty(); } void CPercentPrinter::GetPercents() { char s[32]; unsigned size; { char c = '%'; UInt64 val = 0; if (Total == (UInt64)(Int64)-1) { val = Completed >> 20; c = 'M'; } else if (Total != 0) val = Completed * 100 / Total; ConvertUInt64ToString(val, s); size = (unsigned)strlen(s); s[size++] = c; s[size] = 0; } while (size < kPercentsSize) { _s += ' '; size++; } _s += s; } void CPercentPrinter::Print() { DWORD tick = 0; if (_tickStep != 0) tick = GetTickCount(); bool onlyPercentsChanged = false; if (!_printedString.IsEmpty()) { if (_tickStep != 0 && (UInt32)(tick - _prevTick) < _tickStep) return; CPercentPrinterState &st = *this; if (_printedState.Command == st.Command && _printedState.FileName == st.FileName && _printedState.Files == st.Files) { if (_printedState.Total == st.Total && _printedState.Completed == st.Completed) return; onlyPercentsChanged = true; } } _s.Empty(); GetPercents(); if (onlyPercentsChanged && _s == _printedPercents) return; _printedPercents = _s; if (Files != 0) { char s[32]; ConvertUInt64ToString(Files, s); // unsigned size = (unsigned)strlen(s); // for (; size < 3; size++) _s += ' '; _s += ' '; _s += s; // _s += "f"; } if (!Command.IsEmpty()) { _s += ' '; _s += Command; } if (!FileName.IsEmpty() && _s.Len() < MaxLen) { _s += ' '; _tempU = FileName; _so->Normalize_UString(_tempU); StdOut_Convert_UString_to_AString(_tempU, _temp); if (_s.Len() + _temp.Len() > MaxLen) { unsigned len = FileName.Len(); for (; len != 0;) { unsigned delta = len / 8; if (delta == 0) delta = 1; len -= delta; _tempU = FileName; _tempU.Delete(len / 2, _tempU.Len() - len); _tempU.Insert(len / 2, L" . "); _so->Normalize_UString(_tempU); StdOut_Convert_UString_to_AString(_tempU, _temp); if (_s.Len() + _temp.Len() <= MaxLen) break; } if (len == 0) _temp.Empty(); } _s += _temp; } if (_printedString != _s) { ClosePrint(false); *_so << _s; if (NeedFlush) _so->Flush(); _printedString = _s; } _printedState = *this; if (_tickStep != 0) _prevTick = tick; }